prolog - 没有正确递增

时间:2015-05-12 12:26:30

标签: prolog

我试图在以下程序中增加变量U,D,L,R。然而,它们似乎根本没有增加。

maze(4,0,3,0,0).
cell(0,0,[d],[0.391538986557049]).
cell(1,0,[r,d],[16.597130417636, 0.889878639213553]).
cell(2,0,[l,d],[0.011123208182191, 18.6496954092342]).
cell(3,0,[],[]).
cell(0,1,[u,r],[63.1258159853081, 3.14882640637611]).
cell(1,1,[u,l,r,d],[0.577082416767899, 11.2788559044107, 0.0116108917113176, 25.6907194043197]).
cell(2,1,[u,l,r,d],[89.8399554017928, 0.120311605902415, 0.0687987167581341, 198.151088713489]).
cell(3,1,[l,d],[0.0114526228490019, 152.662532290366]).
cell(0,2,[r,d],[0.0148854629087619, 0.019301544005463]).
cell(1,2,[u,l,r],[9.93466159987408, 0.199913563972552, 1.26393492879008]).
cell(2,2,[u,l,d],[12.3336316807166, 1.59269860596813, 0.680879328533728]).
cell(3,2,[u],[18.8277117544323]).
cell(0,3,[u],[15.6415340291405]).
cell(1,3,[],[]).
cell(2,3,[u,r],[0.216152697975287, 0.0138637250041849]).
cell(3,3,[l],[0.0113867473179591]).

genXY(N,R) :- R = [X,Y], succ(N1, N), between(0, N1, X), between(0, N1, Y).

isMem(U, Dir, C, R) :- not(member(U,Dir)), R is C + 0.
isMem(U, Dir, C, R) :- member(U,Dir), R is C + 1.

stats(U,D,L,R) :-
    U is 0, D is 0, L is 0, R is 0,
    maze(Len,_,_,_,_),
    genXY(Len,Out), 
    [H,T|_] = Out,
    cell(H,T,Dir,_),
    isMem(u, Dir, U, U1), %from here
    U is U1,
    isMem(d, Dir, D, D1),
    D is D1,
    isMem(l, Dir, L, L1),
    L is L1,
    isMem(r, Dir, R, R1),
    R is R1.              %to here

IsMem函数检查元素是否在列表中,如果是,则递增变量。如果不是,则返回相同的值。据我所知,正在从isMem返回正确的值,但变量U,L,D,R似乎没有更新。

编辑:

预期产出:

?- stats(U,D,L,R).
U = D, D = 8,
L = R, R = 7.

澄清一下,该程序会查看第一个单元格。第一个细胞的Dir是[d]。因此,变量D应该增加1,其他变量应该保持不变。下一个单元格有Dir [r,d]。所以R和D都应该增加。现在R应该保持值1而D应该保持2.所以基本上它计算在给定的一组单元格中有多少u,l,d,r。

1 个答案:

答案 0 :(得分:1)

Prolog和范围逻辑编程声明性编程以不同的方式处理变量命令式编程语言:变量只能是设置一次。在逻辑编程的情况下,某些部分可能仍然是可变的。但是,一旦您说X=a,就无法将其重置为X=b(除非您有回溯,或使用非可回溯商店一些Prolog系统提供)。

所以如果你设置了:

U is 0, D is 0, L is 0, R is 0,

这意味着UDLR永远设置为零。

但是,我不明白你为什么要覆盖这些值,你可以简单地使用零并返回所需的值:

stats(U,D,L,R) :-
    maze(Len,_,_,_,_),
    genXY(Len,Out), 
    [H,T|_] = Out,
    cell(H,T,Dir,_),
    isMem(u, Dir, 0, U),
    isMem(d, Dir, 0, D),
    isMem(l, Dir, 0, L),
    isMem(r, Dir, 0, R).

换句话说,直接使用0调用谓词并使用U等来捕获结果并将其返回。

此外,您可以使用以下内容优化isMem

isMem(U,Dir,C,R) :-
    member(U,Dir),
    !,
    R is C + 1.
isMem(_,_,C,C).

这将提高性能,并且在许多情况下是指定程序的更安全的方式,因为最后一个句子使谓词在句法上完全合并。

修改

根据您希望在答案中计算的内容,您可以考虑将程序重新设计为。首先编写一个程序,根据迷宫的大小增加坐标。

coorinc(X,Y,X1,Y) :-
    X1 is X+1,
    maze(N,_,_,_,_),
    X1 < N,
    !.
coorinc(_,Y,0,Y1) :-
    Y1 is Y+1,
    maze(N,_,_,_,_),
    Y1 < N.

现在您可以使用累加器来计算统计信息:

stat(U,D,L,R) :-
    stats(0,0,0,0,0,0,U,D,L,R).

现在需要实现stat/10的逻辑:

stats(X,Y,U0,D0,L0,R0,U,D,L,R) :-
    coorinc(X,Y,X1,Y1),
    !,
    cell(X,Y,Dir,_),
    isMem(u,Dir,U0,U1),
    isMem(d,Dir,D0,D1),
    isMem(l,Dir,L0,L1),
    isMem(r,Dir,R0,R1),
    stats(X1,Y1,U1,D1,L1,R1,U,D,L,R).

stats(X,Y,U0,D0,L0,R0,U,D,L,R) :-
    cell(X,Y,Dir,_),
    isMem(u,Dir,U0,U),
    isMem(d,Dir,D0,D),
    isMem(l,Dir,L0,L),
    isMem(r,Dir,R0,R).