序言:修复多个答案(使用剪切?)

标签 prolog

我正在计算列表中的实例数...

count(_,[],N,N).
count(Elem,[Elem|List],N,M) :- !, N1 is N+1, count(Elem,List,N1,M). 
count(Elem,[_|List],N,M) :- count(Elem,List,N,M). 

所以,我在序言中写了两种方式,第一种有效(上面),但我很想知道为什么第二个没有(或者更确切地说,会给我多个答案 - 只有第一个是正确的)为什么是这个?

非常感谢
count(Z,X,R) :- count2(Z,X,R,0).
count2(W,[H|T],L,A):- (W == H), Lnew is A+1, count2(W,T,L,Lnew).
count2(W,[H|T],L,A):- count2(W,T,L,A).
count2(W,[],A,A).

最佳答案

您的第二次尝试产生多个解决方案的原因是第二个 count2 子句不会阻止 W 和 H 取相同的值。所以即使count2的第一个子句成功,它也可以回溯并在第二个子句上再次成功。

您可以像 Vincent Ramdhanie 所说的那样通过使用剪切来解决此问题,或者如果您希望避免使用剪切,则可以在第二个子句中添加显式检查以防止 W 和 H 统一,如下所示:

count(Z,X,R) :- count2(Z,X,R,0).
count2(W,[W|T],L,A):- Lnew is A+1, count2(W,T,L,Lnew).
count2(W,[H|T],L,A):- W \= H, count2(W,T,L,A).
count2(_,[],A,A).

另请注意,第一个 count2 子句现在使用隐式统一。而不是明确的检查。在我看来,这更短更容易阅读。除非当然有理由使用平等而不是统一。

关于序言:修复多个答案(使用剪切?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1924651/

相关文章:

error-handling - Prolog-如何捕获不正确的Arity错误?

inheritance - 在序言中定义 is_a 谓词?

prolog - Prolog 中的打印路径

recursion - Prolog:删除列表中的所有空格

prolog - 下面代码中的修剪选择点如何使其更加高效(Prolog)?

Prolog:计算列表中的原子数

list - prolog 中列表的所有元素的所有子集

algorithm - 为什么在这种未定义的情况下,我对 Dijkstra 算法的实现会失败?

prolog - 生成元素 (a, b) 的所有可能配对,其中 a 来自集合 A,b 来自 prolog 中的集合 B

prolog - 如何确定约束逻辑编程的查询结果