有没有办法测试任意列表是否对称?
例如:
?- 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).
有谁知道这样做的好方法?真的很感激任何帮助!
顺便说一句:我不关心元素数量不均的列表。
答案 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,以及确保列表的最后一个元素与第一个元素匹配: - )。