2013-05-08 16 views
2

sublist(L1,L2,I,J)序言 - 提取一個子表

我有一個列表,L1傳遞中,有2個索引IJ一起,我想L2是含有IJ之間的所有元素的包容子表。
如果J超出範圍,我希望它從I到列表的末尾。同樣,如果I小於0,我希望從列表的開始到JI>J返回空列表。

我有什麼至今:

sublist(_,[],I,J):- 
    I > J. 
sublist(Xs,Ys,I,Length):- 
    length(Xs,Length), 
    N > L, 
    sublist(Xs,Ys,I,J). 
sublist([X|_],[X],1,1). 
sublist([X|Xs],[X|Ys],1,J):- 
    J > 1, 
    J1 is J - 1, 
    sublist(Xs,Ys,1,J1). 
sublist([_|Xs],Ys,I,J):- 
    I > 1, 
    I1 is I - 1, 
    J1 is J - 1, 
    sublist(Xs,Ys,I1,J1). 
+0

*你到目前爲止有什麼問題*?這裏的人不應該給你答案,而是解釋。 – Rubens 2013-05-08 02:26:41

+0

@Rubens哦,對不起,忘了包括。第二個謂詞不起作用。它目前需要'I'和'J'在列表中。 – 2013-05-08 02:34:30

回答

4

您可以通過重新思考自己的戰略解決這個問題。

首先,你的基本情況是什麼?

  • 您與空列表作爲輸入
  • I > J

在兩個那些案件結束了,你會追加空單,無論你有這麼遠,並呼籲它好。

接下來,您關心的邊緣情況是什麼?

  • J超出了列表的末尾
  • I是列表

在第一種情況下開始之前,你只是遍歷到輸入列表的末尾。第二,你從輸入列表的開始處開始。

好吧,讓我們嘗試並實現這一點,我將使用累加器並圍繞它打包調用。

sublist(L1, L2, I, J):- 
    sublist(L1, Temp, I, J, []), 
    !, 
    reverse(Temp, L2). 

我們採取的輸入列表L1,一個變量,統一到我們的輸出列表L2,以及指數,IJ。我正在使用cut,這樣我就不必擔心其他解決方案的回溯,並將其反轉,因爲累積列表是反向構建的。

讓我們研究基礎案例。

空的列表作爲輸入,只是將累加器與我們的輸出列表合併。我們現在不關心這些指數。事實證明,這也滿足了J超出列表末尾的邊緣情況。因爲那時我們已經將所有的輸入列表累加到累加器中,並且仍然有一個J值。

sublist([], L2, _I, _J, L2). 

I> J再一次將累加器與我們的輸出列表統一起來。我們不再關心輸入列表。

sublist(_L1, L2, I, J, L2):- 
    I > J. 

現在邊緣案例。

J超出列表的末尾解決了上面。

I在列表開始之前,只需將該索引設置爲0,然後繼續。

sublist(L1, L2, I, J, L2):- 
    I < 0, 
    sublist(L1, L2, 0, J, L2). 

現在我們只需要實現實際的邏輯。我們只想從正確的I開始累計。所以讓我們遞減I並丟棄輸入列表的部分,直到我們到達我們想要的位置。爲了使索引結束,我們還需要減少J。這樣我們在索引之間保持相同的距離。

sublist([_L|Ls], L2, I, J, Acc):- 
    I > 0, 
    sublist(Ls, L2, I-1, J-1, Acc). 

我們終於成爲我們想成爲的地方。那麼,讓我們開始用輸入列表中的部分構建列表。這繼續下去,直到我們遇到我們的基本情況之一。之後,累加器返回原來的sublist子句。

sublist([L|Ls], L2, I, J, Acc):- 
    sublist(Ls, L2, I, J-1, [L|Acc]). 

把所有我們一起結束:

sublist(L1, L2, I, J):- 
    sublist(L1, Temp, I, J, []), 
    !, 
    reverse(Temp, L2). 
sublist([], L2, _I, _J, L2). 
sublist(_L1, L2, I, J, L2):- 
    I > J. 
sublist(L1, L2, I, J, L2):- 
    I < 0, 
    sublist(L1, L2, 0, J, L2). 
sublist([_L|Ls], L2, I, J, Acc):- 
    I > 0, 
    sublist(Ls, L2, I-1, J-1, Acc). 
sublist([L|Ls], L2, I, J, Acc):- 
    sublist(Ls, L2, I, J-1, [L|Acc]). 

,我們可以測試它像這樣:

?- sublist([1,2,3,4,5], S, 0,3). 
S = [1, 2, 3, 4]. 

?- sublist([1,2,3,4,5], S, -1,30). 
S = [1, 2, 3, 4, 5]. 

?- sublist([1,2,3,4,5], S, 3,1). 
S = []. 

?- sublist([1,2,3,4,5], S, 3,3). 
S = [4]. 

?- sublist([1,2,3,4,5], S, 3,4). 
S = [4, 5]. 
+1

+1優秀,深入的答案。稍微關注'is/2'的缺失,但顯然'/2'使用算術表達式。 – 2013-05-08 03:40:49

+0

以自上而下的方式構建結果更具有道德感,它可以被爭論,並且可以/應該一樣直觀。 :)最後也不需要扭轉。 – 2013-05-09 10:21:26

0

我覺得你剛纔在第二個子句一些錯字。試試這個(未經測試的)校正,需要符合你的要求

如果J不在邊界之內,我希望它從I到列表的末尾。

sublist(Xs,Ys,I,J):- 
    length(Xs,Length), 
    J > Length, 
    sublist(Xs,Ys,I,Length).