Clojure で、いろいろな FizzBuzz
数値を一つ渡すと、FizzBuzzの結果を返す関数をいくつか作ってみました。
(fizz-buzz 1) ;=> 1
(fizz-buzz 3) ;=> "fizz"
(fizz-buzz 5) ;=> "buzz"
(fizz-buzz 15) ;=> "fizz buzz"
cond
(defn fizz-buzz [n]
(cond
(zero? (mod n 15)) "fizz buzz"
(zero? (mod n 3)) "fizz"
(zero? (mod n 5)) "buzz"
:else n))
「(zero? (mod ))」の重複が気になります。
condp
最初に↓を思いついたけど、「(zero? (mod )) 」の重複は残っているし、文字数も増えています。けど個人的には、問題がそのままコードになっているようで読みやすいかも。
(defn fizz-buzz [n]
(condp = [(zero? (mod n 3))
(zero? (mod n 5))]
[true true] "fizz buzz"
[true false] "fizz"
[false true] "buzz"
[false false] n))
でも、condpを使わなくても似たように作れるわけで。(Clojure のマップは関数として動作し、引数に一致するキーの値を返す)
(defn fizz-buzz [n]
({[true true] "fizz buzz" ;マップを作成
[true false] "fizz"
[false true] "buzz"
[false false] n}
[(zero? (mod n 3)) ;検索するキーを作成
(zero? (mod n 5))]))
calvaのチュートリアルで見つけた、シンプルな condp。condp の fn に渡る引数の順番に注意。少しハマりました。
(defn fizz-buzz [n]
(condp (fn [a b] (zero? (mod b a))) n
15 "fizz buzz" ;n を15で割ったあまりが0なら"fizz buzz"を返す
3 "fizz"
5 "buzz"
n))
defmulti
同じく、calvaのチュートリアルで見た defmulti を使う例
(defmulti fizz-buzz (juxt #(zero? (mod % 3))
#(zero? (mod % 5))))
(defmethod fizz-buzz [true true] [n] "fizz buzz")
(defmethod fizz-buzz [true false] [n] "fizz")
(defmethod fizz-buzz [false true] [n] "buzz")
(defmethod fizz-buzz [false false] [n] n)
条件分岐なし
Yehonathan Sharvit のブログ で見つけた,if,cond,condpなどを使わない例。
FizzBuzzの答えを先に作って、指定された数値の答えを取ってきて返す。
(defn choice [a b]
(clojure.string/join (or (seq a) (seq b))))
;(choice "" "1") => "1"
;(choice "Fizz" "3") => "Fizz"
(defn fizzbuzz [n]
(let [fizzes (cycle ["" "" "Fizz"])
buzzes (cycle ["" "" "" "" "Buzz"])
words (map str fizzes buzzes)
numbers (map str (rest (range)))]
(take n (map choise words numbers)))) ;ClojureScriptの場合は、choice を max で代用可能。
ディスカッション
コメント一覧
まだ、コメントがありません