2013-06-29 70 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).