Prolog - 检查出现次数不按预期工作

Prolog - Check number of occurences doesn't work as expected

序言中: 我有以下函数来计算列表中某个元素的出现次数:

%count(L:list,E:int,N:int) (i,i,o)
count([],_,0).
count([H|T],E,C):-H == E,count(T,E,C1),C is C1+1.
count([_|T],E,C):-count(T,E,C).

我测试过,效果很好。但是问题来了,我有另一个功能必须检查“1”在列表中出现的次数是否少于2次。

check(L):-count(L,1,C),C<2.

每当我尝试检查列表 [1,1,1,1] 时,我得到的结果是 "true",这是错误的,我不知道为什么。我试着做了一些修改,但是功能就是不行。

之所以会这样,是因为count([1,1,1,1],1,1)也是如此!在你最后的 count 中,当 H 等于 E 时,它也可以匹配。为了说明这一点,使用 ; 让 prolog 寻找 count([1,1,1,1],1,R) 的更多答案。你会看到会发生什么。

count([],_,0).
count([E|T],E,C):-
    count(T,E,C1),
    C is C1+1.
count([H|T],E,C):-
    H \= E,
    count(T,E,C).

check(L) :- 
    count(L,1,C),
    C < 2.


?- check([1,1,1,1,1]).
false
?- check([1]).
true

第二个和第三个子句头匹配相同的序列。作为最小的更正,我会提交测试

count([],_,0).
count([H|T],E,C):-H == E,!,count(T,E,C1),C is C1+1.
count([_|T],E,C):-count(T,E,C).

改善测试习惯!

测试 Prolog 代码时,不要只查看某些查询的第一个答案并得出结论“有效”。

非确定性 Prolog 的核心。

很多时候,某些代码 乍一看 可以正常工作(当查看第一个答案时),但会出现问题(主要是错误的答案 and/or 非终止)在回溯时。


回到你原来的问题...如果你想/需要保留 , consider using the following minimal variation of the code :

count([],_,0).
count([E|T],E,C) :-
   count(T,E,C1),
   C is C1+1.
count([H|T],E,C) :- 
   dif(H,E),
   count(T,E,C).

dif/2 以合乎逻辑的方式表达句法术语不等式。有关它的信息,请查看 !