如果第二个和第三个参数在作为第一个参数的列表中同样频繁地出现,您可以编写一个谓词occurrences/5 为真。第 4 和第 5 个参数是对应的计数器。那么谓词occurrences/1 是调用谓词:
occurrences(List) :-
occurrences(List,a,b,0,0).
occurrences([],_A,_B,N,N).
occurrences([A|Xs],A,B,N0,M) :-
N1 is N0+1,
occurrences(Xs,A,B,N1,M).
occurrences([B|Xs],A,B,N,M0) :-
M1 is M0+1,
occurrences(Xs,A,B,N,M1).
occurrences([X|Xs],A,B,N,M) :-
dif(A,X),
dif(B,X),
occurrences(Xs,A,B,N,M).
您从 0 处的计数器开始,并取决于列表的头部等于A
或B
相应的计数器增加,或者如果头部与两者不同,则不增加计数器。现在让我们看看您给定示例的结果:
?- occurrences([a,a,b,b]).
true ;
false.
?- occurrences([a,a,a,b,b]).
false.
但是,我认为让您指定两个元素的谓词occurrences/3 会更有用:
occurrences(List,A,B) :-
dif(A,B),
occurrences(List,A,B,0,0).
然后您的示例查询将如下所示:
?- occurrences([a,a,b,b],a,b).
true ;
false.
?- occurrences([a,a,a,b,b],a,b).
false.
您还可以询问哪些元素同样经常出现:
?- occurrences([a,a,b,b,c,c,d],X,Y).
X = a,
Y = b ;
X = a,
Y = c ;
X = b,
Y = a ;
X = c,
Y = a ;
X = b,
Y = c ;
X = c,
Y = b ;
dif(X, d),
dif(X, c),
dif(X, c),
dif(X, b),
dif(X, b),
dif(X, a),
dif(X, a),
dif(X, Y),
dif(Y, d),
dif(Y, c),
dif(Y, c),
dif(Y, b),
dif(Y, b),
dif(Y, a),
dif(Y, a).
最后一个解决方案对应于两个根本没有出现在列表中的元素,因为它们都出现的频率相同,即 0 次。如果您想在另一个方向使用谓词,即询问哪些列表使得两个给定元素出现的频率相同,您必须在谓词时为限制列表长度的目标添加前缀打电话,例如:
?- length(L,_),occurrences(L,a,b).
L = [] ;
L = [_G150],
dif(_G150, b),
dif(_G150, a) ;
L = [a, b] ;
L = [b, a] ;
L = [_G116, _G119],
dif(_G116, b),
dif(_G116, a),
dif(_G119, b),
dif(_G119, a) ;
L = [a, b, _G162],
dif(_G162, b),
dif(_G162, a) ;
L = [a, _G159, b],
dif(_G159, b),
dif(_G159, a) ;
L = [b, a, _G162],
dif(_G162, b),
dif(_G162, a) ;
.
.
.