将原子绑定到Prolog中递归目标的结果

时间:2014-05-09 16:36:16

标签: recursion prolog

所以,让我们说我试图找到低于某个最大数字的所有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编程试图断言自己

有没有办法回归'这里的嵌套递归一直是目标的结果?或者我只想到这一切都错了?

2 个答案:

答案 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

相关问题