4

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 表示它已经完成。代码:

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 是现在的问题)任何帮助将不胜感激!

4

3 回答 3

4

你注意到这是怎么变坏了吗?首先,Prolog 非常漂亮和花花公子,向您展示了它是多么聪明,直到后来才让您震惊:购买。更多的。内存。现在!

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

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

?- ins(a, [b,c], R), false。
错误:超出全局堆栈

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

应用程序([],L,L):-。
应用程序([H|T],L2,[H|L]):-
    应用程序(T,L2,L),。

ins(E,列表,R):-
    R = R1,
    应用程序(R2,R3,R1),应用程序([E],R4,R3)应用程序(R2,R4,列表)。

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

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

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

直接的解决方法是将第一个 app/3-goal 放在最后。


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

于 2017-11-19T22:56:17.853 回答
3

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

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] ;
…
于 2017-11-20T09:06:58.533 回答
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]].
于 2017-11-20T07:30:11.313 回答