2

プロローグのリスト内の要素を、カット アンド ペースト操作と同様に、同じリスト内の新しい場所に移動したいと考えています。

たとえば、リスト [1,2,3,4,5] がある場合

私は次のようなものが欲しい:

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

List = 元のリスト、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.
4

1 に答える 1

2

Prolog リストをインデックスで処理するのは簡単ではないという難しい方法を見つけました。

問題をより宣言的にし、Prolog で解決できるようにするために、長さ/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).

要素を移動するには、List から 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)ため、マッピングが簡単な方法で完了することに注意してください。

edit : 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).
于 2013-06-29T08:18:11.907 に答える