FizzBuzz問題のRubyによる普通の解答例

FizzBuzz問題(フィズバズ問題)とは、

1から100までの数をプリントするプログラムを書け。ただし3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」とプリントし、3と5両方の倍数の場合には「FizzBuzz」とプリントすること。

というものです。だいぶ前に話題になりました。元ネタは以下のサイト:

どうしてプログラマに・・・プログラムが書けないのか?
Why Can't Programmers.. Program? (原文)

ここでは、問題の「FizzBuzz」のところを「Fizz,Buzz」に変えた(単語の間にカンマを入れた)ものに対する、いくつかの解答例を紹介します。もちろん、以下の解答をオリジナルの問題の解答に書き直すのは簡単です。

解答例

その1

最も普通の方法。

1.upto(100){ |i|
  if i % 3 == 0 && i % 5 == 0  # 3の倍数かつ5の倍数
    puts "Fizz,Buzz"
  elsif i % 3 == 0  # 3の倍数(かつ、5の倍数でない)
    puts "Fizz"
  elsif i % 5 == 0  # 5の倍数(かつ、3の倍数でない)
    puts "Buzz"
  else # 3の倍数でも5の倍数でもない
    puts i
  end
}

以下は、上のプログラムにおいて、繰り返し(upto)の部分を配列操作に置き換えた方法:

array = Array.new(100){|i| i+1}
array.map!{ |i|
  if i % 3 == 0 && i % 5 == 0  # 3の倍数かつ5の倍数
    "Fizz,Buzz"
  elsif i % 3 == 0  # 3の倍数(かつ、5の倍数でない)
    "Fuzz"
  elsif i % 5 == 0  # 5の倍数(かつ、3の倍数でない)
    "Buzz"
  else  # 3の倍数でも5の倍数でもない
    i
  end
}
print array.join("\n")

その2

メソッドの再帰的定義による方法。

def fizzbuzz(n)
  fizzbuzz(n-1) if n > 1
  if n % 3 == 0 && n % 5 == 0
    puts "Fizz,Buzz"
  elsif n % 3 == 0
    puts "Fizz"
  elsif n % 5 == 0
    puts "Buzz"
  else
    puts n
  end
end

fizzbuzz(100)

その3

論理演算子が条件を評価する順序を利用した方法。

1.upto(100){ |i|
  puts (i%3 == 0 && i%5 == 0 && "Fizz,Buzz") \
    || (i%3 == 0 && "Fizz") || (i%5 == 0 && "Buzz") || i
}

これをワンライナーにすると、以下のようになります:

> ruby -e "1.upto(100){
|i| puts (i%3==0&&i%5==0&&\"Fizz,Buzz\")
||(i%3==0&&\"Fizz\")||(i%5==0&&\"Buzz\")||i}"

表示の都合上、改行を入れていますが、コマンドは1行で入力します。

その4

配列を利用した方法。

1.upto(100){ |i|
  array = []
  array.push("Fizz") if i % 3 == 0
  array.push("Buzz") if i % 5 == 0
  if array.size > 0 
    puts array.join(",")  # 配列の要素を「,」で結合
  else
    puts i
  end
}

以下のプログラムは、上のプログラムと全く同じで、記号の使い方を変えただけです:

1.upto(100){ |i|
  array = []
  array << "Fizz" if i % 3 == 0
  array << "Buzz" if i % 5 == 0
  puts array.size > 0 ? array * "," : i
}

その5

以下は、配列の要素が存在しないときnilを返すことを利用した解答例:

1.upto(100){ |i|
  a = ["Fizz,Buzz"]
  b = ["Fizz"]
  c = ["Buzz"]
  puts [a[i%15], b[i%3], c[i%5], i].compact.first
}

これを、変数を省略してワンライナーにすると、以下のようになります:

> ruby -e "1.upto(100){
|i| puts [[\"Fizz,Buzz\"][i%15], [\"Fizz\"][i%3], [\"Buzz\"][i%5], i].compact.first}"

表示の都合上、改行を入れていますが、コマンドは1行で入力します。

その6

剰余(%記号等)を用いないFizzBuzz問題の解答例。Fizz, Buzzの出現に一定の周期性(15で一巡する)があることに着目:

j = 1
1.upto(100){ |i|
  case j
  when 15
    puts "Fizz,Buzz"
    j = 0
  when 3, 6, 9, 12
    puts "Fizz"
  when 5, 10
    puts "Buzz"
  else
    puts i
  end

  j += 1
}

最終手段

出力結果をまるごとprint文で出力する。あるいは、出力結果が書かれたテキストファイルを読み込む。ある意味、確実な方法です。

print DATA.read

__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
(以下略)

【theme : プログラミング
【genre : コンピュータ

プロフィール

よしいず

Author:よしいず
MATHEMATICS.PDFというウェブサイトを運営しています。

管理の都合上、トラックバックとコメントはオフにしてあります。ブログ経験者なら分かっていただけると思いますが、スパム(アダルトやその他の宣伝)ばかりなのが現実です。

リンクは自由です。当サイトの記事に対する間違いの指摘・意見・感想などを述べた記事からのリンクは歓迎です。ただし、ブログ記事アップ直後はミスが多く、頻繁に修正します。場合によっては削除する可能性もあります。その際、何も断りもなく修正・削除しますがご了承ください。内容を参考にする場合には投稿後一週間ほど様子を見てからにしてください(笑)。

記事の間違いを指摘するときは、その具体的箇所、理由(仕様に反するなど)・根拠(参考にした文献など)、代替案(同じ結果を得るための正しいやり方)も教えてください。そうしないと、(指摘される側および第三者はその時点では無知の状態なので、)どこが間違いなのか分かりませんし、本当に間違っているのかどうかが判断・検証できません。実際、間違いだと指摘されたことが結局は正しかったというケースもありますので。

このブログのタイトル一覧

リンク
月別アーカイブ
カテゴリ
最新記事
検索フォーム
RSSリンクの表示