prolog列表插入任何位置

时间:2017-11-19 22:19:09

标签: list insert prolog failure-slice

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

ins 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])。它给出了预期的结果然后说错,表明它已经完成。 代码:

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).

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

3 个答案:

答案 0 :(得分:3)

你有没有注意到这是怎么回事?首先,Prolog是非常好的和花花公子,并告诉你它有多聪明,只有在它后来它击中你:买。更多。内存。现在!

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

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

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

您可以对剩余的程序执行相同操作:只需添加 false ,以便剩余的程序仍然循环或用完空间。我提出了以下最小

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放在最后。

但还有其他的东西:你使用了各种难以理解的变量。也许坚持一个更统一的计划。此外,无需使用[A]附加app/3。实际上你只需要两个app/3目标。

答案 1 :(得分:1)

以下是此谓词的简单实现:

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

答案 2 :(得分:0)

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]].