2012-05-28 61 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,並且不得使用(或非常特別小心地使用)內置插件。