2013-06-29 97 views
1

我想將序言中的列表中的元素移動到同一列表中的新位置,類似於剪切&粘貼操作。在Prolog中移動列表的元素

舉例來說,如果我有列表[1,2,3,4,5]

我想是這樣的:

move(List, D1, D2, D3, Newlist) 

清單=原始列表,D1 =從什麼元素, D2 =列表中的什麼元素,列表中的D3目的地。

一個例子:

move([1,2,3,4,5,6,7,8,9], 1, 3, 5, NewList) :- (Implementation). 

NewList = [4,5,1,2,3,6,7,8,9]. 

我做的,因爲當D3> D2,併爲案件類似的,當D2 D3 <,但我認爲我沒有正確。

% Move D3 > D2 & D2 
move([X|L], D1, D2, D3, Resultado) :- 
    movevalue([X|L], D1, D2, Z), 
    moveinsert([X|L], Z, D3, ParteB), 
    primerapartel([X|L], D3, PrimeraParte), 
    deleting(PrimeraParte, D1, D2, ParteA), 
    append(ParteA, ParteB, Resultado), 
    !. 

movevalue([X|L], D1, D2, Z) :- 
    D1 > 1, 
    E1 is D1 - 1, 
    E2 is D2 - 1, 
    movevalue(L, E1, E2, Z), 
    !. 
movevalue([X|L], 1, D2, [X|Z]) :- 
    D2 > 0, 
    E2 is D2 - 1, 
    movevalue(L, 1, E2, Z). 
movevalue([X|L], 1, 0, Z) :- 
    Z = []. 

moveinsert([X|L], Z, D3, Resultado) :- 
    D3 > 1, 
    E3 is D3 - 1, 
    moveinsert(L, Z, E3, Resultado), 
    !. 
moveinsert([X|L], Z, 1, Resultado) :- 
    append(Z,L,Resultado). 

%append([X],Z,Resultado2) 
%Primera parte L 
primerapartel(_, 0, Resultado) :- 
    Resultado = [], !. 
primerapartel([X|L], N, [X|Resultado]) :- 
    N > 0, 
    N1 is N - 1, 
    primerapartel(L, N1, Resultado), 
    !. 

deleting(Lista, D1, D2, Resultado) :- 
    deletingizq(Lista, D1, D2, ResultadoA), 
    deletingder(Lista, D1, D2, ResultadoB), 
    append(ResultadoA, ResultadoB, Resultado), 
    !. 

deletingizq([Princi|Pal], D1, D2, [Princi|Resultado]) :- 
    D1 > 1, 
    E1 is D1 - 1, 
    E2 is D2 - 1, 
    deletingizq(Pal, E1, E2, Resultado). 
deletingizq([X|L], 1, D2, Resultado) :- 
    D2 > 1, 
    E2 is D2-1, 
    deletingizq(L, 1, E2, Resultado). 
deletingizq([X|L], 1, 1, Resultado) :- 
    Resultado = []. 

deletingder([Princi|Pal], D1, D2, Resultado) :- 
    D1 > 1, 
    E1 is D1 - 1, 
    E2 is D2 - 1, 
    deletingder(Pal, E1, E2, Resultado). 
deletingder([X|L], 1, D2, Resultado) :- 
    D2 > 1, 
    E2 is D2 - 1, 
    deletingder(L, 1, E2, Resultado). 
deletingder([X|L], 1, 1, Resultado) :- 
    Resultado = L. 
+0

從你身邊一些努力? – CapelliC

+0

@CapelliC現在我粘貼了我在其中一個案例中所做的事情,我不需要有人編寫代碼,關於如何以一種好的方式實現它的想法是當我迷路時,我得到一個解決方案,但問題是我認爲這並不是真的最好的辦法,我沒有想到爲了做這件事我花了25行(當做所有的情況),我認爲這可以優化,但我一直在努力與此有關的爲期2天,並沒有得到一個很好的進展,誰在最佳的方式解決它的方式。 非常感謝您的回答:) –

+0

將每個規則完全放在一行上並不能提供非常可讀的代碼。 –

回答

2

您已經找到了Prolog列表不容易處理的困難方法。

爲了使問題更具說明性,因此可以在Prolog中解決,我將在length/2和nth1/3的幫助下將索引與映射分開。

首先,我們知道Result將具有與List相同的長度。執行本:

move(List, Start, Stop, Target, Result) :- 
    length(List, N), 
    length(Result, N), 
    move_elements(1, N, List, Start, Stop, Target, Result). 

四處移動元素需要從列表中映射的索引結果,我們必須爲每個元素做:

/* edit: see the code below - this is buggy  
move_elements(I, N, _List, _Start, _Stop, _Target, _Result) :- 
    I =:= N + 1. 
move_elements(I, N, List, Start, Stop, Target, Result) :- 
    nth1(I, List, E), 
    index_map(I, Start, Stop, Target, P), 
    nth1(P, Result, E), 
    J is I + 1, 
    move_elements(J, N, List, Start, Stop, Target, Result). 
*/ 
move_elements(I, N, List, Start, Stop, Target, Result) :- 
    I =< N, 
    nth1(I, List, E), 
    index_map(I, Start, Stop, Target, P), 
    nth1(P, Result, E), 
    J is I + 1, 
    !, move_elements(J, N, List, Start, Stop, Target, Result). 
move_elements(_I, _N, _List, _Start, _Stop, _Target, _Result). 

我們留下了最困難的部分:index_map 必須做一些算術,在可用的位置之間玩雜耍。我認爲這個問題到目前爲止還有點不確定。這裏只是簡單的情況下,覆蓋你的測試查詢:

index_map(I, Start, Stop, Target, P) :- 
    I >= Start, 
    I =< Stop, 
    P is Target - (Stop - Start + 1) + I. 
index_map(_I, _Start, _Stop, _Target, _P). 

您應該添加更多的測試來指定多個約束,但要注意index_map/5 最後子句允許的Prolog來搜索匹配元素(通過nth1(P, Result, E)),從而以簡單的方式完成映射。

編輯:從foreach/2的幫助,我們才能避免循環

move(List, Start, Stop, Target, Result) :- 
    length(List, N), 
    length(Result, N), 
    foreach(nth1(I, List, E), assign(I, E, Start, Stop, Target, Result)). 

assign(I, E, Start, Stop, Target, Result) :- 
    index_map(I, Start, Stop, Target, P), 
    nth1(P, Result, E).