2014-11-21 35 views
5

我試圖做一個函數,將可變長度的列表按順序分成三個長度均勻的列表。以下內容將其分成三部分,但進程會一次將它們插入到每個列表中。使用Prolog將單個列表拆分爲三個

的我想要的一個例子是:

[1, 2, 3, 4, 5] -> [1, 2], [3, 4], [5] 

另一個例子是:

div([], [], [], []). 
div([X], [X], [], []). 
div([X,Y], [X], [Y], []). 
div([X,Y,Z|End], [X|XEnd], [Y|YEnd], [Z|ZEnd]):- 
    div(End, XEnd, YEnd, ZEnd). 

[8, 7, 6, 5, 4, 3, 2, 1] -> [8, 7, 6], [5, 4, 3], [2, 1]. 

下面的代碼通過一次插入到每個列表中的一個分裂他們

此代碼輸出:

[1, 2, 3, 4, 5] -> [1, 4], [2, 5], [3] 

我該如何解決這個問題?

回答

5

@Boris的回答在第一個參數列表的長度未知時不會終止。看到這一點,就沒有必要看任何進一步的比用第一個目標:

 
div(L, L1, L2, L3) :- 
    length(L, Len), false, 
    % here you compute for example Len1 and Len2 
    length(L1, Len1), 
    length(L2, Len2), 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 

在另一方面,原來的程序有quite nice termination properties。 CTI提供了以下最佳的終止性質:

div(A,B,C,D) terminates_if b(A);b(B);b(C);b(D). 

換句話說,確保終止,你只需要一個參數(或ABCD)是一個具體的列表是有限的,地(這就是b(..)的含義)。這是一個非常強大的終止條件。真的很可惜,這些論點不合適!爲什麼不推廣你的程序?唯一的問題是它限制了列表元素。因此,我將通過_小號替換列表元素的所有變量名:

gdiv([], [], [], []). 
gdiv([_], [_], [], []). 
gdiv([_,_], [_], [_], []). 
gdiv([_,_,_|End], [_|XEnd], [_|YEnd], [_|ZEnd]):- 
    gdiv(End, XEnd, YEnd, ZEnd). 

very same終止性質保持這個程序。

唉,現在有點太籠統了。鮑里斯的解決方案,現在可以改變用途:

divnew(Zs, As, Bs, Cs) :- 
    gdiv(Zs, As, Bs, Cs), 
    append(As, BsCs, Zs), 
    append(Bs, Cs, BsCs). 

我要表達同樣的首選方式寧願:

divnew(Zs, As, Bs, Cs) :- 
    gdiv(Zs, As, Bs, Cs), 
    phrase((seq(As), seq(Bs), seq(Cs)), Zs). 

seq//1定義見other answers

+0

謝謝@false。我也明白你在這個問題之外想要告訴我什麼。 – Mocking 2016-04-15 05:26:27

2
div(L, L1, L2, L3) :- 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 

你看這是如何分割三個列表?現在你沒有說你期望列表L1L2L3是多長。如果您不希望謂詞像現在一樣普遍,則可以使用length/2來獲得L的長度並設置三個結果的長度。由於你說的「相對均勻的長度」,這是相對的,我需要以某種方式解釋它,假設你的意思是,對於一個正整數len和n,len = 3n,你得到len1 = len2 = len3 = len2 = len2 = len3 = len2 = len3 = len3 = len2 = len3 = n,對於k = 3n + 1,你得到len1 = n + 1,len2 = len3 = n,對於k = 3n + 2,你得到len1 = len2 = n + 1,len3 = n。我讓你弄清楚如何計算長度。

div(L, L1, L2, L3) :- 
    length(L, Len), 
    % here you compute for example Len1 and Len2 
    length(L1, Len1), 
    length(L2, Len2), 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 
+0

我不是100%確定,但我認爲你誤解了我的問題。我試圖將第一個列表分成3個列表。 – Mocking 2014-11-21 09:36:50

+0

@Mocking你真的嘗試過這個謂詞嗎?此外,仍然不清楚是否對結果列表的長度有任何限制。 – 2014-11-21 09:38:33

+0

對不起,我試圖讓我的問題更清楚。我試圖將可變長度的列表分成3個甚至(或相對均勻)的列表。這實際上有助於這種情況嗎? – Mocking 2014-11-21 09:46:22