2012-05-28 37 views
1

我试图找出这个问题,但没有成功 你能告诉我什么是错?序言deleteall不起作用

% using accumulator 
deleteall(X,Y,Zs) :- deleteall(X,Y, [], Zs). 
deleteall(X, [], Zs, Zs). 
deleteall(X, [X|Xs], Xs, V). 
deleteall(X, [Y|Xs], [Y|Zs], V) :- deleteall(X, Xs, Zs,V). 

回答

0

辛格尔顿变量总是疑神疑鬼,对你来说,什么是V的含义deleteall(X, [X|Xs], Xs, V).

除此之外,我不明白你为什么使用累加器。

您是否分配了未被删除的元素?否则,这里是工作可以用deleteAll ...

deleteall(_, [], []). 
deleteall(X, [X|Xs], Zs) :- !, deleteall(X, Xs, Zs). 
deleteall(X, [Z|Xs], [Z|Zs]) :- deleteall(X, Xs, Zs). 

测试:

?- deleteall(2,[1,2,3,54,2,1,4,2],X). 
X = [1, 3, 54, 1, 4] ; 
false. 
0

从你的代码,它似乎想要基于统一deleteall语义(另一种是删除只使用(==)/ 2)相等的术语。是否所有的列表元素(以及您想要删除的元素)总是在地面上?如果不是,那么只要您想要删除的元素被部分实例化,并且在与其中一个列表元素统一时进一步实例化,您的代码就会失败。您可以通过使用例如双重否定在身体而不是头统一。正如“chac”已经指出的那样,你也离开了选择点。使用cut或if-then-else解决了这个问题。改进代码的另一种方法是将列表移动到第一个参数,从而允许Prolog的第一个参数索引为您提供更好的性能(当然,假设对谓词的调用将实例化第一个参数)。遵循以下这些定义:

delete_all([], _, []). 
delete_all([X|Xs], Y, Zs) :- 
    ( \+ X \= Y -> 
     delete_all(Xs, Y, Zs) 
    ; Zs = [X|Zs0], 
     delete_all(Xs, Y, Zs0) 
    ). 
1

对于纯粹的解决方案,请考虑this answer – note the different argument order

但实际的问题是:什么是错解决方案?

有一种方法,其方式是独一无二的Prolog的回答这个。在其他编程语言中,你必须找出有意义的测试用例。然后,您将使用这些测试用例来查看您的实现是否有效。当然,在Prolog中也是如此。

不过想想实际成本弄清楚这些测试用例!你必须全面了解整个关系。你将不得不精心打印精神上存在的数据结构。这是相当智力的努力。你的例子非常简单,所以这个努力似乎很小。但想象一下在这里和那里添加的更多细节。

那么怎样才能找出一个测试用例谓语不理解实际的关系?

只需采取最一般的查询。也就是说,在所有参数中都有一个具有不同变量的目标对于你的例子,那将是deleteall(X, Xs, Ys)。现在,我们的工作已经完成,我们可以让Prolog填补空白。

 
?- deleteall(X,Xs,Ys). 
Xs = Ys, Ys = [] ; 
Xs = [X] ; 
false. 

根据您的定义,我们得到两个答案。第一个答案包含Xs为空列表[]的解决方案。第二个答案包含Xs是一个元素列表的解决方案。这就是你所有的关系描述。

包含两个或更多元素的列表如何?他们没有解决方案。所以,你的定义在这方面太具体了。

第二个答案适用于所有Ys。例如。根据你的定义,deleteall(1,[1],[2,3])也保留–。更糟糕的是:deleteall(1,[1],[1]).根本没有删除。所以你的定义太笼统了。


这是怎么回事?那么,你必须编写纯粹的单调程序。也就是说,不得使用不完整的内置插件,如!/0,(\+)/1,(\=)/2,(\==)/2,并且不得使用(或非常特别小心地使用)内置插件。