Prolog移位或旋转元素

use*_*060 1 prolog

我需要prolog中的关系来将列表左移一个元素,这样就可以了

shift([a,b,c,d,e,f,g,h],3,Shifted).
Run Code Online (Sandbox Code Playgroud)

应该产生

Shifted = [d,e,f,g,h,a,b,c]
Run Code Online (Sandbox Code Playgroud)

你可以帮帮我吗?

这就是我所拥有的

shift([], []).
shift([H|T], L) :-
   append(T, [H], L).

shift(0, L, L) :- !.
shift(N, L1, L2) :-
   N1 is N-1,
   shift(L1, L),
   shift(N1, L, L2).
Run Code Online (Sandbox Code Playgroud)

Eug*_*Sh. 6

可能有更有效的解决方案,但Prolog的美妙之处在于,您可以在逻辑上而不是强制性使用它.

什么是逻辑上的转变?L1=Lx || LyN位置移动列表会使列表L2=Ly || Lx的长度Lx完全正确N.(注意:这里||表示连接).我们如何将其翻译成Prolog?直截了当:

shift(L1, N, L2) :- 
    append(Lx, Ly, L1), % L1 is Lx || Ly
    append(Ly, Lx, L2), % L2 is Ly || Lx
    length(Lx, N).      % The length of Lx is N
Run Code Online (Sandbox Code Playgroud)

更新:N OP在评论中指出了额外的负面要求.对于这种情况,需要扩展上述内容.它可以被修改,使得实际的左移位置将是总列表长度减去位置的数量:

shift(L1, N, L2) :-
    N < 0, !,             % this is the case for negative N
    length(L1, Len),
    N1 is Len + N,
    shift(L1, N1, L2).  

shift(L1, N, L2) :- 
    append(Lx, Ly, L1), % L1 is Lx || Ly
    append(Ly, Lx, L2), % L2 is Ly || Lx
    length(Lx, N).      % The length of Lx is N
Run Code Online (Sandbox Code Playgroud)

请注意,这两种实现仅适用于不超过列表长度的N. 如果要处理它的情况,则必须N按模数截断列表的长度.

更新2: 我实际上已经意识到负面情况可以更加明确地实施.它与交换符号和L1与L2相同.因此具体案例可以用以下内容代替

shift(L1, N, L2) :-
    N < 0, !,
    N1 is -N,
    shift(L2, N1, L1).
Run Code Online (Sandbox Code Playgroud)