List Prolog-统计列表中的重复次数

List Prolog-统计列表中的重复次数,list,prolog,clpfd,meta-predicate,List,Prolog,Clpfd,Meta Predicate,我试图通过一个列表来计算一个给定单词出现的次数。到目前为止,我已经做到了: count_repetitions([_], [], 0). count_repetitions([Word], [Word|Tail], Count):- count_repetitions([Word], Tail, X), Count is X + 1. count_repetitions([Word], [Z|Tail], Count):- Word \= Z, count_repet

我试图通过一个列表来计算一个给定单词出现的次数。到目前为止,我已经做到了:

count_repetitions([_], [], 0).
count_repetitions([Word], [Word|Tail], Count):-
   count_repetitions([Word], Tail, X), 
   Count is X + 1.
count_repetitions([Word], [Z|Tail], Count):-
   Word \= Z, 
   count_repetitions([Word], Tail, Count).
因此查询
?-count\u重复([yes],[yes,and,yes,and,no],X)。
将给出
X=2


这似乎有效。现在我需要编写一个谓词,以
X=[(yes-2)]
的形式输出一个包含搜索词及其出现次数的列表。我完全被卡住了,有什么建议吗?

在我看来,你已经在那里了。您可以简单地用另一个谓词包装您的谓词:

word_repetitions(Word, List, [(Word-Count)]) :-
    count_repetitions(Word, List, Count).
请注意,
字数对周围不需要括号或括号:

word_repetitions(Word, List, Word-Count) :-
    count_repetitions(Word, List, Count).
(但如果你坚持的话,你可以使用它们)

在原始谓词上,重命名以反映差异:

list_word_reps([], Word, Word-0).
list_word_reps([W|Rest], Word, Word-Reps) :-
    list_word_reps(Rest, Word, Word-Reps0),
    (   W == Word
    ->  Reps is Reps0 + 1
    ;   Reps = Reps0
    ).

?- list_word_reps([yes,no,yes,no,maybe,yes], yes, X).
X = yes-3.

列表出现在单词之前的原因是谓词随后变得具有确定性。使用if-then-else而不是两个不同的子句也是如此。如果你愿意的话,你可以把答案放在一个列表中(只需将参数括在括号中),但同样,这是不必要的。

在我看来,你已经在那里了。您可以简单地用另一个谓词包装您的谓词:

word_repetitions(Word, List, [(Word-Count)]) :-
    count_repetitions(Word, List, Count).
请注意,
字数对周围不需要括号或括号:

word_repetitions(Word, List, Word-Count) :-
    count_repetitions(Word, List, Count).
(但如果你坚持的话,你可以使用它们)

在原始谓词上,重命名以反映差异:

list_word_reps([], Word, Word-0).
list_word_reps([W|Rest], Word, Word-Reps) :-
    list_word_reps(Rest, Word, Word-Reps0),
    (   W == Word
    ->  Reps is Reps0 + 1
    ;   Reps = Reps0
    ).

?- list_word_reps([yes,no,yes,no,maybe,yes], yes, X).
X = yes-3.

列表出现在单词之前的原因是谓词随后变得具有确定性。使用if-then-else而不是两个不同的子句也是如此。如果您愿意,可以将答案放入列表中(只需将参数括在括号中),但同样,这是不必要的。

此答案显示了一种逻辑上纯粹的方法。以下是基于

我们定义的
t计数/3

与此问题的所有其他答案所呈现的代码不同,此答案中呈现的代码是单调的,即使与非基本术语一起使用,也在逻辑上保持合理:

?- tcount(=(yes),[A,B,C,D],2).
      A=yes ,     B=yes , dif(C,yes), dif(D,yes)
;     A=yes , dif(B,yes),     C=yes , dif(D,yes)
;     A=yes , dif(B,yes), dif(C,yes),     D=yes
; dif(A,yes),     B=yes ,     C=yes , dif(D,yes)
; dif(A,yes),     B=yes , dif(C,yes),     D=yes
; dif(A,yes), dif(B,yes),     C=yes ,     D=yes
; false.
让我们尝试更一般的方法:

?- tcount(=(yes),[A,B,C,D],Count).
      A=yes ,     B=yes ,     C=yes ,     D=yes , Count = 4
;     A=yes ,     B=yes ,     C=yes , dif(D,yes), Count = 3
;     A=yes ,     B=yes , dif(C,yes),     D=yes , Count = 3
;     A=yes ,     B=yes , dif(C,yes), dif(D,yes), Count = 2
;     A=yes , dif(B,yes),     C=yes ,     D=yes , Count = 3
;     A=yes , dif(B,yes),     C=yes , dif(D,yes), Count = 2
;     A=yes , dif(B,yes), dif(C,yes),     D=yes , Count = 2
;     A=yes , dif(B,yes), dif(C,yes), dif(D,yes), Count = 1
; dif(A,yes),     B=yes ,     C=yes ,     D=yes , Count = 3
; dif(A,yes),     B=yes ,     C=yes , dif(D,yes), Count = 2
; dif(A,yes),     B=yes , dif(C,yes),     D=yes , Count = 2
; dif(A,yes),     B=yes , dif(C,yes), dif(D,yes), Count = 1
; dif(A,yes), dif(B,yes),     C=yes ,     D=yes , Count = 2
; dif(A,yes), dif(B,yes),     C=yes , dif(D,yes), Count = 1
; dif(A,yes), dif(B,yes), dif(C,yes),     D=yes , Count = 1
; dif(A,yes), dif(B,yes), dif(C,yes), dif(D,yes), Count = 0.
下面这件案子怎么样

?- tcount(_,_,-1).
false.
如何利用
t计数/3
作为
length/2
的替代方案

?- N in 1..3, length(Xs,N). N = 1, Xs = [_A] ; N = 2, Xs = [_A,_B] ; N = 3, Xs = [_A,_B,_C] ... % does not terminate ?- use_module(library(lambda)). true. ?- N in 1..3, tcount(\_^ =(true),Xs,N). N = 1, Xs = [_A] ; N = 2, Xs = [_A,_B] ; N = 3, Xs = [_A,_B,_C] ; false. % terminates universally ?-N在1..3中,长度(Xs,N)。 N=1,Xs=[[u A] ; N=2,Xs=[[u A,u B] ; N=3,Xs=[[u A,[u B,[u C] ... % 不终止 ?使用_模块(库(lambda))。 对。 ?-N在1..3中,t计数(\\\^=(true),Xs,N)。 N=1,Xs=[[u A] ; N=2,Xs=[[u A,u B] ; N=3,Xs=[[u A,[u B,[u C] ; 错.%普遍终止
这个答案显示了一种逻辑上纯粹的方法。以下是基于

我们定义的
t计数/3

与此问题的所有其他答案所呈现的代码不同,此答案中呈现的代码是单调的,即使与非基本术语一起使用,也在逻辑上保持合理:

?- tcount(=(yes),[A,B,C,D],2).
      A=yes ,     B=yes , dif(C,yes), dif(D,yes)
;     A=yes , dif(B,yes),     C=yes , dif(D,yes)
;     A=yes , dif(B,yes), dif(C,yes),     D=yes
; dif(A,yes),     B=yes ,     C=yes , dif(D,yes)
; dif(A,yes),     B=yes , dif(C,yes),     D=yes
; dif(A,yes), dif(B,yes),     C=yes ,     D=yes
; false.
让我们尝试更一般的方法:

?- tcount(=(yes),[A,B,C,D],Count).
      A=yes ,     B=yes ,     C=yes ,     D=yes , Count = 4
;     A=yes ,     B=yes ,     C=yes , dif(D,yes), Count = 3
;     A=yes ,     B=yes , dif(C,yes),     D=yes , Count = 3
;     A=yes ,     B=yes , dif(C,yes), dif(D,yes), Count = 2
;     A=yes , dif(B,yes),     C=yes ,     D=yes , Count = 3
;     A=yes , dif(B,yes),     C=yes , dif(D,yes), Count = 2
;     A=yes , dif(B,yes), dif(C,yes),     D=yes , Count = 2
;     A=yes , dif(B,yes), dif(C,yes), dif(D,yes), Count = 1
; dif(A,yes),     B=yes ,     C=yes ,     D=yes , Count = 3
; dif(A,yes),     B=yes ,     C=yes , dif(D,yes), Count = 2
; dif(A,yes),     B=yes , dif(C,yes),     D=yes , Count = 2
; dif(A,yes),     B=yes , dif(C,yes), dif(D,yes), Count = 1
; dif(A,yes), dif(B,yes),     C=yes ,     D=yes , Count = 2
; dif(A,yes), dif(B,yes),     C=yes , dif(D,yes), Count = 1
; dif(A,yes), dif(B,yes), dif(C,yes),     D=yes , Count = 1
; dif(A,yes), dif(B,yes), dif(C,yes), dif(D,yes), Count = 0.
下面这件案子怎么样

?- tcount(_,_,-1).
false.
如何利用
t计数/3
作为
length/2
的替代方案

?- N in 1..3, length(Xs,N). N = 1, Xs = [_A] ; N = 2, Xs = [_A,_B] ; N = 3, Xs = [_A,_B,_C] ... % does not terminate ?- use_module(library(lambda)). true. ?- N in 1..3, tcount(\_^ =(true),Xs,N). N = 1, Xs = [_A] ; N = 2, Xs = [_A,_B] ; N = 3, Xs = [_A,_B,_C] ; false. % terminates universally ?-N在1..3中,长度(Xs,N)。 N=1,Xs=[[u A] ; N=2,Xs=[[u A,u B] ; N=3,Xs=[[u A,[u B,[u C] ... % 不终止 ?使用_模块(库(lambda))。 对。 ?-N在1..3中,t计数(\\\^=(true),Xs,N)。 N=1,Xs=[[u A] ; N=2,Xs=[[u A,u B] ; N=3,Xs=[[u A,[u B,[u C] ; 错.%普遍终止 库(聚合)经常被低估:

count(L, C) :-
    aggregate(set(W-N), aggregate(count, member(W, L), N), C).
屈服

1 ?- count([a,b,a],C).
C = [a-2, b-1].
?- count(a, [a,b,a], C).
C = a-2.
所以,越简单越好

count(W, L, W-N) :-
    aggregate(count, member(W, L), N).
屈服

1 ?- count([a,b,a],C).
C = [a-2, b-1].
?- count(a, [a,b,a], C).
C = a-2.
基于setof,aggregate/3允许对变量的量化进行更精细的控制(即,哪些值被聚合),但如果没有解决方案,则将失败,而不是像有时需要的那样产生0

在这种情况下,基于findall/3的aggregate\u all/3将返回0,但不允许量化说明符。

库(聚合)通常被低估:

count(L, C) :-
    aggregate(set(W-N), aggregate(count, member(W, L), N), C).
屈服

1 ?- count([a,b,a],C).
C = [a-2, b-1].
?- count(a, [a,b,a], C).
C = a-2.
所以,越简单越好

count(W, L, W-N) :-
    aggregate(count, member(W, L), N).
屈服

1 ?- count([a,b,a],C).
C = [a-2, b-1].
?- count(a, [a,b,a], C).
C = a-2.
基于setof,aggregate/3允许对变量的量化进行更精细的控制(即,哪些值被聚合),但如果没有解决方案,则将失败,而不是像有时需要的那样产生0


基于findall/3的aggregate\u all/3在这种情况下将返回0,但不允许使用量化说明符。

感谢您的解决方案Boris。X=[yes-2]对我来说有点输入错误,不必放在括号里。再次感谢!谢谢你的解决方案,鲍里斯。X=[yes-2]对我来说有点输入错误,不必放在括号里。再次感谢!很好的概括,但是名字。好的,是关于一位贵族伯爵的。可能。进一步的沟:
t计数(P\u 1,List,-1)
-这真的应该调用
call(P\u 1,X)
?有一个错误!它应该是
:-meta\u谓词t计数(2,,?)。
@false。Thx 4指出那一点!现在应该更好了。对于长度为(Xs,N)的1..3中的
N的非终止性,这是不好的。
。这是由于length/2建议越来越大的N,但N上的约束禁止在3之后的实例化尝试失败。约束中应该有一些东西告诉length/2,它永远不会以这种方式找到解决方案。很好的泛化,但是名称。好的,是关于一位贵族伯爵的。可能。进一步的沟:
t计数(P\u 1,List,-1)
-这真的应该调用
call(P\u 1,X)
?有一个错误!它应该是
:-meta\u谓词t计数(2,,?)。
@false。Thx 4指出那一点!现在应该更好了。对于长度为(Xs,N)的1..3中的
N的非终止性,这是不好的。
。这是由于length/2建议越来越大的N,但N上的约束禁止在3之后的实例化尝试失败。约束中应该有某种东西告诉length/2它永远不会以这种方式找到解决方案。