【问题标题】:Splitting a list at an specified element在指定元素处拆分列表
【发布时间】:2012-10-19 03:22:15
【问题描述】:

我一直在尝试在给定元素处拆分 Prolog。我已经接近了,但我无法获得列表的左侧部分。

split(X,[Y|L]) :- split(X,[Y|L],[Y|K],M).
split(_,[],[],[]).
split(X,[Y|L],K,[Y|M]) :- X < Y, split(X,L,K,M).
split(X,[Y|L],[Y|K],M) :- X >= Y, split(X,L,K,M).
split(X,[Y|L],[Y|K],M) :- X = Y, write(Y), write(' '), write(L).

输入:

split(2,[1,2,3,4,5]).

返回:

2 [3,4,5]

我希望它返回

[1,2] [3,4,5].

【问题讨论】:

    标签: list split prolog


    【解决方案1】:

    我不完全确定你想在这里做什么。例如,split(5, [1,2,3,4,5]) 应该做什么?就此而言,假设输入列表已排序是否安全?我假设是这样的。

    您的规则split/2 的基本问题是您没有任何输出参数。 Prolog 的工作方式与大多数编程语言不同;没有return 这样的东西。起初,这感觉像是一个严重的限制,但 Prolog 实际上允许您“返回”任意数量的结果。看看这段代码,在我看来,你对这种理解的理解已经到了一半,因为你有split/2,它似乎没有任何输出参数,但它调用split/4,它有你需要的两个输出参数。

    首先,我会放弃split/2 的想法并尝试让split/4 工作。你所拥有的东西在那里看起来并不太疯狂:

    ?- split(2, [1,2,3,4,5], X, Y).
    X = [1, 2],
    Y = [3, 4, 5] .
    
    ?- split(5, [1,2,3,4,5], X, Y).
    X = [1, 2, 3, 4, 5],
    Y = [] .
    
    ?- split(1, [1,2,3,4,5], X, Y).
    X = [1],
    Y = [2, 3, 4, 5] .
    

    这表明您的大部分规则都是正确的。您遇到麻烦的地方是其他解决方案:

    ?- split(2, [1,2,3,4,5], X, Y).
    ... ;
    2 [3,4,5]
    X = [1, 2|_G317] ;
    false.
    
    ?- split(5, [1,2,3,4,5], X, Y).
    ... ;
    5 []
    X = [1, 2, 3, 4, 5|_G326] ;
    false.
    
    ?- split(1, [1,2,3,4,5], X, Y).
    ... ;
    1 [2,3,4,5]
    X = [1|_G314].
    

    您可以从那里的文章中看到,这些额外的解决方案是由您的最后一条规则生成的,X = Y, write(Y)... 等。只需删除该规则即可在split/4 中产生所需的行为。

    继续前进,我认为您真正想要的可能不是split/2,而是带有一个输出参数的split/3,一个列表列表。根据我们目前所拥有的,生成它并不难:

    split(X, List, [Before, After]) :- split(X, List, Before, After).
    

    运行它,我们看到我们得到了您提到的预期结果:

    ?- split(3, [1,2,3,4,5], X).
    X = [[1, 2, 3], [4, 5]] ;
    false.
    
    ?- split(1, [1,2,3,4,5], X).
    X = [[1], [2, 3, 4, 5]] ;
    false.
    
    ?- split(5, [1,2,3,4,5], X).
    X = [[1, 2, 3, 4, 5], []] ;
    false.
    

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      我会这样写,所以如果你需要一些其他用例,你可以“重用”谓词(写入输出流不是我们需要的,大多数时候)

      split(X, Xs) :-
          split(X, Xs, L, R), format('~w ~w', [L, R]).
      
      split(_, [], [], []).
      split(X, [Y|Xs], [], [Y|Xs]) :-
          X < Y.
      split(X, [X|Xs], [X], Xs).
      split(X, [Y|Xs], [Y|Ls], Rs) :-
          X > Y,
          split(X, Xs, Ls, Rs).
      

      测试

      ?- split(2,[1,2,3,4,5]).
      [1,2] [3,4,5]
      true ;
      false.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-10
        • 2014-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-22
        相关资源
        最近更新 更多