Prolog 的内置反向函数作用为奇数
Prolog's built-in reverse function acting odd
给定以下代码:
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 = [].
非常笨拙的方法,但现在这似乎对我有用。我会努力提高效率。
问题是您想要反转最终结果,但您的反转是在对 xyz/2
的每次递归调用中完成的。如果您在 xyz(cs140a, X)
调用中执行 trace
,您会看到它在不同的递归中被调用了几次。
如果你想要最后一次,那么你可以这样写:
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).
给定以下代码:
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 = [].
非常笨拙的方法,但现在这似乎对我有用。我会努力提高效率。
问题是您想要反转最终结果,但您的反转是在对 xyz/2
的每次递归调用中完成的。如果您在 xyz(cs140a, X)
调用中执行 trace
,您会看到它在不同的递归中被调用了几次。
如果你想要最后一次,那么你可以这样写:
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).