List 在任何位置插入序言列表

List 在任何位置插入序言列表,list,insert,prolog,failure-slice,List,Insert,Prolog,Failure Slice,Prolog新手,尝试编写一个谓词,给出元素可以插入列表中任何位置的所有选项。 例: ins(a[b,c],R)。应给出: R = [a,b,c] R = [b,a,c] R = [b,c,a] 确实如此,但随后给出了一个错误“超出全局堆栈”。有没有一种方法可以使这更具确定性,给出结果并付诸实施?当它反向运行时,即ins(X,Y,[a,b,c])。它给出了预期的结果,然后说false表示它已经完成。 代码: 这是一个在在线编译器中运行代码的链接,(这也有一个我希望如何使用ins的示例,但ins

Prolog新手,尝试编写一个谓词,给出元素可以插入列表中任何位置的所有选项。 例:

ins(a[b,c],R)。
应给出:

R = [a,b,c]
R = [b,a,c]
R = [b,c,a]
确实如此,但随后给出了一个错误“超出全局堆栈”。有没有一种方法可以使这更具确定性,给出结果并付诸实施?当它反向运行时,即ins(X,Y,[a,b,c])。它给出了预期的结果,然后说false表示它已经完成。 代码:

这是一个在在线编译器中运行代码的链接,(这也有一个我希望如何使用ins的示例,但ins是目前的问题)
任何帮助都将不胜感激

你有没有注意到这是怎么搞砸的?首先,Prolog非常漂亮,向你展示了它是多么的聪明,直到后来它才打动了你:买。更多内存现在

如果Prolog站在前面不是更好吗?在给出任何答案之前

好吧,你可以强迫Prolog做这个。在查询末尾添加一个
false
,如下所示:

?- ins(a, [b,c], R), false. ERROR: Out of global stack 这意味着我们必须修改剩余可见部分中的某些内容,以消除循环。换句话说:只要可见部分保持不变,错误就会持续——保证

有关此技术的更多信息,以了解不终止的原因,请参阅

最直接的解决办法是把第一个app/3-goal放在最后



但还有一件事:你使用了各种难以理解的变量。也许坚持一个更统一的方案。此外,不需要使用
app/3
附加
[A]
。实际上,您只需要两个
app/3
目标。

Prolog有一个有趣的谓词,名为select

?- select(a, Out, [b,c]).
Out = [a, b, c] ;
Out = [b, a, c] ;
Out = [b, c, a] ;
false.
ins(Elem, In, Lst_Out) :-
    setof(Out, select(Elem, Out, In), Lst_Out).
您可以将它与另一个非常有用的谓词一起使用,该谓词名为setof

?- select(a, Out, [b,c]).
Out = [a, b, c] ;
Out = [b, a, c] ;
Out = [b, c, a] ;
false.
ins(Elem, In, Lst_Out) :-
    setof(Out, select(Elem, Out, In), Lst_Out).
这使得:

?- ins(a, [b,c], Out).
Out = [[a, b, c], [b, a, c], [b, c, a]].

下面是该谓词的一个简单实现:

ins(X, [], [X]).
ins(X, [H|T], [X,H|T]).
ins(X, [H|T], [H|T2]) :-
    ins(X, T, T2).
它按照您期望的方向工作:

?- ins(a, [b,c], R).
R = [a, b, c] ;
R = [b, a, c] ;
R = [b, c, a] ;
false.

?- ins(a, L, [a,b,c]).
L = [b, c] ;
false.

?- ins(X, [b,c], [a,b,c]).
X = a ;
false.

?- ins(X, L, [a,b,c]).
X = a,
L = [b, c] ;
X = b,
L = [a, c] ;
X = c,
L = [a, b] ;
false.

?- ins(a, X, Y).
X = [],
Y = [a] ;
X = [_5312|_5314],
Y = [a, _5312|_5314] ;
X = [_5312],
Y = [_5312, a] ;
X = [_5312, _5324|_5326],
Y = [_5312, a, _5324|_5326] ;
…

@false您确实可以将这两个事实融合到
ins(X,L,[X | L])。
。两个版本在ins(a,X,Y)方面仍然存在问题(它们不会列举所有可能的情况)。融合这两个子句也会给出正确的解决方案。