所以,让我们说我试图找到低于某个最大数字的所有5个因子的总和。我递归地这样做,因为这似乎最容易。这是我的代码:
isFactor(X):-
Y is X mod 5,
Y = 0.
sumAll(Number, Result):-
sumAll(Number, 0, Result).
sumAll(Number, RunningTotal, Result):-
(isFactor(Number) ->
NextTotal is RunningTotal + Number;
NextTotal is RunningTotal),
NextNumber is Number - 1,
(NextNumber > 0 ->
mulSum(NextNumber, NextTotal, NextResult);
NextResult is RunningTotal),
number(NextResult) -> % this test is so that the interpreter
write(NextResult), nl; % doesn't print out a bunch of extra stuff
true. % (the internal IDs of each binding of
% NextResult maybe?) after the answer.
现在,这是有效的(也就是说,它打印正确的总和),但我有点恼火,我无法弄清楚如何安排代码,以便
| ?- sumAll(10, X).
将X
绑定到10
,而不是打印' 10'并断言“是”'最后。
如果Result
(第13行)成立,我的直觉是以某种方式将NextResult
重新绑定到NextNumber > 0
,但我怀疑只是多年的Python编程试图断言自己
有没有办法回归'这里的嵌套递归一直是目标的结果?或者我只想到这一切都错了?
答案 0 :(得分:1)
您的代码似乎比需要的更复杂,也许这种复杂性隐藏了一个重要的事实:
在sumAll(Number, RunningTotal, Result):-
中,结果是单身。然后几乎没有机会获得计算值。
我会试图摆脱number(NextResult) -> etc..
(顺便说一句,在使用if / then / else时,通常需要括号来获得预期的嵌套 - 即(C -> T ; F)
),并且'分配&# 39;而不是结果。
答案 1 :(得分:1)
对于简单的事情来说,这非常复杂。要对可被N整除的列表的所有元素求和,您只需要这个尾递归实现:
sum_all( Xs , N , Sum ) :-
sum_all( Xs , N , 0 , Sum )
.
sum_all( [] , _ , S , S ) .
sum_all( [X|Xs] , N , T , S ) :-
X mod N =:= 0 ,
! ,
T1 is T+X ,
sum_all(Xs,N,T1,S)
.
sum_all( [_|Xs] , N , T , S ) :-
sum_all(Xs,N,T,S)
.
非尾递归实现稍微简单一点,但会将其堆栈列入长列表中:
sum_all( [] , _ , 0 ) .
sum_all( [X|Xs] , N , S ) :-
sum(Xs,N,T) ,
( X mod N =:= 0 -> S is T+X ; S is T )
.
你甚至可以做这样的事情来分解"有趣的"列表总和的值:
sum_all(Xs,N,Sum) :-
findall( X , ( member(X,Xs), X mod N =:= 0 ) , L ) ,
sum(L,Sum)
.
sum(L,S) :- sum(L,0,S).
sum( [] , S ,S ) .
sum( [X|Xs] , T ,S ) :- T1 is T+X , sum(Xs,T1,S) .
一旦你有了,那么你可以简单地说:
sum_modulo_N_values( Xs , N ) :-
sum_all(Xs,N,Sum) ,
writenl( sum = Sum )
.
调用类似这样的东西
sum_modulo_N_values( [1,2,5,6,7,10,11,15,31,30] , 5 ) .
您将获得写入控制台的预期sum = 60
。