読者です 読者をやめる 読者になる 読者になる

No Programming, No Life

新しいNPNLです。http://d.hatena.ne.jp/fumokmm/ から引っ越してきました。

Buzzになる数字をn個挙げるをClojureで

Clojure FizzBuzz

このシリーズの一覧はこちら

ソース

解説

まずはこれ。

(defn to-fizz-buzz-str [x]
  [x, (cond
        (= (mod x 15) 0) "FizzBuzz"
        (= (mod x 3) 0)  "Fizz"
        (= (mod x 5) 0)  "Buzz"
        :else            (str x)) ] )

これは、引数の数値(ここではx)をFizzBuzz文字にマップする関数で、結果はインデックス付きのベクタで返す。

例:

(to-fizz-buzz-str 9)      ;=> [9 "Fizz"]
(to-fizz-buzz-str 10)     ;=> [10 "Buzz"]
(to-fizz-buzz-str 15)     ;=> [15 "FizzBuzz"]
(to-fizz-buzz-str 100002) ;=> [100002 "Fizz"]

で、次にさっき定義した、to-fizz-buzz-strを利用して、FizzBuzzの無限リストを変数fizz-buzz-listに束縛。

(def fizz-buzz-list
  (map to-fizz-buzz-str (iterate inc 1)))

ここで、

(iterate inc 1)

は、1から1ずつ増分していく無限シーケンスを生成している部分。

fizz-buzz-listは無限に続くので、取り扱い注意。利用する際はtakeとかして使うように。

例:

(take 5 fizz-buzz-list)
;=> ([1 "1"] [2 "2"] [3 "Fizz"] [4 "4"] [5 "Buzz"])

to-only-buzz-listは、引数で受け取ったリストから "Buzz" の部分だけ抜き出す関数です。

(defn to-only-buzz-list [list]
  (map first (filter #(= (last %) "Buzz") list)))

そしてこれらを組み合わせて、doseqで出力。

(doseq [x (take 10 (to-only-buzz-list fizz-buzz-list))]
  (println x))

ここでは、

  • fizz-buzz-list(無限のFizzBuzzリスト)を、to-only-buzz-listに変換
  • そこからtake10(シーケンスの先頭から10要素だけ取得)した結果をxとして取得
  • それをprintlnで出力

しています。

結果:

5
10
20
25
35
40
50
55
65
70

おわりに

Clojure面白くなってきた。
Happy Coding!