计算序言列表中特定元素的数量

时间:2012-08-12 16:15:32

标签: lambda prolog logic

我试图计算一个元素出现在列表中的次数,到目前为止我已经提出了

rate(X,[H|T],N):-
  X == H,
  N is N+1,
  rate(X,T,N).
rate(X,[_|T],N) :-
  rate(X,T,N).  
rate(_,[],N) :-
  N is 0.

我找到了匹配的时间,没有匹配时以及到达列表末尾的时间。但是,当我测试我得到

43 ?- rate(4,[4,2,3,4,4,2],X).
ERROR: is/2: Arguments are not sufficiently instantiated
Exception: (6) frequency(4, [4, 2, 3, 4, 4, 2], _G393) ?     

我错过了哪些论据?

3 个答案:

答案 0 :(得分:4)

当且仅当X是数字时,您才能使用is/2(如N is X中所述)。如果X是自由变量,则不能使用is/2。在您的第一个条款中,您有:N is N+1。这很糟糕,因为N是一个自由变量(此时它没有值,N + 1也是如此)。

还有另一个错误。在:

rate(X,[_|T],N) :-
  rate(X,T,N).

因为你只在X不是列表中的第一个元素时使用它,你应该检查这是真的!这是代码:

count(_, [], 0) :- !. /* empty list, base case */

count(X, [X|T], N) :- /* if X is in the head of the list */
    count(X, T, N2), /* count on the tail (let this N2) */
    N is N2 + 1.     /* and N is N2 + 1  */

count(X, [Y|T], N) :- 
    X \= Y,          /* if X is not in the head */
    count(X, T, N).  /* just count the rest */

答案 1 :(得分:2)

你需要使你的条款互相排斥,第二个条款将在第一个条款的任何地方成功。

关于你的错误,它是关于信息的流动。您需要在第一个子句中交换行,如下所示:

rate(X,[H|T],N):-
  X == H,
  rate(X,T,N1),
  N is N1+1.

此更改将使您的谓词尾递归。要进行尾递归,它需要传递 down 调用链中的信息,而不是像现在一样将其接收回来:

rate(X,[H|T],N):-
  X == H,
  N1 is N+1,
  rate(X,T,N1).

现在您看到此处未收到最终值,但指定初始值。当我们达到基本情况时,我们得到了结果:

rate(X, [], N).

此处N是结果。怎么回来?当我们到达底部时,使用附加参数(一个未实例化的变量)与此结果统一:

rate(X, [], N, V) :- V is N.

现在recursive子句必须适应这个变量,沿着不变向下传递给调用链。

答案 2 :(得分:1)

如果您喜欢功能风格,可以使用SWI Prolog编写:

:- use_module(library(lambda)).


rate(X,L,N) :-
    foldl(\Y^V0^V1^((X = Y->V1 is V0+1; V1 = V0)), L, 0, N).