递归地在prolog中旋转列表

时间:2017-01-05 21:31:07

标签: prolog

我正在尝试递归地旋转prolog中的列表,但它不能按预期工作。

代码:

rot([],[]).
rot([H|T1], [T2|H]):-rot(T1,T2).

输出:

?- rot([1,2,3], V).
V = [[[[]|3]|2]|1]

预期产出:

?- rot([1,2,3], V).
V = [3,2,1]

有人能解释一下为什么我的代码不起作用吗?

3 个答案:

答案 0 :(得分:4)

由于Prolog是无类型的,你确实可以编写类似[List|Element]的内容,但是如果你想让列表有意义,那么构建列表的唯一方法就是[Element|List]。所以[T2|H]根本没有意义。在这种情况下,T2应为元素,H为列表(或空列表[])。

您需要定义两个谓词:

  • 主谓词(rot/2),它只是从给定列表中弹出头部并调用递归谓词;和
  • 递归谓词(此处为rot/3),它只传递给定列表的所有元素,并将原始头部作为尾部元素发出。

这一起工作如下:

%main predicate rot/2
rot([],[]).
rot([H|T1],T2) :-
    rot(T1,H,T2).

%recursive predicate rot/3
rot([],Last,[Last]).
rot([H|T1],Last,[H|T2]) :-
    rot(T1,Last,T2).

答案 1 :(得分:3)

您的代码不起作用,因为在[H|T]之类的表达式中,H是列表的元素,T是列表的尾部 - 也是列表。例如:

?- [H|T] = [1,2,3].
H = 1,
T = [2, 3].

那么当你转换它时会发生什么?

?- [H|T] = [1,2,3], X = [T|H].
H = 1,
T = [2, 3],
X = [[2, 3]|1].

看到问题?

答案 2 :(得分:2)

问题在于第二个条款。我做的是旋转L1内第一个列表的尾部,然后用L1和第一个元素调用append并将结果赋值给L(第二个参数)

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

rot([], []).
rot([H|T], L) :- rot(T, L1), my-append(L1, H, L).