此页面上的练习 09 http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/要求创建一个将重复元素打包到子列表中的谓词。
一个简单的解决方案是简单的
pack([], []).
pack([H|T], [I|U]) :-
split(H, T, I, P),
pack(P, U).
其中 splitsplit(Head, Tail, HeadGroup, Rest)
被定义为
split(A, [], [A], []).
split(A, [B|T], [A], [B|T]) :- A \= B.
split(A, [A|T], [A|U], B) :- split(A, T, U, B).
效果很好,并且与上述网页上提供的示例解决方案非常一致。
该解决方案失败的地方是查询,例如pack(X, [[a], [b, b]]).
. 两个解集之间的对应是双射的(其中每一个只有一个) A
,所以必须有一个更好的解。pack(A, B)
B
解决它的一种方法是更改评估顺序,帮助 prolog 根据参数的类型选择非无限分支,如下所示
pack([], []).
pack(A, B) :-
( var(A) ->
A = [H|T],
B = [I|U],
pack(P, U),
split(H, T, I, P)
; A = [H|T],
B = [I|U],
split(H, T, I, P),
pack(P, U)
).
这方面的两个问题。
首先,这令人难以置信的丑陋,那么是否有更好的方法来根据参数类型选择规则顺序?
其次,可能是更复杂的问题,有没有办法在没有 的情况下重写解决方案var(A)
,如果没有,为什么?