我是Prolog的新手而不是母语人士,所以如果你不理解我,我很抱歉。
我的问题是如何才能找到列表中的a
和b
是否同等?
例如,[a,a,b,b]
应该给我true
,但如果其中任何一个看起来比另一个更多,那么它应该给false
。例如:[a,a,a,b,b]
。
有人能帮帮我吗?这是我到目前为止所知道的,但我知道这是错误的,但我正在努力。
count(N,[],0).
count(N,[N|T],U) :-
!,
count(N,T,U1),
U is U1+1.
count(N,[H|T],U) :-
count(N,T,U).
occurrences([],[]).
occurrences([H|T],[[H,X]|Y]) :-
count(H,[H|T],X),
occurrences(T1,Y).
答案 0 :(得分:2)
occurrences([],_A,_B,N,N).
occurrences([H|T],A,B,N0,M0) :-
elem_x_count_(H,A,N1,N0),
elem_x_count_(H,B,M1,M0),
occurrences(T,A,B,N1,M1).
elem_x_count_(E,X,New,Old) :-
if_(E=X, New is Old+1, New=Old).
在此版本中,只有一个递归规则使用elem_x_count_ / 4来增加相应的计数器参数(如果列表的头部分别与A
和B
匹配,或者保持不变。调用谓词保持不变:
occurrences(List,A,B) :-
dif(A,B),
occurrences(List,A,B,0,0).
或
occurrences(List) :-
occurrences(List,a,b,0,0).
这样,如果所有三个参数都是基础的话,谓词就会成功确定(不需要在;
之后按true
,因为没有选择点保持打开状态)。以下是旧版本中带有出现次数/ 3的示例查询:
?- occurrences([a,a,b,b],a,b).
true.
另一个区别是dif / 2约束的数量较少。例如:
?- 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, b),
dif(X, a),
dif(X, Y),
dif(Y, d),
dif(Y, c),
dif(Y, b),
dif(Y, a).
此查询的最后一个解决方案与我以前的版本不同。它描述了相同的结果,但在另一个版本中出现两次的所有差异现在只出现一次。其他示例查询产生相同的答案。
答案 1 :(得分:1)
如果第二个和第三个参数在第一个参数的列表中经常出现,则可以编写谓词出现次数/ 5。第4和第5个参数是相应的计数器。然后谓词出现次数/ 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.
但是,我认为使用谓词出现/ 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) ;
.
.
.
答案 2 :(得分:0)
您可以在访问时从列表'尾部 - 它必须存在 - 中选择匹配元素,而不是计数。
递归基础案例将是您能想到的最简单的... 而select / 3是内置的,可以为您的问题提供真正紧凑的解决方案。
修改的
嗯,代码很简单......
occurrences([],[]).
occurrences([H|T],R) :- select(H,T,U), occurrences(U,R).
注意:成功时,R将成为空列表
答案 3 :(得分:0)
你只有一个列表,所以一开始你的模式匹配会失败顺便说一下我会尝试这样做,我不会添加任何解释,这样你就可以自己弄清楚它是如何工作的。
count(List):-
count(List,0,0).
count([],L,L).
count([H|T],L,R):-
(
H == 'a' ->
NewL is L + 1,
count(T,NewL,R)
)
;
(
H == 'b' ->
NewRight is R + 1,
count(T,L,NewRight)
).