Prolog Shift n次列表函数的任意一种方式

Prolog Shift n次列表函数的任意一种方式,prolog,Prolog,我必须定义一个谓词nshift/3,它将列表以任意方式移动N次。 示例: ?- nshift(3,[a,b,c,d,e,f,g,h],Shifted). Shifted = [d,e,f,g,h,a,b,c] ?-­nshift(1,[1,2,3,4,5],Shifted). Shifted = [2,3,4,5,1] ?-­nshift(-2,[a,b,c,d,e,f,g,h],Shifted). Shifted = [g,h,a,b,c,d,e,f] 我创

我必须定义一个谓词nshift/3,它将列表以任意方式移动N次。 示例:

?- nshift(3,[a,b,c,d,e,f,g,h],Shifted). 
  Shifted = [d,e,f,g,h,a,b,c]   
?-­nshift(1,[1,2,3,4,5],Shifted).   
  Shifted = [2,3,4,5,1]
?-­nshift(-2,[a,b,c,d,e,f,g,h],Shifted).    
  Shifted = [g,h,a,b,c,d,e,f]
我创建了一个代码来处理前两个示例,但是最后一个示例中的N时间是-2,我遇到了问题。谁能帮帮我吗。 我的代码:

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

nshift(0, L, L) :- !.
nshift(N, L1, L2) :-
   N1 is N-1,
   my_shift(L1, L),
   nshift(N1, L, L2).
我有这个旧密码

rotate(right, L, [T|H]) :- append(H, [T], L).
rotate(left, [H|T], L) :- append(T, [H], L).
然后,我认为如果第一个参数<0,您可以调整nshift/3测试,比如

nshift(0, L, L) :- !.
nshift(N, L1, L2) :-
  N < 0, rotate(right, L1, L), N1 is N+1, nshift(N1, L, L2).
nshift(N, L1, L2) :-
  N > 0, rotate(left, L1, L), N1 is N-1, nshift(N1, L, L2).
nshift(0,L,L):-!。
N移位(N,L1,L2):-
N<0,旋转(右,L1,L),N1为N+1,N移位(N1,L,L2)。
N移位(N,L1,L2):-
N>0,旋转(左,L1,L),N1为N-1,N移位(N1,L,L2)。

正如另一个答案所暗示的,您的轮班类型通常称为轮班。使用非负N进行旋转可以用一种很好的声明方式编写,如下所示

naive_rotate(N, Xs, Ys) :-
    length(Bs, N),
    append(As, Bs, Xs),
    append(Bs, As, Ys).
虽然这是可行的,但人们会很快指出它的终止属性很差:当您回溯到
rotate/3
,即请求更多解决方案时,它不会终止。这可以通过在列表长度上添加冗余条件来解决,即

rotate(N, Xs, Ys) :-
    same_length(Xs, Ys),
    leq_length(Bs, Xs),
    length(Bs, N),
    append(As, Bs, Xs),
    append(Bs, As, Ys).

  same_length([], []).
  same_length([_|Xs], [_|Ys]) :- same_length(Xs, Ys).

  leq_length([], _).
  leq_length([_|Xs], [_|Ys]) :- leq_length(Xs, Ys).
这现在可以很好地用于各种查询模式,例如

?- rotate(2, [a,b,c,d,e], Ys).   % gives Ys = [d,e,a,b,c]
?- rotate(2, Xs, [a,b,c,d,e]).   % gives Xs = [c,d,e,a,b]
?- rotate(N, [a,b,c,d,e], Ys).   % 5 solutions
?- rotate(N, Xs, [a,b,c,d,e]).   % 5 solutions
?- rotate(N, Xs, Ys).            % many solutions
然后,您可以将原始的
nshift/3
编写为

nshift(N, Xs, Ys) :-
    ( N>=0 -> rotate(N, Xs, Ys) ; M is -N, rotate(M, Ys, Xs) ).

我不知道序言,但你不应该在某个点将数字与0进行比较吗?@Teepeemm这与OP设计的第一个
nshift/3
规则隐式发生。我知道这听起来很琐碎,但要处理负移位的情况,请将值取反为正,然后将其移向另一个方向。