目标a(3, X)
应该返回6
。基于此代码。我已经将其转换为Prolog代码,但是在递归谓词中存在问题。前两行用于0和1返回相同的值。
c=1
for i = 2 to n do
if c > i then
c=c-1
else
c=c+1
end if
end for
return c
但是在第4步,它得到结果,然后返回到第2步,并通过迭代返回错误的结果。我认为这是一个统一的问题,但找不到哪里。
a(N, N) :- N < 2, !.
a(N, X) :- a(1, 2, N, X).
第2步。
a(C1, I, N, C1) :- I > N, !.
第3步。
a(C, I, N, C1) :- C > I, !,
C1 is C - I,
I1 is I + 1,
a(C1, I1, N, C1).
第4步。
a(C, I, N, C1) :- C =< I, !,
C1 is C + I,
I1 is I + 1,
a(C1, I1, N, C1).
这是跟踪。
[trace] ?- a(3, X).
Call: (8) a(3, _1238) ? creep
Call: (9) 3<2 ? creep
Fail: (9) 3<2 ? creep
Redo: (8) a(3, _1238) ? creep
Call: (9) a(1, 2, 3, _1238) ? creep
Call: (10) 2>3 ? creep
Fail: (10) 2>3 ? creep
Redo: (9) a(1, 2, 3, _1238) ? creep
Call: (10) 1>2 ? creep
Fail: (10) 1>2 ? creep
Redo: (9) a(1, 2, 3, _1238) ? creep
Call: (10) 1=<2 ? creep
Exit: (10) 1=<2 ? creep
Call: (10) _1474 is 1+2 ? creep
Exit: (10) 3 is 1+2 ? creep
Call: (10) _1480 is 2+1 ? creep
Exit: (10) 3 is 2+1 ? creep
Call: (10) a(3, 3, 3, 3) ? creep
Call: (11) 3>3 ? creep
Fail: (11) 3>3 ? creep
Redo: (10) a(3, 3, 3, 3) ? creep
Call: (11) 3>3 ? creep
Fail: (11) 3>3 ? creep
Redo: (10) a(3, 3, 3, 3) ? creep
Call: (11) 3=<3 ? creep
Exit: (11) 3=<3 ? creep
Call: (11) _1486 is 3+3 ? creep
Exit: (11) 6 is 3+3 ? creep
Call: (11) _1492 is 3+1 ? creep
Exit: (11) 4 is 3+1 ? creep
Call: (11) a(6, 4, 3, 6) ? creep
Call: (12) 4>3 ? creep
Exit: (12) 4>3 ? creep
Exit: (11) a(6, 4, 3, 6) ? creep !!! SHOULD STOP HERE !!!
Exit: (10) a(3, 3, 3, 3) ? creep
Exit: (9) a(1, 2, 3, 1) ? creep
Exit: (8) a(3, 1) ? creep
X = 1 .
答案 0 :(得分:0)
您需要另一个变量。您正在“超载” math.sqrt
,因此在进行递归调用时它已被实例化(绑定),并且最终在跟踪中出现了类似的事情(请注意,使用显示的代码,我不会得到与您所做的相同的跟踪,因此您对代码做了一些不同的操作):
C1
所以这是一个带有附加变量的更正:
| ?- a(3,X).
1 1 Call: a(3,_23) ?
2 2 Call: 3<2 ?
2 2 Fail: 3<2 ?
2 2 Call: a(1,2,3,_23) ?
3 3 Call: 2>3 ?
3 3 Fail: 2>3 ?
3 3 Call: 1>2 ?
3 3 Fail: 1>2 ?
3 3 Call: 1=<2 ?
3 3 Exit: 1=<2 ?
4 3 Call: _23 is 1+2 ?
4 3 Exit: 3 is 1+2 ?
5 3 Call: _174 is 2+1 ?
5 3 Exit: 3 is 2+1 ?
6 3 Call: a(3,3,3,3) ?
7 4 Call: 3>3 ?
7 4 Fail: 3>3 ?
7 4 Call: 3>3 ?
7 4 Fail: 3>3 ?
7 4 Call: 3=<3 ?
7 4 Exit: 3=<3 ?
8 4 Call: 3 is 3+3 ?
8 4 Fail: 3 is 3+3 ? <--- FAILS HERE: DUE TO C1 ALREADY BOUND
3 cannot be 3+3 !
6 3 Fail: a(3,3,3,3) ?
2 2 Fail: a(1,2,3,_23) ?
1 1 Fail: a(3,_23) ?
(1 ms) no
然后您得到:
a(C, I, N, C1) :- C > I, !,
C2 is C - I,
I1 is I + 1,
a(C2, I1, N, C1).
a(C, I, N, C1) :- C =< I, !,
C2 is C + I,
I1 is I + 1,
a(C2, I1, N, C1).
顺便说一句,不要那么快就在整个代码中散布剪切。如果没有他们,请首先使一切正常。然后将它们非常有意地修剪决策分支。它们有时会修剪出您真正想要的路径,并导致不良结果。