扭转列表

时间:2015-03-06 08:12:44

标签: graph prolog

我需要帮助扭转列表。

fun(a, [b, d]).
fun(b, [c]).
fun(c, []).
fun(d, [e]).
fun(e, [f]).
fun(f, [g]).
fun(g, []).

xyz(X, Y):- 
    fun(X, Z) -> findall([A|B], (member(A, Z), xyz(A, B)), L),
    flatten(L, F), sort(F, Y); Y = [].

查询xyz(a,X).给了我X = [b,c,d,e,f,g]. 但是,我希望它能给我X = [g,f,e,d,c,b]

我尝试了不同的尝试来扭转名单,但我没有运气。

我尝试在此之后添加一个额外的谓词,但它也不起作用:

xyz2(X,Y):-
    xyz(X,Y),
    reverse(Y,Z),
    Z\=0.

在我的另一篇文章中找到了上述实施方法的信用证。 Recursion in PROLOG?

1 个答案:

答案 0 :(得分:2)

您可以避免一些困难的编程,并通过重新定义您的问题使您的程序更容易阅读。假设f/2描述了一个有向图,第一个参数的边到第二个参数中的每个元素,所以:

a ---> b
a ---> d
b ---> c
% etc

然后,您的问题是,图表中的哪些节点可以从给定节点到达?您可以在library(ugraphs)的帮助下定义解决方案。

f/2

创建所有边
edge(From-To) :-
    f(From, L),
    member(To, L).

您现在可以收集边缘,制作图表,并找到可从起始节点到达的节点:

foo(X, L) :-
    findall(E, edge(E), Edges),
    vertices_edges_to_ugraph([], Edges, G),
    reachable(X, G, All),
    once(select(X, All, R)), % remove the node you start from
    reverse(R, L).

根据定义,节点总是可以自己访问,因此您需要从可访问节点列表中选择它。

?- foo(a, X).
X = [g, f, e, d, c, b].

?- foo(e, X).
X = [g, f].

?- foo(g, X).
X = [].

我并不完全理解为什么元素的顺序很重要。这感觉有点像代码味道。