【问题标题】:Prolog Choose 3 From ListProlog 从列表中选择 3
【发布时间】:2015-11-22 06:15:59
【问题描述】:

我创建了一个序言程序,它给了一个数字列表,子列表将生成包含 N 个项目的子列表。有人告诉我,这可以通过 1 个事实和 2 个规则来完成。提示我选择了第一项,或者我没有选择,这让我感到困惑。我有基本情况和第一种情况,但我希望有人能帮助我理解第二种情况。

choose(1, [H], [H]).
choose(N, [H,TL], [H|ST]) :- choose(Less1, TL, ST), Less1 is N-1.

所以我的第三条规则我想选择列表中的第二项

choose(N, [F,S|T], [S|ST]) :- choose(Less1, T, ST), Less1 is N-1.

然而,我的最后一条规则是不平衡的,整体不起作用。任何想法都非常感谢!

【问题讨论】:

    标签: list prolog


    【解决方案1】:

    虽然this previous answer by @madanasta 应该已经为您指明了正确的方向,但我们在此答案中使用 对其进行了扩展:

    :- use_module(library(clpfd)).
    

    我们这样定义n_from_chosen/3

    n_from_chosen(0,_,[])。 n_from_chosen(N,[X|Es],[X|Xs]) :- N #> 0, N #= N0+1, n_from_chosen(N0,Es,Xs)。 n_from_chosen(N,[_|Es],Xs) :- N #> 0, n_from_chosen(N,Es,Xs)。

    示例查询:

    ?- n_from_chosen(2,[1,2,3,4],Xs)。 Xs = [1,2] ; Xs = [1,3] ; Xs = [1,4] ; Xs = [2,3] ; Xs = [2,4] ; Xs = [3,4] ;错误的。

    这个更一般的查询怎么样?

    ?- n_from_chosen(N,[1,2,3],Xs)。 N = 0, Xs = [] ; N = 1, Xs = [1] ; N = 2, Xs = [1,2] ; N = 3,Xs = [1,2,3] ; N = 2, Xs = [1, 3] ; N = 1, Xs = [2] ; N = 2, Xs = [2,3] ; N = 1,Xs = [3] ;错误的。

    【讨论】:

      【解决方案2】:

      前两句背后的想法原则上是正确的。然而:

      • 当必须找到长度为 1 的子列表但原始列表的长度不是 1 时,第一个子句没有用。这是有问题的。
      • 在第二个子句中,我假设您的意思是 [H|TL]。

      鉴于这些,您的问题的解决方案可能是:

      choose(1, [H|_], [H]).
      choose(N, [H|TL], [H|ST]) :- Less1 is N - 1, choose(Less1, TL, ST).
      choose(N, [_|T], L) :- choose(N, T, L).
      

      试图解释:

      • 在给定任何至少包含一个元素的列表的情况下,第一个子句将生成长度为 1 的子列表:它将简单地将第三个参数与仅包含原始列表头部的单元素列表统一起来。
      • 第二个子句将处理请求长度大于 1 的子列表的情况,在这种情况下,它将把第三个参数与包含原始列表头部和尾部的列表统一起来,由于递归,它将是原始列表尾部的子列表,其长度等于请求的长度减去 1。
      • 第三个子句将简单地跳过原始列表的头部,并将第三个参数与一个列表统一起来,由于递归,该列表将是原始列表尾部的请求长度的子列表。

      多亏了第三个子句,Prolog 将能够为请求的长度等于或大于 1 提供替代解决方案。

      一些结果:

      ?- choose(2, [1,2,3,4], L).
      L = [1, 2] ;
      L = [1, 3] ;
      L = [1, 4] ;
      L = [2, 3] ;
      L = [2, 4] ;
      L = [3, 4] ;
      false.
      

      请注意,您不能像使用@repeat's solution 那样使用它来解决具有未绑定长度变量的查询。要在纯 Prolog 中实现这一点,您必须稍微更改第二个子句背后的逻辑:

      choose(N, [H|TL], [H|ST]) :- choose(Less1, TL, ST), N is Less1 + 1.
      

      这也可能有助于阐明递归在这种情况下的工作原理。

      希望这会有所帮助。

      (免责声明:我相当肯定可以对上述解决方案的工作原理提供更好的解释(更不用说更好的解决方案了)。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-03
        • 2015-11-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多