序言列表在任何位置插入

prolog list insert at any position

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

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

R = [a,b,c]
R = [b,a,c]
R = [b,c,a]

确实如此,但随后出现错误 'Out of Global stack'。有没有办法使这更具确定性,给出结果并完成?当它是 运行 相反的时候。 ins(X, Y, [a,b,c])。它给出了预期的结果,然后说 false 表明它已经完成。 代码:

app([],L,L).
app([H|T],L2,[H|L]) :- 
    app(T,L2,L).

ins(E, List, R) :-
    R = R1,
    app(R2, R3, R1),
    app([E], R4, R3),
    app(R2, R4, List).

这里是一个link到运行在线编译器的代码,SWISH(这也有我希望如何使用ins的例子,但是ins是问题所在马上) 任何帮助将不胜感激!

你有没有注意到这是怎么回事?首先,Prolog 非常友好和花花公子,向您展示了它是多么聪明,只是后来它让您印象深刻:购买。更多的。内存。现在!

如果 Prolog 放在前面不是更好吗?在显示任何答案之前?

好吧,您可以强制 Prolog 执行此操作。在查询末尾添加一个 false,如下所示:

?- ins(a, [b,c], R), false.
ERROR: Out of global stack

你可以对剩余的程序做同样的事情:只需添加 false,这样剩余的程序仍然循环或用完 space。我想出了以下最小

app([],L,L) :- false.
app([H|T],L2,[H|L]) :-
    app(T,L2,L), false.

ins(E, List, R) :-
    R = R1,
    app(R2, R3, R1), false,
    app([E], R4, R3),
    app(R2, R4, List).

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

这意味着我们必须修改剩余可见部分的某些内容才能摆脱循环。换句话说:只要可见部分保持不变,错误就会一直存在——保证!

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

直接解决方法是将第一个 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.

您可以将它与另一个非常有用的谓词一起使用,称为 setof :

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] ;
…