swi-prolog找到网格中的所有路径

时间:2014-02-02 05:21:46

标签: list grid prolog

我需要在网格中的两个给定点之间构建所有可能的路径,如此

 [1,1][2,1][3,1][4,1][5,1]
 [1,2][2,2][3,2][4,2][5,2]
 [1,3][2,3][3,3][4,3][5,3]
 [1,4][2,4][3,4][4,4][5,4]
 [1,5][2,5][3,5][4,5][5,5]

我有一个名为doesnt_contain的实用程序(无论是什么),它检查元素是否已经在路径中以避免循环。我试着从给定的点开始,每走一步,我都要向北,向东,向西走。当满足目标时,我将路径添加到所有可能路径的列表中。这是代码:

doesnt_contain([], _, _).
doesnt_contain([[H1|[H2|_]]|T], X, Y):- (X =\= H1; Y =\= H2), doesnt_contain(T, X, Y).
doesnt_contain([[H1|[H2|_]]|_], X, Y):- X == H1, Y == H2, fail.

build_paths(X1, Y1, X2, Y2, _, L, AL):- X1 =:= X2, Y1 =:= Y2, write([L|AL]).
build_paths(X1, Y1, X2, Y2, Limit, L, AL):-
    (X1 =\= X2; Y1 =\= Y2),
    ((X1 < Limit, X is X1 + 1, doesnt_contain(L, X, Y1), 
    build_paths(X, Y1, X2, Y2, Limit, [[X, Y1]|L], AL));
    (Y1 < Limit, Y is Y1 + 1, doesnt_contain(L, X1, Y), 
    build_paths(X1, Y, X2, Y2, Limit, [[X1, Y]|L], AL));
    (X1 > 1, X is X1 - 1, doesnt_contain(L, X, Y1), 
    build_paths(X, Y1, X2, Y2, Limit, [[X, Y1]|L], AL));
    (Y1 > 1, Y is Y1 - 1, doesnt_contain(L, X1, Y), 
    build_paths(X1, Y, X2, Y2, Limit, [[X1, Y]|L], AL))).

按顺序输出参数的一个示例:(开始X),(开始Y),(结束X),(结束Y),(网格限制),(包括开始的初始路径),(列表)所有路径)。

?- build_paths(2, 2, 4, 4, 5, [[2,2]], []).
[[[4,4],[3,4],[2,4],[1,4],[1,5],[2,5],[3,5],[4,5],[5,5],[5,4],[5,3],[5,2],[4,2],[3,2],[2,2]]]
true .

这段代码给了我一条路然后停止了。我需要所有可能的路径。我想我知道为什么它会在找到第一条路径后停止。这是因为or(;)运算符。但我不知道如何让它生成所有路径。

1 个答案:

答案 0 :(得分:1)

我试图清理你的代码......

build_paths(P, P, _, L) :- !, writeln(L).
build_paths(P1, P2, Limit, Ps) :-
    move(P1, P, Limit),
    \+ memberchk(P, Ps),
    build_paths(P, P2, Limit, [P|Ps]).

move([X1,Y1], [X,Y], Limit) :-
    X1 < Limit, X is X1 + 1, Y is Y1 ;
    Y1 < Limit, Y is Y1 + 1, X is X1 ;
    X1 > 1, X is X1 - 1, Y is Y1 ;
    Y1 > 1, Y is Y1 - 1, X is X1.

调用它
?- aggregate(count, build_paths([2, 2], [4, 4], 5, []), CountSol).

我得到了

...
[[4,4],[3,4],[3,3],[4,3],[4,2],[4,1],[3,1],[3,2],[2,2],[2,3],[2,4],[2,5],[1,5],[1,4],[1,3],[1,2],[1,1],[2,1]]
[[4,4],[5,4],[5,5],[4,5],[3,5],[3,4],[3,3],[4,3],[4,2],[4,1],[3,1],[3,2],[2,2],[2,3],[2,4],[2,5],[1,5],[1,4],[1,3],[1,2],[1,1],[2,1]]
[[4,4],[4,5],[3,5],[3,4],[3,3],[4,3],[4,2],[4,1],[3,1],[3,2],[2,2],[2,3],[2,4],[2,5],[1,5],[1,4],[1,3],[1,2],[1,1],[2,1]]
CountSol = 18184.

值得注意的是主要是生成和测试之间的分离。您将位置更新和检查捆绑在一起,这使您的代码更容易出错。