在上一篇文章中,我最终想出了如何编写 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/计算机应该能够毫无困难地处理这个问题,这意味着我需要重新考虑算法?