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现在是问题) 任何帮助将不胜感激!
答案 0 :(得分:3)
你有没有注意到这是怎么回事?首先,Prolog是非常好的和花花公子,并告诉你它有多聪明,只有在它后来它击中你:买。更多。内存。现在!
如果Prolog在前面会不会更好?在显示任何答案之前?
好吧,你可以强制Prolog做到这一点。在查询末尾添加 false
,如下所示:
?- ins(a, [b,c], R), false. ERROR: Out of global stack
您可以对剩余的程序执行相同操作:只需添加 false
,以便剩余的程序仍然循环或用完空间。我提出了以下最小failure-slice
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.
这意味着我们必须修改剩余可见部分中的某些内容以消除该循环。换句话说:只要可见部分保持不变,错误就会持续存在 - 保证!
有关此技术的更多信息,请了解非终止的原因,请参阅failure-slice
立即解决方法是将第一个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]].