更改参数数量并统一

时间:2018-12-03 22:31:30

标签: prolog

我在获取正确的输出时遇到问题。您可以在跟踪中看到我的结果。但是我想不起来在某个时候停止它。它应该计算公式说的内容,然后简单地将结果写到列表中,并递减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, !.

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).