2016-10-04 30 views
11

(這是對that question的後續處理)。刪除列表中的前導s(s(0))

如何編寫lead1(Xs,Ys)這是真的,如果YsXs的後綴,並刪除了所有前導s(s(0))條款。因此,現在不是刪除前導0,而是現在刪除前導s(s(0))

與原始問題相比,難點在於正確處理s(X)s(s(X))的情況。

+4

「正確處理s(X)和s(s(X))的情況」非常籠統,無助於理解謂詞的行爲,請考慮編輯回答r,添加更多信息... – coder

+0

@coder:這不是規範的一部分。只是爲什麼這個最小的變化是有趣的理由。 – false

+0

我也不明白問題出在哪裏。這個問題肯定需要一些例子來展示爲什麼@TopologicalSort建議是不夠​​的。 – Fatalize

回答

4

下面是與if_/3=/3版本:

list_suffix([],[]). 
list_suffix([X|Xs],S) :- 
    if_(X=s(s(0)), list_suffix(Xs,S), S=[X|Xs]). 

查詢與地面的第一個參數成功確定性:

?- list_suffix([s(0)],S). 
S = [s(0)]. 

?- list_suffix([s(0),s(s(0))],S). 
S = [s(0), s(s(0))]. 

?- list_suffix([s(s(0)),s(0),s(s(0))],S). 
S = [s(0), s(s(0))]. 

?- list_suffix([s(s(0)), s(s(0)),s(0),s(s(0))],S). 
S = [s(0), s(s(0))]. 

如果該列表由來自S/1的不同期限的,說f(_)第二個列表與第一個列表相同:

?- list_suffix([f(_)],S). 
S = [f(_G201)]. 

?- list_suffix([f(_)],[]). 
false. 

部分實例化列表以及工作:

?- list_suffix([X, s(s(0)),s(0),s(s(0))],S). 
X = s(s(0)), 
S = [s(0), s(s(0))] ; 
S = [X, s(s(0)), s(0), s(s(0))], 
dif(X, s(s(0))). 

最一般查詢的工作很好,但被列出的答案是一種不公平的方式:

?- list_suffix(X,Y). 
X = Y, Y = [] ; 
X = [s(s(0))], 
Y = [] ; 
X = [s(s(0)), s(s(0))], 
Y = [] ; 
X = [s(s(0)), s(s(0)), s(s(0))], 
Y = [] ; 
. 
. 
. 

但是,這可以通過在前面一個進球來彌補長度/ 2:

?- length(X,_), list_suffix(X,Y). 
X = Y, Y = [] ; 
X = [s(s(0))], 
Y = [] ; 
X = Y, Y = [_G155], 
dif(_G155, s(s(0))) ; 
X = [s(s(0)), s(s(0))], 
Y = [] ; 
X = [s(s(0)), _G79], 
Y = [_G79], 
dif(_G79, s(s(0))) ; 
X = Y, Y = [_G155, _G158], 
dif(_G155, s(s(0))) ; 
X = [s(s(0)), s(s(0)), s(s(0))], 
Y = [] ; 
. 
. 
. 
+3

更簡單的解決方案,更高效,+1 :) !!! – coder

+2

@coder:謝謝:-D – tas

2

Hiere是我對上一個問題的回答的改編。它顯示了使用when/2而不是freeze/2。凍結/ 2只在第一個參數上有一個非變量/ 1條件。當/ 2可以遵循更復雜的條件時。

lead(X, Y) :- var(X), !, freeze(X, lead(X,Y)). 
lead([X|Y], Z) :- \+ ground(X), !, when(ground(X), lead([X|Y],Z)). 
lead([s(s(0))|X], Y) :- !, lead(X, Y). 
lead(X, X). 

下面是一些示例運行,我選擇了類似的例子,就像我在上一個答案中給出的答案。我們看到,當/ 2適應自身的條件時,列表參數被逐漸實例:

?- lead([s(0),s(s(0)),s(s(0)),s(0)],Y). 
Y = [s(0), s(s(0)), s(s(0)), s(0)]. 

?- lead([s(s(0)),s(s(0)),s(s(0)),s(0)],Y). 
Y = [s(0)]. 

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(_). 
X = s(_G3686), 
when(ground(_G3686), lead([s(_G3686), s(s(0)), s(s(0)), s(0)], Y)). 

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(0). 
X = s(0), 
Y = [s(0), s(s(0)), s(s(0)), s(0)]. 

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(_)). 
X = s(s(_G3713)), 
when(ground(_G3713), lead([s(s(_G3713)), s(s(0)), s(s(0)), s(0)], Y)). 

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)). 
X = s(s(0)), 
Y = [s(0)]. 

凍結/ 2,當/ 2 corouting元。文獻中詳細記載了它們的純度。根據這個source,第一個Prolog系統帶有Corler/2原語的Prolog-II。消息來源還提到了Corouting對引導約束求解器的重要性。

假設純淨與交換性測試,這裏是一個樣本測試:

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)). 
X = s(s(0)), 
Y = [s(0)]. 

?- X=s(s(0)), lead([X,s(s(0)),s(s(0)),s(0)],Y). 
X = s(s(0)), 
Y = [s(0)]. 

但冷凍/ 2當/ 2不necesserely保證完整性,因爲我已經在我的第一個答案寫了,我們可能需要做'最後'。意思是在查詢之後,我們可能會有一系列陷入困境的目標。在約束規劃中,我們將開始標記。

還凍結/ 2,當/ 2無法提前找到失敗時,通過組合目標,因爲約束求解器可以做到。

上述示例運行時沒有導入,而在Jekejeke Prolog中使用SWI-Prolog,並使用Minlog Extension和導入庫(term/suspend)。

+0

所以你不再使用'freeze/2'。 – false

+0

凍結/ 2仍被用在lead/2謂詞的第一個子句中。 freeze/2是when/2的特例,它可以定義爲'freeze(X,G): - when(nonvar(X),G).'。我在回答你的原始問題時已經提到過/ 2,你沒有注意到嗎? –