2017-03-15 130 views
2

我試圖定義一個謂詞「刪除(L1,L2,L3)」,當L3等於L2減去這些元素中包含的任何元素L1。例如。刪除([1],[1,2,3],X)=>會統一爲X = [2,3]。我的代碼如下:序言:從列表B中刪除列表A中發生的所有元素

isNonElement(_, []). 
isNonElement(X, [Y|Z]) :- X \= Y, isNonElement(X,Z). 

delete(_, [], []). 
delete(Y, [X|W], Z) :- \+(isNonElement(X, Y)), delete(Y, W, Z). 
delete(Y, [X|W], [X|Z]) :- isNonElement(X, Y), delete(Y, W, Z). 

但是它似乎不適用於每個測試用例。任何人都可以幫我解決我的代碼有什麼問題嗎?

在此先感謝!

此致敬禮, Skyfe。

P.S.我不能告訴我的謂詞不能正確工作的情況,因爲它是由學校系統測試的,它不告訴我哪個測試用例失敗。

+0

*減去任何*或減*所有*。你的例子只有一個元素,所以這是在一般情況下告訴你的後果。另外*不要*使用'delete'作爲謂詞名稱。它已經被圖書館謂詞所採用。使用更具體的東西。 – lurker

回答

3

你是非常接近

剩下的一個問題是,你正在應用一個完全合理的邏輯推理來判斷不承認這樣的閱讀。你的代碼工作完全按照預期的,如果你簡單地套用以下的極其直接的變化:中

  1. 代替(\=)/2,使用dif/2
  2. 代替\+(isNonElement(X, Y)),簡單地寫:member(X, Y)

第一次更改總是可取的:它通常會使您的程序在更多方向上可用。第二個改變通過使用純謂詞來避免使用不純否定。

總體而言,我們現在有:

 
isNonElement(_, []). 
isNonElement(X, [Y|Z]) :- dif(X, Y), isNonElement(X,Z). 

delete(_, [], []). 
delete(Y, [X|W], Z)  :- member(X, Y), delete(Y, W, Z). 
delete(Y, [X|W], [X|Z]) :- isNonElement(X, Y), delete(Y, W, Z). 

現在檢查了這一點:首先,你的測試案例:

 
?- delete([1], [1,2,3], X). 
X = [2, 3] ; 
false. 

按預期工作!

其次,具有可變的情況下,爲L2

 
?- delete([], L2, []). 
L2 = [] ; 
false. 

這似乎也是很不錯的。

三,另一個變量:

 
?- delete([X], [1,2,3], Ls3). 
X = 1, 
Ls3 = [2, 3] ; 
X = 2, 
Ls3 = [1, 3] ; 
X = 3, 
Ls3 = [1, 2] ; 
Ls3 = [1, 2, 3], 
dif(X, 3), 
dif(X, 2), 
dif(X, 1) ; 
false. 

注意現在X不同的可能性,並dif/2如何在回答用於表達X必須從某個整數不同在這種情況下, 。

使用不純謂詞排除這樣更通用的用法,並且您的評分系統也可以嘗試這樣的情況。

請注意,您當然可以輕鬆地自己實現member/2。這是最直接的關係之一。然而,還要注意delete/3是可怕的命名:一個勢在必行總是意味着使用一個特定的方向,但我們正在考慮在這裏的關係也承認許多其他用途 模式!

+0

感謝您的詳細解答!替換isNonElement的否定由會員修正。我不允許使用預定義的謂詞,所以我只是重寫它。至於謂詞的名稱,這是我的課程老師的選擇,我不能改變它,但我同意。再次感謝你的幫忙:) – Skyfe

+2

太好了!請注意,初始溶液已經使用預定義的謂詞'(\ +)/ 1'和'(\ =)/ 1',因此採取與一粒鹽這樣的要求。要查看版本之間的一些差異,請考慮以下查詢:'? - delete([X],[a],Z)'。在初始版本中,如果*'X'爲'a',則會得到'Z = []'正確的*,但是否則錯誤!如果使用'構件/ 2'代替不合理的否定,則得到:'X = A,Z = []',它是至少一個*正確*溶液。然而,這是不完整* *,這是因爲其他的解決方案是'Z = [A],DIF(X,一)'。只有'dif/2'給你這個! – mat