在Prolog中向左移动列表N次

时间:2014-06-23 19:32:32

标签: prolog failure-slice

我试图在Prolog shiftL(L1,N,L2)中建立关系,将L1向左移动N次(旋转),结果为L2,所以例如shiftL([1,2,3], 2, [3,1,2])是真的。

我尝试了以下内容:

shiftL([],N,[]).
shiftL([X|Xs],1,L) :- append(Xs,[X],L).
shiftL([X|Xs],N,L) :- N1 is N-1 , N=\=1 , shiftL(L1,N1,L) , append(Xs,[X],L1).

它的效果很好,但是在给我结果之后它总是继续做其他事情并且我得到了堆栈溢出:

?- shiftL([1,2,3], 2, L).
L = [3, 1, 2] ;
ERROR: Out of global stack

我不知道造成这种情况的原因。我以为我用第二行和N=\=1语句覆盖了基本情况。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

以下是相关的程序片段():

shiftL([],N,[]) :- false.
shiftL([X|Xs],1,L) :-
   append(Xs,[X],L), false.
shiftL([X|Xs],N,L) :-
   N1 is N-1 ,
   N=\=1,
   shiftL(L1,N1,L), false,
   append(Xs,[X],L1).

基本上,目标append(Xs,[X],L)循环。它循环,因为XsL都不是列表 - 这是一个固定长度的列表。要看到这一点,请考虑递归目标 shiftL(L1,N1,L)。正如您在片段中看到的那样,L1无处可寻。因此它是一个未实例化的变量。 L是查询中的变量。因此,您需要将L1L列入清单。就像把隐藏的append(Xs,[X],L1)放在前面一样。

还有另一个循环:

?- shiftL([1,2,3],-1,L).

我相信你可以自己解决这个问题。

有关故障切片如何缩小非终止问题的更多示例,请参阅