【问题标题】:Find an "infix" of a list in Prolog - order matters在 Prolog 中查找列表的“中缀” - 顺序很重要
【发布时间】:2020-04-19 19:43:24
【问题描述】:

一个知道 Prolog 一周的人的问题=)

我正在写一些序言命令infix(Inf,List) 检查一个列表是否如我们的教授所说的那样是另一个列表的“中缀”。顺序很重要+它不应该在列表的开头或结尾。

这意味着例如:

如果我们有 Inf=[1,2] 和 List=[1,2,3,4] 那么是假的。

如果我们有 Inf=[3,4] 和 List=[1,2,3,4] 那么 is 也是假的。

如果我们有 Inf=[2,3] 和 List=[1,2,3,4] 那么它是真的。

如果是 Inf=[3,2] 和 List=[1,2,3,4] 那么是假的。

如果是 Inf=[2,4] 和 List=[1,2,3,4,5] 那么是假的。

我已经写了一些规则,用它们我似乎设法解决了顺序问题,而不是计算列表的第一个元素。

infix(Inf,List):- length(Inf,L1),length(List,L2), L1>L2, !, fail.
infix(Inf,List):- length(Inf,L1),length(List,L2), L1=L2, !, fail.
infix(Inf,List):- length(Inf,L1),length(List,L2), L1<L2, delete_first(Inf,List).

delete_first(Inf,[_L|List]):- sublist(Inf,List).

sublist([El|Sub],[El|List]):- checksublist(Sub,List).
sublist([S|Sub],[L|List]):- sublist([S|Sub],List).

checksublist([], L).
checksublist([El|Sub],[El|List]):- checksublist(Sub,List).

但是,我无法以某种方式制定它,因此最后一个元素不计入=(。根据我的直觉逻辑,条件checksublist([], L).应该像checksublist([], [_|[]]).一样,但这不起作用方式-我什么都错了。

有人知道在这种情况下如何摆脱最后一个元素吗?提前致谢!

【问题讨论】:

    标签: prolog


    【解决方案1】:

    语法来拯救!但我不会称这个中缀。是某个subsequence,实际上甚至是某个substring

    infix(Inf, List) :-
       Inf = [_|_],
       phrase(([_], ..., seq(Inf), [_], ...), List).
    
    % The following are frequently predefined
    
    ... --> [] | [_], ... .
    
    seq([]) --> [].
    seq([E|Es]) --> [E], seq(Es).
    

    (编辑)由于您坚持前缀和后缀都不为空,您可能希望它也适用于中缀。因此添加了Inf = [_|_]

    这是使用Scryer顶层的结果:

    ?- infix(Inf,"abcdef").
       Inf = "b"
    ;  Inf = "bc"
    ;  Inf = "bcd"
    ;  Inf = "bcde"
    ;  Inf = "c"
    ;  Inf = "cd"
    ;  Inf = "cde"
    ;  Inf = "d"
    ;  Inf = "de"
    ;  Inf = "e"
    ;  false.
    

    请参阅this 如何在其他系统中将字符列表打印为双引号字符。

    【讨论】:

      【解决方案2】:

      这太迫切了。

      你可以让 Prolog 用append/2 解决它。它是搜索辅助编程,让我们使用它。

      infix(Inf,List) :- append([Prefix,Inf,Suffix],List),Prefix\=[],Suffix\=[].
      

      这完全是声明性的,从某种意义上说 它被表述为解决方案必须满足的约束(非常数学)。

      使用单元测试框架对其进行测试:

      :- begin_tests(infix).
      
      test(one,[fail]) :- infix([1,2],[1,2,3,4]).
      test(two,[fail]) :- infix([3,4],[1,2,3,4]).
      test(three) :- infix([2,3],[1,2,3,4]).
      test(four,[fail]) :- infix([3,2],[1,2,3,4]).
      test(five,[fail]) :- infix([2,4],[1,2,3,4,5]).
      
      :- end_tests(infix).
      
      rt:-run_tests(infix).
      

      然后

      ?- rt.
      % PL-Unit: infix ..
      Warning: user://1:12:
              PL-Unit: Test three: Test succeeded with choicepoint
      .. done
      % All 5 tests passed
      true.
      

      遗憾的是,Prolog 没有进行深入的推理和定理证明,而是使用了蛮力:它会尝试可能的解决方案,直到一个通过或不再有。 Weel,这种情况就足够了。

      例如:

      ?- append([Prefix,[3,4],Suffix],[1,2,3,4,5,3,4,6]).
      Prefix = [1, 2],
      Suffix = [5, 3, 4, 6] ;
      Prefix = [1, 2, 3, 4, 5],
      Suffix = [6] ;
      false.
      

      【讨论】:

      • Prefix\=[] 非常单调。 dif(Prefix, []) 或者更好的Prefix = [_|_]
      • 还有:你可以把那些放在append/2之前,从而减少暴力。
      • @false 好东西
      猜你喜欢
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      • 2021-03-10
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多