Arantium Maestum

プログラミング、囲碁、読書の話題

Clojure入門 - Project Eulerを解いてみる 問16

第十六問。

21000のすべての桁の数の和を求める。

やはりOverflowが問題になるので、数字を一桁の数のリストで表し、そのリストに対して2倍にするという操作を定義する。あとは'(2)からはじめて1000回繰り返して、足し合わせるだけ。

(require '[clojure.math.numeric-tower :as math])

(defn double [n]
  (* 2 n))

(defn get-tens [n]
  (-> n
      (/ 10)
      (math/floor)))

(defn get-ones [n]
  (rem n 10))

とりあえずヘルパー関数。

(defn double-list [col]
  (let [doubled-digits (map double col)
        ones (map get-ones doubled-digits)
        tens (map get-tens doubled-digits)
        tens-shifted (concat (rest tens) '(0))]
    (if (zero? (first tens))
      (map + ones tens-shifted)
      (cons (first tens) (map + ones tens-shifted)))))

一桁の数のリストに対する、「倍にする」という操作。すべての数を2倍にして、10の位と1の位に分け、ずらして足し合わせる。

(->> '(2)
     (iterate double-list)
     (take 1000)
     (last)
     (apply +))

あとは使うだけ。

更新: 問十三であやぴーさんにコメント頂いたbigintを使ってしまえば非常に楽:

(->> 2
     (bigint)
     (repeat 1000)
     (apply *)
     (str)
     (map #(Character/digit % 10))
     (apply +))