FizzBuzz問題(Ruby)
「FizzBuzz 問題」という有名な問題があることを知りました。
Fizz Buzz - Wikipedia
Wikipedia から引用すると、
プレイヤーは円状に座る。最初のプレイヤーは「1」と数字を発言する。次のプレイヤーは直前のプレイヤーの次の数字を発言していく。ただし、3で割り切れる場合は 「Fizz」(Bizz Buzz の場合は 「Bizz」)、5で割り切れる場合は 「Buzz」、両者で割り切れる場合は 「Fizz Buzz」 (Bizz Buzz の場合は 「Bizz Buzz」)を数の代わりに発言しなければならない。発言を間違えた者や、ためらった者は脱落となる。
これをプログラミングするということですね。
別に問題はないでしょう。例えば
for i in 1..50 if i % 15 == 0 print "Fizz Buzz, " elsif i % 3 == 0 print "Fizz, " elsif i % 5 == 0 print "Buzz, " else print "#{i}, " end end
でいいですね。結果は
1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, Fizz Buzz, 16, 17, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26, Fizz, 28, 29, Fizz Buzz, 31, 32, Fizz, 34, Buzz, Fizz, 37, 38, Fizz, Buzz, 41, Fizz, 43, 44, Fizz Buzz, 46, 47, Fizz, 49, Buzz,
となります。ただ、これも Wikipedia によると、「2分以内に解け」とか「%(剰余)演算子を使うな」とか「ワンライナーで」とか、色々条件をつけることがあるそうです。そうかあ。逆にできるだけ凝るとかね。プログラマーの数だけ解法があるとか何とか。
剰余演算子(%)を使わない場合
考えてみました。でも、ただ単に割り切れるかどうかを判定するメソッドを作っただけ。
class Integer def divisible?(x) (self - self.div(x) * x) == 0 end end for i in 1..50 if i.divisible?(15) print "Fizz Buzz, " elsif i.divisible?(3) print "Fizz, " elsif i.divisible?(5) print "Buzz, " else print "#{i}, " end end
※追記 これ、おもしろかった。プロで書けないとか、何ですかそれは。そういうこともあるのかあ。
※再追記(2018/2/4)
Ruby 的にもっとも素直に書くとこんな感じ?
1.upto(50) do |i| st = if i % 15 == 0 "FizzBuzz, " elsif i % 3 == 0 "Fizz, " elsif i % 5 == 0 "Buzz, " else "#{i} ," end print st end
※再々追記(2018/2/5)
この方が Ruby っぽいか。
def trans(i) if i % 15 == 0 "FizzBuzz" elsif i % 3 == 0 "Fizz" elsif i % 5 == 0 "Buzz" else i.to_s end end p [*1..50].map{|i| trans(i)}
最後をこう書けたらいいのになあ…
p [*1..].map {|i| trans(i)}.take(50)
いや、しかしこう書けるのか。
p 1.step.lazy.map{|i| trans(i)}.first(50)
うーむ、lazy…。
※再再再追記(2019/12/27)
case ~ when を使って。
fizzbuzz = (1..50).map do |i| case when (i % 15).zero? "FizzBuzz" when (i % 3).zero? "Fizz" when (i % 5).zero? "Buzz" else i.to_s end end p fizzbuzz
基本か。