【问题标题】:prolog list insert at any position在任何位置插入序言列表
【发布时间】:2017-11-19 22:19:09
【问题描述】:

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

【问题讨论】:

    标签: list insert prolog failure-slice


    【解决方案1】:

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

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

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

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

    您可以对剩余的程序执行相同的操作:只需添加 false 以使剩余的程序仍然循环或耗尽空间。我想出了以下最小的

    app([],L,L) :- false。 应用程序([H|T],L2,[H|L]):- 应用程序(T,L2,L),。 ins(E,列表,R):- R = R1, 应用程序(R2,R3,R1),app([E], R4, R3), 应用程序(R2,R4,列表)。 ?- ins(a, [b,c], R), false

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

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

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


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

    【讨论】:

      【解决方案2】:

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

      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) 的问题(他们不会列举所有可能的情况)。
      • 融合这两个子句也可以提供正确的解决方案。
      【解决方案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]].
      

      【讨论】:

        猜你喜欢
        • 2015-05-21
        • 2012-08-25
        • 1970-01-01
        • 2013-12-14
        • 2010-11-23
        • 1970-01-01
        • 1970-01-01
        • 2017-11-22
        • 2011-10-20
        相关资源
        最近更新 更多