这是我的一项任务的问题:
写
repCount(L, X, N)
当N
是列表X
中L
的出现次数时,这是真的。
这是我的代码,我尝试递归地解决问题:
repCount([], X, N) :-
N is 0.
repCount([H|T], X, N) :-
count([H|T], X, N).
count([], X, 0).
count([H|T], X, N) :-
count(T, X, N1),
X =:= H,
N is N1 + 1.
当我提供一个完整相同数字的列表时,它可以工作:
?- repCount([2,2,2], 2, N).
N = 3.
但是如果我提供一个至少有一个不同值的列表:
?- repCount([2,2,22], 2, N).
false.
返回false
。我无法弄清楚为什么会发生这种情况或如何将其更改为“跳过”非匹配值,而不是将整个事件声明为false。任何意见都表示赞赏。
答案 0 :(得分:4)
count([H|T], X, N):- count(T, X, N1), X=:=H, N is N1 + 1.
这里你声明如果X是H,N应该是N1 + 1;但是你没有定义如果X不是H会发生什么(基本上缺少一个else子句) 这应该有效:
count([H|T], X, N):-
count(T, X, N1),
(X=:=H->
N is N1 + 1
; N is N1).
另一种方式是:
count([H|T], X, N):- count(T, X, N1), X=:=H, N is N1 + 1.
count([H|T], X, N):- X=\=H, count(T, X, N1), N is N1.
但这是低效的,因为如果X不是H,则count(T,X,N1)将被调用两次。我们可以通过在子句的头部进行检查来解决这个问题:
count([H|T], H, N):- count(T, X, N1), N is N1 + 1.
count([H|T], X, N):- count(T, X, N1), N is N1.
或简单地说: count([H | T],H,N): - count(T,X,N1),N是N1 + 1.
count([H|T], X, N1):- X=\=H, count(T, X, N1).
答案 1 :(得分:2)
@magus写的一个有趣的补充:如果你只关心元素的数量而不是元素本身,你可以像这样使用findall / 3:
list_elem_num(Ls, E, N) :-
findall(., member(E, Ls), Ds),
length(Ds, N).
答案 2 :(得分:2)
保留logical-purity - 稍加帮助
meta-predicate tcount/3
和(=)/3
!
目标
tcount(=(X),Es,N)
显示“列表Es中有N个项目等于X”。
示例查询:
?- tcount(=(X), [a,b,c,a,b,c,a,b,a], N). ( N = 4, X=a ; N = 3, X=b ; N = 2, X=c ; N = 0, dif(X,a), dif(X,b), dif(X,c) ). % terminates universally
答案 3 :(得分:1)
但假设您不允许“作弊”,如果您想使用递归,则不需要进行'=='比较..您可以使用Prolog的变量统一来达到同一目的:< / p>
% Job done all instances
repCount2([], _, 0).
% Head unifies with X/2nd parameter - ie X found
repCount2([H|T], H, N) :-
repCount2(T, H, NewN),
N is NewN + 1.
% We got here, so X not found, recurse around
repCount2([_|T], X, N) :-
repCount2(T, X, N).
在第二个谓词中,H被提到两次,这意味着如果列表的头部与X相同,则向下递减,然后在递归的其余部分的结果中加1(以0为结尾 - 基本情况,这是累加器的构建方式。)
答案 4 :(得分:0)
几乎就是......你需要使用累加器,因此:
repCount(Xs,Y,N) :-
count(Xs,Y,0,N) % the 3rd argument is the accumulator for the count, which we seed as 0
.
count([],_,N,N). % if the list is empty, unify the accumulator with the result
count([X|Xs],Y,T,N) :- % if the list is non-empty,
X == Y , % and the head of the list (X) is the the desired value (Y),
T1 is T+1 , % then increment the count, and
count(Xs,Y,T1,N) % recurse down, passing the incremented accumulator
. %
count([X|Xs],Y,T,N) :- % if the list is non-empty,
X \== Y , % and the head of the list(X) is not the desired value (Y),
count(Xs,Y,T,N) % simply recurse down
. %
答案 5 :(得分:0)
最初的问题没有说明你可以使用哪些谓词存在限制。
如果你被允许'作弊'即。使用更高阶的谓词,比如'findall',你可以自己进行递归,这可以在一个谓词中完成:
repCount(L, X, N) :-
findall(X, member(X, L), ListOfX),
length(ListOfX, N).