今更FizzBuzzをやってみる
今日初めて面接を担当することがあった。
で、色々聞いてみたのだけど、やっぱりFizzBuzzについて聞いてみたくなったので
次のような条件で15分ほど時間をとって、コードを書いてもらった。
3で割り切れる場合は 「Fizz」(Bizz Buzz の場合は 「Bizz」)、5で割り切れる場合は 「Buzz」、両者で割り切れる場合は 「Fizz Buzz」 (Bizz Buzz の場合は 「Bizz Buzz」)を数の代わりに発言しなければならない。
http://ja.wikipedia.org/wiki/Fizz_Buzz
- 1から100以上で上の条件を満たすこと。
- 利用する言語は何でもよい
- 手元の紙に手書きでよい
- 1から100までは、引数で渡してもいいし、ただのループでも良い
空いた時間が暇だったので、自分でも書いてみた
(1..100).each do |i| p i % 15 == 0 ? "FizzBuzz" : i % 3 == 0 ? "Fizz" : i % 5 == 0 ? "Buzz" : i end
(1..100).each do |i| p i % 15 == 0 ? "FizzBuzz" : i % 3 == 0 ? "Fizz" : i % 5 == 0 ? "Buzz" : i end
普通の書き方。irbから実行するので、無理やり1行にしてみた。
三項演算子の入れ子になっている所がパッと見、わかりにくい。
id:goking さんが面白い書き方をしていた。
- "001”* n の文字列から [nil, nil, "Fizz", ...] の配列を作成
- "00001" * m の文字列から[nil, nil, nil, nil, "Buzz", ...] の配列を作成
- 両方の配列をArray#zipにより、2次元配列にまとめる
- 両方に値がある場合は文字列を連結、片方に文字列がある場合はその文字列、お互いにnilならば数字を出力
- n, m は適当な任意の数字
というふうに実現してた。
それを思い出しながら自分で再実装してみた。
([nil,nil,"Fizz"]*50).zip([nil,nil,nil,nil,"Buzz"]*50).each.with_index(1){|v,i|p v[0]&&v[1]?v[0]+v[1]:v[0]?v[0]:v[1]?v[1]:i}
([nil, nil, "Fizz"] * 50).zip([nil, nil, nil, nil, "Buzz"] * 50).each.with_index(1) {|v,i| p v[0] && v[1] ? v[0] + v[1] : v[0] ? v[0] : v[1] ? v[1] : i }
FizzとBuzzの配列はめんどくさいから直接作っている。
書いてみて思ったこと
配列で添字を取るときは、each_with_indexをいつも使っていたけど、each.with_indexとかけることに気がついた。
初期値を与えるなら、each.with_index(1)で1から連番で添字を取得できる。
今まで知らなかったAPIや書き方がわかったところが良かったな。