给定原子x,我试图将一个列表拆分成一个小于x的原子和一个原子等于或大于x的列表。
例如)
%% split(d,[a,b,c,d,e,f],AtomSmall, AtomBig) should give me
%% AtomSmall = [a,b,c], AtomBig = [d,e,f]
以下是我迄今为止尝试过的内容。我得到了这个概念。但是我的代码包含了AtomSmall
列表中x的等价原子,而不是AtomBig
,尽管我在谓词之前检查了一下。
例如)
%% split(d,[a,b,c,d,e,f],AtomSmall, AtomBig) gives me
%% AtomSmall = [a,b,c,d], AtomBig = [e,f]
before(X,Y):-atom_codes(X,A),atom_codes(Y,B),small(A,B).
small([],[]).
small([H1|T1],[H2|T2]):-H1<H2.
small([H1|T1],[H2|T2]):-H1=:=H2,small(T1,T2).
split(X,[],[],[]).
split(X,[H1|T1],[H1|Small],Big):-before(H1,X),split(X,T1,Small,Big).
split(X,[H1|T1],Small,[H1|Big]):-not(before(H1,X)),split(X,T1,Small,Big).
请帮忙!
答案 0 :(得分:0)
在SWI-Prolog中,您可以使用库中的partition / 4(列表)和标准订单比较(@&gt;)/ 2:
?- lists:partition(@>(d),[a,b,c,d,e,f],L,R).
L = [a, b, c],
R = [d, e, f].
由于比较中的参数顺序是固定的,将pivot作为第一个参数传递,因此lambda表达式(使用库(yall)需要最新版本)可以帮助提供更直观的读数:
?- partition([E]>>(E@<d),[a,b,c,d,e,f],L,R).
L = [a, b, c],
R = [d, e, f].
无论如何,您的代码可以像这样打补丁:
split(_,[],[],[]).
split(X,[H1|T1],[H1|Small],Big):-H1@<X,split(X,T1,Small,Big).
split(X,[H1|T1],Small,[H1|Big]):- \+ H1@<X,split(X,T1,Small,Big).
?- split(d,[a,b,c,d,e,f],L,R).
L = [a, b, c],
R = [d, e, f] ;
false.
答案 1 :(得分:0)
如果参数在字典上等效,则-i
谓词会成功。例如,before/2
为真。这是因为你的第3个子句在整个列表中允许相等的值,直到基本案例最终成功用两个空列表。
此外,如果before(a, a)
和before(X, Y)
是不同长度的原子,X
将会失败。例如,Y
将失败。所以你的before(ab, abc)
也需要照顾这个案例。
重构small/2
将解决这个问题:
small/2
但是......你不需要通过% 1st clause is fixed so unequal length atoms are handled properly
small([], _).
small([H1|_], [H2|_]) :- H1 < H2.
% 3rd clause is fixed so that equal atoms won't succeed here
small([H,H1|T1], [H,H2|T2]) :- small([H1|T1], [H2|T2]).
完成所有这些操作。 Prolog知道如何使用before/2
和@<
运算符以合理的方式比较原子(和一般的Prolog术语),正如@CapelliC在他的回答中指出的那样。所以你的@>
就变成了:
before/2
你根本不需要before(X, Y) :- X @< Y.
。这基本上是@CapelliC在答案中表现出来的第二个解决方案。