Arantium Maestum

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

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

第二十二問

名前のリストが入ったテキストファイルがあって、その名前をソートし、位置のインデックスと文字のスコアをかけあわせた数字の和を求める。

データを望むフォーマットにしてしまえばあとは楽、という種類の問題。まずはその部分のコード。

(require '[clojure.string :as str])

(defn split-by-commas [s]
  (str/split s #","))

(defn truncate-first-last [s]
  (subs s 1 (dec (.length s))))

(def data
  (->> (slurp "names.txt")
       (split-by-commas)
       (map truncate-first-last)))

名前が引用符に囲まれているので取り除く必要がある以外はあまり特筆すべきポイントがない。

truncate-first-lastは(->> s (rest) (drop-last) (apply str))の方がわかりやすいだろうか。あるいは、最初と最後のキャラクターを取り除く、ではなく正規表現などを使って引用符を除く、あるいは大文字ローマ字のみ摘出する、とした方が良かったかもしれない。

次はAを1、Bを2などに置き換えて、文字列を文字の値の和として評価する関数:

(defn score [s]
  (->> s
       (map int)
       (map #(- % 64))
       (apply +)))

まさにそのまんま、と言える。

あとはデータをソートしてスコアを評価して、ソートされた順位とスコアをかけあわせて足し合わせる。

(->> data     ;データを
     sort     ;ソートして
     (map score)     ;スコアを評価し
     (map * (map inc (range)))     ;順位とスコアをかけあわせ
     (apply +))     ;足し合わせる

まさにそのまんまと(以下略