向右旋转列表(Prolog)

时间:2013-11-19 20:59:38

标签: list prolog

我有一项任务,我需要向右旋转一次列表。我也有一个约束,我只能使用一个谓词。似乎向左移动很容易:

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

尽管如此,向右旋转并保持约束似乎更难。这是我的尝试:

rotate([H], H).
rotate([H|T], F) :- rotate(T,F1), append(F1,T,F).

在我看来,它完美无缺,但我只得到false作为输出。任何帮助解决这个问题都将非常感激!

2 个答案:

答案 0 :(得分:13)

如果你已经有一个谓词,比如向左旋转一个rotl(L, Rotated),你可以使用那个相同的谓词向右旋转。只需将列表放入第二个参数并保留第一个变量!

这是关系的深层理念:你可以以多种方式使用它们!

总结一下:

rotleft([E|T], R) :-
   append(T,[E],R).

rotright(L, R) :-
   rotleft(R, L).

以下是最常规查询,其中显示了包含所有可能解决方案的所有答案:

| ?- rotright(L,R).
L = [_A],
R = [_A] ? ;
L = [_A,_B],
R = [_B,_A] ? ;
L = [_A,_B,_C],
R = [_C,_A,_B] ? ;
L = [_A,_B,_C,_D],
R = [_D,_A,_B,_C] ? ;
L = [_A,_B,_C,_D,_E],
R = [_E,_A,_B,_C,_D] ? ;
L = [_A,_B,_C,_D,_E,_F],
R = [_F,_A,_B,_C,_D,_E] ? ;
L = [_A,_B,_C,_D,_E,_F,_G],
R = [_G,_A,_B,_C,_D,_E,_F] ? ;
L = [_A,_B,_C,_D,_E,_F,_G,_H],
R = [_H,_A,_B,_C,_D,_E,_F,_G] ? 

你看到了这种模式吗?对于列表的每个长度(空列表除外),有一个答案包含所有可能的解决方案。看一下如何在一个答案中变量是相同的。我将用一个答案来说明这一点:

L = [_A,_B,_C,_D,_E,_F,_G],
      \  \  \  \  \  \  \____
  ___  \  \  \  \  \  \
     \  \  \  \  \  \  \
R = [_G,_A,_B,_C,_D,_E,_F] ? ;

这是最有趣的问题:

  

列表如何与向左/右旋转的列表相同?

尝试制定该查询并详细查看答案。

答案 1 :(得分:1)

重要的是要注意append/3相当灵活。

正如您所发现的那样,左旋是很容易的。你想来自

[a,b,c]

[b,c,a]

通过观察,这样做只需要从列表中获取第一个项目(头部)并将其附加到列表的其余部分(尾部)。在prolog中,这很简单:

rotate_left( []     , [] ) .        % rotating an empty list yields the empty list
rotate_left( [L|Ls] , Rotated ) :-  % a left rotation of a non-empty list consist of decomposing it into its head and tail, and
  append( Ls , [L] , Rotated )      % - appending the head to the tail.
  .

正确的轮换并不困难。再次,通过观察,你想从

获得
[a,b,c]

[c,a,b]

您需要从列表中获取 last 项,并将其添加到列表的其余部分。同样,您不需要比左旋转更多的东西:

rotate_right( []     , []      ) .         % rotating an empty list yields the empty list.
rotate_right( [L|Ls] , Rotated ) :-        % a right rotation of a non-empty list consists of
  append( LeftPrefix , [Last] , [L|Ls] ) , % - deconstructing it into the last item and everything to its left
  Rotated = [Last|LeftPrefix]              % - reconstructing it with the righmost item first
  .

append/3非常强大,因为它可以将列表分解为所有可能的前缀和后缀。将[a,b,c]输入其第三个参数:

append( Prefix , Suffix , [a,b,c] ).

并且,通过回溯,您可以获得创建列表[a,b,c]的全套可能方法:

Prefix = []      Suffix = [a,b,c]
Prefix = [a]     Suffix = [b,c]
Prefix = [a,b]   Suffix = [c]
Prefix = [a,b,c] Suffix = []