LoginSignup
17
8

More than 5 years have passed since last update.

今更FizzBuzz問題?ファンファンのファン問題やろうぜ

Last updated at Posted at 2018-09-03

はじめに

この記事は新人プログラマ向けに問題と回答例を紹介するものです。
これを読んで少しでもプログラムに造詣が深まれば幸いです。
ベテランの方からの別解もお待ちしています。
今回は個人的好みでrubyで書いています。
言語は特に問いません。

FizzBuzz問題とは

wikipediaから引用して説明すると

3で割り切れる場合は「Fizz」、5で割り切れる場合は「Buzz」、両者で割り切れる場合(すなわち15で割り切れる場合)は「Fizz Buzz」

を表示するようなプログラムを組むことです

例えば以下のような感じですね(今回はこっちは焦点じゃないのでツッコミはなしの方向で)

fizzbuzz.rb
def fizzbuzz(num = 0)
  num.times do |i|
    i+=1
    if i % 15 == 0
      puts "fizzbuzz"
    elsif i % 5 == 0
      puts "buzz"
    elsif i % 3 == 0
      puts "fizz"
    else
      puts i
    end
  end
end

num = ARGV[0].to_i
fizzbuzz(num)
結果
$ ruby fizzbuzz.rb 20
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16
17
fizz
19
buzz

プログラマ界隈では常識的な問題として誰もが1度は解いたことのある問題のはずです(多分)
僕も新人教育などで度々例題として挙げますが、いい加減古臭いし新鮮な問題を出したい…

ファンファンのファン問題とは

そこで「ファンファンのファン問題」です
これは皆さんご存知の某アイドルユニットの曲からヒントを得て考えてみました

「ファンファンファン ファンファンのファン」の形をできるだけスマートに表示せよ

規則性としては

  • はじめに「ファン」を3回表示
  • 次に半角スペースを表示
  • 更に「ファン」を2回表示
  • 「の」を1回表示
  • 「ファン」を1回表示
  • 改行する

という順序です

例1

何のひねりもなく書いたらこんな感じ

fanfannofan1.rb
(1..10).each do |i|
  puts 'ファンファンファン ファンファンのファン'
end
結果
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン

ベタ書きで全くスマートじゃない
「ファン」という同じワードを何回も書いているのでDRYじゃない

例2

fanfannofan2.rb
(1..5).each do |i|
  print 'ファン'

  if i%3 == 0
    print ' '
  end

  if i%5 == 0
    puts 'のファン'
  end

end
結果
ファンファンファン ファンファンのファン

「のファン」の部分がスマートじゃない
またこれは1回目しかうまくいかずこれ以降ループまわしていくとズレてしまう

結果
ファンファンファン ファンファンのファン
ファン ファンファンファン ファンのファン
ファンファン ファンファンファン のファン
ファンファンファン ファンファンのファン

例3

fanfannofan3.rb
(1..10).each do |i|
  (1..6).each do |j|
    print 'ファン'

    if j%3 == 0
      print ' '
    end

    if j%5 == 0
      print 'の'
    end
  end

  puts
end
結果
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン

無事に規則に沿った形を表示できています
が、2重ループで表現している部分がスマートではないですね

例4

fanfannofan4.rb
# 「の」が入るタイミングを事前に配列に確保
threshold_array = Array.new
(1..20).each do |n|
  # 「の」が挟まるタイミングは等差数列の式により
  # an = a + (n-1)d
  # an = 5 + (n-1)6
  # an = 6n-1
  threshold_array.push((6 * n) - 1)
end

(1..60).each do |i|
  print 'ファン'

  # 3の倍数の時に半角スペース or 改行が挟まる
  if i%3 == 0
    if i%2 == 0
      puts
    else
      print ' '
    end
  end

  if threshold_array.include?(i)
    print 'の'
  end
end
結果
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン
ファンファンファン ファンファンのファン

事前に判定配列を作っておくことで2重ループがなくなりました:smile:

おわりに

自分で問題を考えておいて、全然スマートな解答が思いつかず四苦八苦しました:sweat:
結構色んな解法がありそうだなーと思うので是非みなさんポジティブなパッションで挑戦してみてください!

17
8
15

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
8