@mbratchが言ったこと。
あなたが計算しているのは三角数です。宿題が三角数に関するものであり、再帰的思考の学習に関するものではない場合、次のように単純に計算できます。
triangular_number(N,R) :- R is N * (N+1) / 2 .
再帰的思考を学んでいる可能性が高い場合は、これを試してください。
sum(N,R) :- % to compute the triangular number n,
sum(N,1,0,R) % - invoke the worker predicate with its counter and accumulator properly seeded
.
sum(0,_,R,R). % when the count gets decremented to zero, we're done. Unify the accumulator with the result.
sum(C,X,T,R) :- % otherwise,
C > 0 , % - assuming the count is greater than zero
T1 is T+X , % - increment the accumulator
X1 is X+1 , % - increment the current number
C1 is C-1 , % - decrement the count
sum(C1,X1,T1,R) % - recurse down
. % Easy!
追加するために編集:
または、カウント ダウン アプローチを好む場合は、次のようにします。
sum(N,R) :- sum(N,0,R).
sum(0,R,R). % when the count gets decremented to zero, we're done. Unify the accumulator with the result.
sum(N,T,R) :- % otherwise,
N > 0 , % - assuming the count is greater than zero
T1 is T+N , % - increment the accumulator
N1 is N-1 , % - decrement the count
sum(N1,T1,R) % - recurse down
. % Easy!
これらは両方とも末尾再帰です。つまり、プロローグ コンパイラはそれらを反復に変換できます (詳細については、Google の「末尾再帰の最適化」を参照してください)。
アキュムレータを削除したい場合は、次のようにする必要があります。
sum(0,0).
sum(N,R) :-
N > 0 ,
N1 is N-1 ,
sum(N1,R1) ,
R is R1+N
.
少し単純ですが、再帰ごとに別のスタック フレームが消費されます。N の値が十分に大きい場合、実行はスタック オーバーフローで失敗します。