您可以通過重新思考自己的戰略解決這個問題。
首先,你的基本情況是什麼?
在兩個那些案件結束了,你會追加空單,無論你有這麼遠,並呼籲它好。
接下來,您關心的邊緣情況是什麼?
在第一種情況下開始之前,你只是遍歷到輸入列表的末尾。第二,你從輸入列表的開始處開始。
好吧,讓我們嘗試並實現這一點,我將使用累加器並圍繞它打包調用。
sublist(L1, L2, I, J):-
sublist(L1, Temp, I, J, []),
!,
reverse(Temp, L2).
我們採取的輸入列表L1
,一個變量,統一到我們的輸出列表L2
,以及指數,I
和J
。我正在使用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].
*你到目前爲止有什麼問題*?這裏的人不應該給你答案,而是解釋。 – Rubens 2013-05-08 02:26:41
@Rubens哦,對不起,忘了包括。第二個謂詞不起作用。它目前需要'I'和'J'在列表中。 – 2013-05-08 02:34:30