読者です 読者をやめる 読者になる 読者になる

One Source

プログラミング、映画、海外ドラマ、読書 etc...

RubyでFizzBuzz書いてみた


RubyFizzBuzz書いてみます

FizzBuzzとは?

  • 1 から順に数を出力
  • 3 で割り切れるならばFizzと出力
  • 5 で割り切れるならばBuzzと出力
  • 3 でも 5 でも割り切れる場合はFizzBuzzと出力

といった感じの要件を満たすプログラムです。
僕も新卒のOJTの際に書いてみてって言われてJava,JavaScriptで書いた覚えがあります。

現在仕事でRubyを使っているので、初心にもどって書いてみます。
まずはよく見かける形でコーディング

fizz_buzz.rb
(1..100).each do |i|
    if i % 15 == 0
        puts "FizzBuzz"
    elsif i % 3 == 0
        puts "Fizz"
    elsif i % 5 == 0 
        puts "Buzz"
    else
        puts i
    end
end

ふむ
まずこの(1..100)というRangeをターミナルから入力して自由に決めたい。
あとは、ちょっとずつメソッドに切り出してみよう。
加えてRubyのメソッドを存分に使う形で組み替えてみます。

ということで、うねうねした結果がこちら。

fizz_buzz.rb
def console(args)
  raise "argument is nil" if args.nil?
  puts map_upto args.to_i
end

def map_upto(max)
  (1..max).map { |n| fizzbuzz n }
end

def fizzbuzz_hash
  { 'fizz' => 3, 'buzz' => 5 }
end

def fizzbuzz(n)
  fizzbuzz_hash
    .map { |str, val| str if (n % val).zero? }.join
    .tap { |str| break str.empty? ? n : str }
end

if __FILE__ == $0
  console ARGV[0]
end

初めとぜんぜん違う感じになりました。
一つずつ見ていきます。

fizz_buzz.rb
def console(args)
  raise "argument is nil" if args.nil?
  puts map_upto args.to_i
end

ターミナル上に表示させるためのメソッド。
consoleというメソッドの引数にターミナル上での入力を渡す予定です。
このスクリプトを実行した際に、引数がなければ例外をあげます。
to_i で引数をStringからIntegerへ変更しmap_uptoメソッドへ渡しています。
※引数が文字列であった場合でもto_iすることで0となります。

続いてこちら

fizz_buzz.rb
def map_upto(max)
  (1..max).map { |n| fizzbuzz n }
end

maxが先程map_uptoメソッドへ渡された値となります。
もとのコードで(1..100)となっている部分をmaxで置き換えた感じです。
1から順番に渡された引数までをnという値で順次fizzbuzzメソッドへ渡しています。
ここの戻り値がコンソール表示される値となります。

続いてこちら

fizz_buzz.rb
def fizzbuzz_hash
  { 'fizz' => 3, 'buzz' => 5 }
end

こちらは単に固定値のHashを返すだけのメソッドとなります。

続いてこちら

fizz_buzz.rb
def fizzbuzz(n)
  fizzbuzz_hash
    .map { |str, val| str if (n % val).zero? }.join
    .tap { |str| break str.empty? ? n : str }
end

まずfizzbuzz_hashが先程のHashとなります。
mapの部分で、引数で受け取ったnが3,5で余りなく割り切れるかどうかでstr、つまりHashのキーの部分を返しています。

mapは、表示する値を配列にして返すので、例えばnが15の場合、['fizz','buzz']という配列を返すことになります。

対して、余りが生じるような場合は、空の配列を返すことになります。
この配列をjoinすることで文字列として返すことが出来ます。
最後にtapを使うことで、文字列が空の場合は引数を、そうでない場合は文字列を返しています。

でもって最後

fizz_buzz.rb
if __FILE__ == $0
  console ARGV[0]
end

__FILE__ は現在実行しているプログラムのファイル名を表していて
$0は実行時に指定されたファイル名を相対パスで表しているそうです。
これらが等しい場合に、consoleメソッドに入力値を表すARGV[0]を渡しています。
では最後に結果を見てみます。

ruby fizz_buzz.rb 15
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz

いけてるようですね。
時間があればテストも追加しようと思います。

あとは、fizzbuzz_hashメソッドのHashの中身の順番に依存しているのをなんとかしたいですね。
単純に中身を逆にするとfizzbuzzを表示する時にbuzzfizzになってしまうので、なにか良い方法はないものですかね。。。

 

qiitaに同様の記事を投稿しています。

こっちのほうが読みやすいかも

qiita.com

初めての投稿:ブログの目的と自己紹介

 

◆ブログの目的

  • 思考の整理

     - 今の働き方は別に会社に所属していなくてもできるのでは? etc...

  • ちょっとした技術のTips&備忘録

     - 技術者としての成長と共有

  • 未経験文系エンジニアとして

     - 未経験でもやれるぞ!ってな話

  • 転職

     - エージェントいる?みたいな話

 

目的は思考の整理や日々の振返りですが、ちょっとした技術のTipsや備忘録、最近の関心事なんかもつらつら連ねていこうと思います。

あとは、未経験文系エンジニアとして働いてきたことや転職についてなんかもふれていければなって思います。

 

◆自己紹介

出身地:香川県

住居 :東京都

年齢 :25歳

職業 :ITコンサルタント

              -現在2社目

趣味 :読書、映画・海外ドラマ鑑賞、コードリーディング、フットサル 

では、これからよろしくお願いします。