在Prolog中移动列表的元素

时间:2013-06-29 03:48:57

标签: list prolog

我想将prolog列表中的元素移动到同一列表中的新位置,类似于cut&粘贴操作。

例如,如果我有列表[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< 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.

1 个答案:

答案 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).

移动元素需要将索引从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搜索匹配的元素(通过{{1} }),从而以简单的方式完成映射。

编辑:在foreach / 2的帮助下,我们可以避免循环

nth1(P, Result, E)