Prolog任务

时间:2012-02-22 19:17:48

标签: list prolog

这是我的一项任务的问题:

  

repCount(L, X, N)N是列表XL的出现次数时,这是真的。

这是我的代码,我尝试递归地解决问题:

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。任何意见都表示赞赏。

6 个答案:

答案 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)

保留 - 稍加帮助 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).