我在获取正确的输出时遇到问题。您可以在跟踪中看到我的结果。但是我想不起来在某个时候停止它。它应该计算公式说的内容,然后简单地将结果写到列表中,并递减D并重复该过程,直到达到0而不是0。
t(R, L) :- t(R, R, L).
t(D, R, [Ti|L]) :- D >= 1, !,
Ti is D * ((D + 1) / 2),
D1 is D - 1,
t(D1, R, [Ti|L]).
输入为t(2,L)。
Call: (8) t(2, _1804) ? creep
Call: (9) t(2, 2, _1804) ? creep
Call: (10) 2>=1 ? creep
Exit: (10) 2>=1 ? creep
Call: (10) _2052 is 2*((2+1)/2) ? creep
Exit: (10) 3.0 is 2*((2+1)/2) ? creep
Call: (10) _2064 is 2+ -1 ? creep
Exit: (10) 1 is 2+ -1 ? creep
Call: (10) t(1, 2, [3.0|_1804]) ? creep
Call: (11) 1>=1 ? creep
Exit: (11) 1>=1 ? creep
Call: (11) _2088 is 1*((1+1)/2) ? creep
Exit: (11) 1 is 1*((1+1)/2) ? creep
Call: (11) _2094 is 1+ -1 ? creep
Exit: (11) 0 is 1+ -1 ? creep
Call: (11) t(0, 2, [1, 3.0|_1804]) ? creep
Call: (12) 0>=1 ? creep
Fail: (12) 0>=1 ? creep
**Fail: (11) t(0, 2, [1, 3.0|_1804]) ? creep**
Fail: (10) t(1, 2, [3.0|_1804]) ? creep
Fail: (9) t(2, 2, _1804) ? creep
Fail: (8) t(2, _1804) ? creep
false.
基于此公式,输出应为L = [1,3] Ti为D *((D + 1)/ 2),与迹线中标记的行相同,但不。当达到D = 0时,它应该停止,但是没有达到。
我尝试通过创建0的大小写来阻止它,但是它不起作用。
t(0, []) :- !.
t(0, _, _) :- !.
t(_, _, R, L) :- R < 1, !.
答案 0 :(得分:1)
问题在于您从未告诉过Prolog万一D=0
时该怎么做。因此Prolog不断递减D
,直到D >= 1
不再成功为止,这意味着您达到了“ 失败”的地步。然后,Prolog将开始回溯,直到找到一个回溯点,或者在这里,它将展开整个调用堆栈,并报告失败。
即使您设法实现停止条件,这也不足够,因为在谓词中,您使用[Ti|L]
作为参数,然后递归调用[Ti|L]
。这意味着递归调用将旨在设置列表中的一个元素 same (!),如果值不同,则将再次导致失败。
由于从右到左构建了列表,因此可以使用以空列表开头的累加器,并且每次在递归调用中将元素放在列表的前面。然后,停止条件将累加器与结果统一起来。
t(R, L) :-
t(R, [], L).
t(0, R, R).
t(D, L, R) :-
D >= 1, !,
Ti is D * ((D + 1) / 2),
D1 is D - 1,
t(D1, [Ti|L], R).
然后产生预期的结果:
?- t(2, L).
L = [1, 3.0] ;
false.
但是请注意,通过从左到右工作并使用累加器对索引求和,可以提高上述效率。
例如:
t(N, R) :-
t(1, 1, N, R).
t(I, _, N, []) :-
I > N.
t(I, A, N, [A|T]) :-
I =< N,
I1 is I+1,
A1 is A + I1,
t(I1, A1, N, T).