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

fizzbuzzでもいろんな書き方がありますね。今の僕ならこう書く

なんとなくネットサーフィンしていたら上記の記事に出会い、
なるほど色んな書き方がある物だなと感じました。
でも個人的にはあまり好きではない書き方だったので
(応用2のFizzBuzzFozzの時にメソッドを呼び分けているのですが
このロジックは抽象化してメソッドにいれたほうが好みなので)
今の自分ならこう書くだろうというのを書いてみました。


※使い慣れないrubyなので慣用表現に誤りがあるかもしれませんが
そこはご了承ください。

#!/usr/bin/ruby                                                                                                                       
puts '【基本】「まず基本的な FizzBuzz 問題を実現するプログラムを書きなさい'                           
class Array                                                                                                                               
  def fizzbuzzify                                                                                                                       
    self.map do |i|                                                                                                                      
      case true                                                                                                                            
      when i % 15 === 0 then                                                                                                    
        'FizzBuzz'                                                                                                                         
      when i % 5 === 0 then                                                                                                      
        'Buzz'                                                                                                                               
      when i % 3 === 0 then                                                                                                      
        'Fizz'                                                                                                                                
      else                                                                                                                                    
        i                                                                                                                                       
      end                                                                                                                                    
    end                                                                                                                                      
  end                                                                                                                                        
end                                                                                                                                          
puts (1..100).to_a.fizzbuzzify                                                                                                   
                                                                                                                                              
puts '【応用1】「同じ処理を 100 まで、200 まで、1000 までの配列にそれぞれ適用しなさい」'    
puts (1..100).to_a.fizzbuzzify                                                                                                   
puts (1..200).to_a.fizzbuzzify                                                                                                   
puts (1..1000).to_a.fizzbuzzify                                                                                                 
                                                                                                                                                
puts '【応用2】「1000 までの場合だけ、30 の倍数の時に "FizzBuzzFozz" にしなさい」'              
class Array                                                                                                                               
  def fizzbuzzfozzify                                                                                                               
    if self.count != 1000 then                                                                                                    
      return self.fizzbuzzify                                                                                                        
    end                                                                                                                                      
    self.map do |i|                                                                                                                      
      case true                                                                                                                            
      when i % 30 === 0 then                                                                                                    
        'FizzBuzzFozz'                                                                                                                  
      when i % 15 === 0 then                                                                                                    
        'FizzBuzz'                                                                                                                         
      when i % 5 === 0 then                                                                                                      
        'Buzz'                                                                                                                               
      when i % 3 === 0 then                                                                                                      
        'Fizz'                                                                                                                                
      else                                                                                                                                    
        i                                                                                                                                       
      end                                                                                                                                    
    end                                                                                                                                      
  end                                                                                                                                        
end                                                                                                                                          
puts (1..100).to_a.fizzbuzzfozzify                                                                                            
puts (1..200).to_a.fizzbuzzfozzify                                                                                            
puts (1..1000).to_a.fizzbuzzfozzify         

puts '【応用3】「1000 までの場合だけ、標準出力でなく、hoge.txt に出力するようにしなさい」'  
class FizzbuzzFozzOutput                                                                                                        
  def initialize(array_or_maxnum)                                                                                             
    case array_or_maxnum                                                                                                         
    when Array then                                                                                                                   
      @array = array_or_maxnum                                                                                               
    when Integer then                                                                                                                
      @array = (1..array_or_maxnum).to_a                                                                                  
    else                                                                                                                                      
      @array = (1..(array_or_maxnum.to_i)).to_a                                                                         
    end                                                                                                                                      
  end                                                                                                                                        
  def execute                                                                                                                            
    if @array.count === 1000 then                                                                                           
      File::open('hoge.txt', 'w') {|f|                                                                                               
        f.puts @array.fizzbuzzfozzify                                                                                           
      }                                                                                                                                         
    else                                                                                                                                      
      puts @array.fizzbuzzfozzify                                                                                               
    end                                                                                                                                      
  end                                                                                                                                        
end                                                                                                                                          
FizzbuzzFozzOutput.new(100).execute                                                                                    
FizzbuzzFozzOutput.new(200).execute                                                                                    
FizzbuzzFozzOutput.new(1000).execute        


まず、基本のFizzBuzzのロジックをオープンクラスで標準のArrayクラスのインスタンスメソッドとして追加します。
(標準のArrayに置くべきか、別のFizzBuzzArray的なクラスを作った方がいいかはちょっとよくわかりません。)
配列をFizzBuzz化する、という意味で Array#fizzbuzzify という名前を付けています。
なんとなく動詞っぽい気がしますが英語が得意でないので実際のところどうかはよく知りません。


応用1ではそれぞれの配列作ってfizzbuzzifyするだけです。


応用2では新たなロジックが出てくるので、それをまたArrayクラスのインスタンスメソッドとして追加します。
今度は Array#fizzbuzzfozzify としました。
1000までの場合という意味を厳密に考えるとめんどくさいので、とりあえず
1000個の要素の配列だった場合にFizzBuzzFozzが出るようにしています。
それ以外の場合は Array#fizzbuzzify に委譲します。
これで呼び出し側ではメソッドを呼び分ける必要はなく、どんな配列でも
Array#fizzbuzzfozzify を呼べばいいようになりました。


続いて応用3ですが、今度は出力先が変わります。
出力するメソッドをどこに置くかですが、Arrayに置くのもどうかと思ったので
新規で FizzbuzzFozzOutput クラスを作り、excecute メソッドで出力先が変わるロジックを吸収することにしました。
あと色気を出して、コンストラクタに配列だけじゃなく数値でも受け取れるようにしています。
いやらしいですね。