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