「scheme」タグアーカイブ

codeiq @riverplus さんの「ディビジョン・ナイン問題」をrubyとschemeで解いた

回答まとめはこちら

問題は下記。

1 から 4 の数字を使って作る n 桁の整数のうち、9 の倍数となるものの個数を F(n) と定義します。例えば、F(1) = F(2) = 0、F(3) = 10、F(4) = 40 となることが確かめられます。

標準入力から、自然数 n(1 ≦ n ≦ 20)が与えられます。標準出力に F(n) の値を出力するプログラムを書いてください。

1111…から4444…まで全通り生成して数えていては終わらないので、9の剰余で分類します。すなわち、1から4の数字を使って作るn桁の数字のうち、9で割ったあまりがrになるものの個数をF(n,r) とすると、
 \displaystyle F(n+1,r) = \sum^4_{i=1}F(n,r-i)
の漸化式になります。

これをrubyで計算し、F(n,0)を出力するコードが下記。Hashの引数が9で割ったあまりになっています。

n=gets.to_i
h={}
h[1]=h[2]=h[3]=h[4]=1
(1...n).each{|m|
  tmp=Hash.new{|h,k| h[k]=0 }
  h.each{|k,v|
    (1..4).each{|i|
      tmp[(i+k)%9]+=v
    }
  }
  h=tmp
}
puts h[0]

最近始めたschemeで書いたのはこちら、末尾再帰といえば聞こえはいいけど、ループを再帰にして、状態を関数の引数で覚えている、というだけ。もっとスマートに書けると思うんだけど、引数10個くらいだしまぁいいよね、ということで。

(use-modules (ice-9 rdelim))
(define (solve i a0 a1 a2 a3 a4 a5 a6 a7 a8)
    (if (= i 1)
        a0
        (+ (solve (- i 1)
                  (+ a5 a6 a7 a8)
                  (+ a6 a7 a8 a0)
                  (+ a7 a8 a0 a1)
                  (+ a8 a0 a1 a2)
                  (+ a0 a1 a2 a3)
                  (+ a1 a2 a3 a4)
                  (+ a2 a3 a4 a5)
                  (+ a3 a4 a5 a6)
                  (+ a4 a5 a6 a7)))))
(display (solve (string->number (read-line)) 0 1 1 1 1 0 0 0 0))
(newline)