给出以下代码:
fun(a, [b]).
fun(b, [c]).
fun(c, [d]).
fun(d, [e]).
fun(e, []).
xyz(X, Y):-
fun(X,Z) -> findall([A|B], (member(A,Z), xyz(A,B)), L),
flatten(L,F), sort(F,J), reverse(J,Y); Y = [].
使用查询xyz(a,X)
,我得到预期的输出X = [e,d,c,b].
。
什么可能扔掉这个?这与排序功能有关吗?如果是这样,根据下面链接中的文档,优先顺序的字母或数字顺序可能会将其抛弃,但cs40
仍未解释cs30
之前的情况。我很难找到相关性。我该如何解决这个问题?
http://www.swi-prolog.org/pldoc/doc_for?object=sort/2 http://www.swi-prolog.org/pldoc/man?section=compare
顺便说一下,fun函数可以有多元素列表,例如fun(a,[b,c],其中a
有多个依赖b
和c
。关于我目前的问题,方面应该不要太重要,但只是把这个事实告诉那里。
感谢@lurker,我取得了很大的进步。
给出以下代码:
final_xyz(X, Y):- xyz(X, R), reverse(R, Y).
xyz(X, Y) :-
fun(X,Z) -> findall([A|B], (member(A,Z), xyz(A,B)), L),
flatten(L,Y); Y = [].
为了解决此问题,我将代码更新为:
xyz-final(X,Y):-
fun(X,Z),
Z\=0,
( length(Z,1) -> xyz(X,J), reverse(J,Y)
;
xyz2(X,B), sort(B,C), reverse(C,Y)
).
xyz(K, [X|Y]):- fun(K, [X]), !, xyz(X, Y).
xyz(_, []).
xyz2(X, Y) :-
fun(X,Z) -> findall([A|B], (member(A,Z), xyz2(A,B)), L),
flatten(L,Y); Y = [].
非常笨拙的方法,但这似乎对我有用。我会努力提高效率。
答案 0 :(得分:1)
问题在于您想要反转最终结果,但在每次递归调用xyz/2
时都要反向。如果您在trace
电话上进行xyz(cs140a, X)
,则会在不同的递归上看到它被调用几次。
如果你想在最后一次,那么你可以这样写:
final_xyz(X, Y) :-
xyz(X, R),
reverse(R, Y).
xyz(X, Y) :-
fun(X,Z) -> findall([A|B], (member(A,Z), xyz(A,B)), L),
flatten(L,Y); Y = [].
然后调用final_xyz(cs140a, X)
收益,X = [m16a,cs30,cs40,cs110]
。
xyz
谓词的替代方法,可以避免使用findall
和flatten
。此版本应避免循环路径,并且不显示重复:
xyz(X, Y) :-
fun(X, L),
xyz(L, [], R),
reverse(R, Y).
xyz([H|T], A, R) :-
( memberchk(H, A)
-> xyz(T, A, R)
; fun(H, L)
-> xyz(L, [H|A], R1),
xyz(T, R1, R)
; xyz(T, [H|A], R)
).
xyz([], A, A).