3

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

2 回答 2

2

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

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

对于初学者,我会放弃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.

希望这可以帮助!

于 2012-10-19T05:16:54.433 回答
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.
于 2012-10-19T09:17:51.700 回答