2012-10-19 125 views
3

我一直在嘗試在給定元素處拆分Prolog。我走近了,但我無法得到列表的左側部分。拆分指定元素的列表

split(X,[Y|L]) :- split(X,[Y|L],[Y|K],M). 
split(_,[],[],[]). 
split(X,[Y|L],K,[Y|M]) :- X < Y, split(X,L,K,M). 
split(X,[Y|L],[Y|K],M) :- X >= Y, split(X,L,K,M). 
split(X,[Y|L],[Y|K],M) :- X = Y, write(Y), write(' '), write(L). 

輸入:

split(2,[1,2,3,4,5]). 

返回:

2 [3,4,5] 

我希望它返回

[1,2] [3,4,5]. 

回答

2

我並不完全確定要在這裏做什麼。例如,split(5, [1,2,3,4,5])應該做什麼?對於這個問題,假設輸入列表被排序是否安全?我會假設如此。

規則split/2的基本問題是您沒有任何輸出參數。 Prolog的工作方式與大多數編程語言不同;沒有return這樣的東西。起初,這感覺像是一個嚴重的限制,但Prolog實際上允許你「返回」儘可能多的結果。看看這段代碼,在我看來你已經完成了一半的理解,因爲你有split/2,它似乎沒有任何輸出參數,但它調用了split/4,它有你需要的兩個輸出參數。

對於初學者,我放棄了split/2的想法,並試圖讓split/4工作。你有什麼不看起來太瘋狂:

?- split(2, [1,2,3,4,5], X, Y). 
X = [1, 2], 
Y = [3, 4, 5] . 

?- split(5, [1,2,3,4,5], X, Y). 
X = [1, 2, 3, 4, 5], 
Y = [] . 

?- split(1, [1,2,3,4,5], X, Y). 
X = [1], 
Y = [2, 3, 4, 5] . 

這表明你的大部分規則是正確的。當你遇到麻煩是與其他解決方案:

?- split(2, [1,2,3,4,5], X, Y). 
... ; 
2 [3,4,5] 
X = [1, 2|_G317] ; 
false. 

?- split(5, [1,2,3,4,5], X, Y). 
... ; 
5 [] 
X = [1, 2, 3, 4, 5|_G326] ; 
false. 

?- split(1, [1,2,3,4,5], X, Y). 
... ; 
1 [2,3,4,5] 
X = [1|_G314]. 

您可以從寫作對那裏由您的最後一個規則,X = Y, write(Y)...等產生這些額外的解決方案,只需刪除該規則看生產中所需的行爲split/4

繼續前進,我想可能不是split/2你實際上想要的是split/3帶有一個輸出參數列表的列表。它不會是太難基礎上,我們至今產生:

split(X, List, [Before, After]) :- split(X, List, Before, After). 

運行它,我們看到我們得到你所提到的期望的結果:

?- split(3, [1,2,3,4,5], X). 
X = [[1, 2, 3], [4, 5]] ; 
false. 

?- split(1, [1,2,3,4,5], X). 
X = [[1], [2, 3, 4, 5]] ; 
false. 

?- split(5, [1,2,3,4,5], X). 
X = [[1, 2, 3, 4, 5], []] ; 
false. 

希望這有助於!

1

我會寫這樣一來,這樣你就可以「重複使用」的斷言,如果你需要一些其他用途的情況下(即寫入輸出流是不是我們需要的,大部分的時間)

split(X, Xs) :- 
    split(X, Xs, L, R), format('~w ~w', [L, R]). 

split(_, [], [], []). 
split(X, [Y|Xs], [], [Y|Xs]) :- 
    X < Y. 
split(X, [X|Xs], [X], Xs). 
split(X, [Y|Xs], [Y|Ls], Rs) :- 
    X > Y, 
    split(X, Xs, Ls, Rs). 

測試

?- split(2,[1,2,3,4,5]). 
[1,2] [3,4,5] 
true ; 
false.