拆分指定元素的列表

时间:2012-10-19 03:22:16

标签: list split prolog

我一直试图在给定元素上拆分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].

2 个答案:

答案 0 :(得分:2)

我不完全确定你想在这里做什么。例如,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.

希望这有帮助!

答案 1 :(得分:1)

我会这样写,所以如果你需要一些其他用例,你可以'重用'谓词(写入输出流不是我们需要的,大部分时间)

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.