Countinuation Passing to reduce the count of beans

和田栄一先生のブログが大好きです。淡々とした静かな文章の間々に、計算機への愛情が見え隠れする様はたまりません。

そんな和田先生が、節分に関するエントリにて、以下のような問題を取り上げていました。

年の数が多いと, 10の桁の数と1の桁の数を足したものにする. それでも多いときは? もう一度このようにする. たとえば78歳なら78粒は多いので7+8=15とする. それでも多ければ1+5=6とする. 繰り返すのはいやなので閉じた式にする.つまり(modulo n 9)となる.
9歳の子供は9粒だから, (+ (modulo (+ n 8) 9) 1)というべきである. でも今度は0歳が9粒になってしまった. はて? それはさておき...

パラメトロン計算機: 節分

先生のアプローチは繰り返しを避けるということでしたが、この問題は継続渡し形式(continuation passing style)でコードを書くよい題材であるように思い、Schemeで書いてみました*1Schemeの処理系にはGaucheを用いています。

(define (reducebeans x cont)
  (if (>= x 10)
      (reducebeans (modulo x 10)
		   (lambda (n)
		     (reducebeans (quotient x 10)
				  (lambda (m) (reducebeans (+ n m) cont)))))
      (cont x)))

結果もよいようです。

gosh> (reducebeans 78 values)
6
gosh> (reducebeans 15 values)
6
gosh> (reducebeans 9 values)
9
gosh> (reducebeans 0 values)
0

*1:2009/2/8修正。>を>=とした