Prolog的内置反向功能表现为奇数

时间:2015-03-09 00:09:56

标签: prolog

给出以下代码:

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有多个依赖bc。关于我目前的问题,方面应该不要太重要,但只是把这个事实告诉那里。


更新

感谢@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 = [].

非常笨拙的方法,但这似乎对我有用。我会努力提高效率。

1 个答案:

答案 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谓词的替代方法,可以避免使用findallflatten。此版本应避免循环路径,并且不显示重复:

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).