Prolog:测试任意列表是否对称

时间:2009-12-21 19:34:38

标签: list prolog symmetric

有没有办法测试任意列表是否对称?

例如:

?- symmetric([a,b,b,a]).
true.

?- symmetric([a,b,c,a]).
false.

?- symmetric([a,a]).
true.

我的尝试是将第一个元素与最后一个元素进行比较,如果它们相等则删除它们并继续执行列表的其余部分;否则失败。如果列表有2个元素且它们相等,则成功。否则失败。

然而,使用这个谓词“查找”列表的结尾并不是真正的高效:

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

有谁知道这样做的好方法?真的很感激任何帮助!

顺便说一句:我不关心元素数量不均的列表。

2 个答案:

答案 0 :(得分:6)

我找到了问题的答案。

对称列表是一个回文(有时候你看不到森林中的树木)......而这个简单的谓词测试了这个:

is_palindrome(L) :- reverse(L,L).

答案 1 :(得分:2)

但是你的算法很有意思。内置last/2(至少在SWI Prolog中)不会受到递归方法性能损失的影响。有了这个,这是一个实现你的想法的版本:

symmetric([]).
symmetric([L]).
symmetric([H|T]):-
    last(T,H),        % this forces the last element to equal the first
    append(T1,[H],T), % this deconstructs the rest list in one without the last elem.
    symmetric(T1).    % and recurses on that

有趣的是使用append/3谓词,在没有最后一个元素的情况下将初始休息列表解构为剩余列表。

编辑:我意识到即使没有last/2,我也可以使用append/3。所以这是改进版本:

symmetric([]).
symmetric([L]).
symmetric([H|T]):-
    append(T1,[H],T), % deconstruct and assure symmetry
    symmetric(T1).    % and recurse

现在,append同时执行两者,解构获得T1,以及确保列表的最后一个元素与第一个元素匹配: - )。