Prolog-创建另一个列表的所有可能班次的列表?

时间:2019-02-23 00:11:53

标签: list prolog rotation

对于我的任务,我需要创建一个序言中另一个列表的所有可能移位(旋转)的列表。例如,

getPosition()

当前,我有一个程序可以将其向左移动一次。

getPosition()

但是,我需要创建另一个程序,其中最终结果(R)包含所有可能的移位。序言中的递归确实开始使我感到困惑,但是我很确定这是必需的。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

使用same_length/2append/3保持逻辑纯正!

list_rotations(Es, Xss) :-
   same_length(Es, [_|Xss]),
   rotations_of(Xss, Es).

rotations_of([], _Es).
rotations_of([Xs|Xss], Es) :-
   same_length([_|Xss], Suffix),
   same_length(Es, Xs),
   append(Suffix, Prefix, Xs),
   append(Prefix, Suffix, Es),
   rotations_of(Xss, Es).

示例查询:

?- list_rotations([A,B,C,D], Xss).
Xss = [[B,C,D,A],
         [C,D,A,B],
           [D,A,B,C]].           % succeeds deterministically

答案 1 :(得分:1)

您的问题的解决方案可能是:

rotatelist([H|T], R) :- append(T, [H], R).

rotate(L,LO,LL):-
    rotatelist(L,L1),
    \+member(L1,LO),!,
    append([L1],LO,L2),
    rotate(L1,L2,LL).
rotate(_,L,L).

?- rotate([1,2,3,4],[],L).
L = [[1, 2, 3, 4], [4, 1, 2, 3], [3, 4, 1, 2], [2, 3, 4, 1]]

仅旋转列表并检查此列表是否已插入输出列表中。如果不是,则递归继续,否则它将返回L中的列表。我插入剪切!只是为了只包含所有可能旋转的列表。如果您还想生成其他列表,只需将其删除...

相反,如果您想要使用提供的原型的解决方案,则可能是:

rotatelist([H|T], R) :- append(T, [H], R).

all_shifts(_,[],I,I).
all_shifts(L,Result,Len,I):-
    I < Len,
    rotatelist(L,LO),
    I1 is I+1,
    all_shifts(LO,R1,Len,I1),
    append([LO],R1,Result).

?- length([1,2,3,4],L), all_shifts([1,2,3,4],R,L,1).
L = 4,
R = [[2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]

这个想法与以前基本相同。请注意,第二个解决方案不是尾递归。