在上一篇文章中,我最终想出了如何编写 gprolog 程序来检查一个列表是否是另一个列表的排列。据我所知,它有效。
现在,我正在创建一个mysort
谓词,它将排列谓词与这个组合谓词(据我所知,也可以工作):
sorted([]).
sorted([L]) :- !.
sorted([L|[T|TT]]) :- L @=< T, sorted([T|TT]).
由于我的原始perm
谓词设计为!
在得到答案后立即终止,因此我进行了一些修改以允许mysort
检查可能性。这是mysort
,它的特殊backtrack_perm
,以及与旧的重叠perm
(我只是将其修改为对 的轻微更改backtrack_perm
):
perm([],[]).
perm([LH|LT],R) :-
backtrack_perm([LH|LT],R),
!.
perm_recurse([],X).
perm_recurse([LH|LT],R) :-
member(LH,R),
select(LH,[LH|LT],X),
select(LH,R,Y),
perm_recurse(X,Y),
!.
mysort(L,M) :-
backtrack_perm(L,M),
sorted(M),
!.
backtrack_perm([],[]).
backtrack_perm([LH|LT],R) :-
length([LH|LT],A),
length(R,B),
A == B,
member(LH,R),
select(LH,[LH|LT],X),
select(LH,R,Y),
perm_recurse(X, Y).
尽管它的组件看起来可以正常工作,但mysort
在某些输入上会导致堆栈溢出,例如mysort([5,3,2],X)
. 在已经排序的列表中,例如mysort([2,3,5],X)
,甚至是部分列表中,mysort([3,2,5],X)
跟踪可能很长,但它确实得到了答案。正因为如此——而且由于一个较小的完全向后的列表[2,1]
可以正常工作——我认为问题在于该过程本身对于所有这些排列来说太耗费空间/时间。
如果不深入研究更长的痕迹,是否可以安全地假设是这种情况?或者 Prolog/计算机应该能够毫无困难地处理这个问题,这意味着我需要重新考虑算法?