LoginSignup
8
7

More than 5 years have passed since last update.

Ruby1.9の勉強に使った FizzBuzz サンプル

Posted at

Golf

fizzbuzz_golf.rb
1.upto(100){|i|puts"#{[:Fizz][i%3]}#{[:Buzz][i%5]}"[/.+/]||i}

->、to_proc

fizzbuzz_proc.rb
def fizzbuzz
  -> n { n % 15 == 0 ? :FizzBuzz : n % 5 == 0 ? :Buzz : n % 3 == 0 ? :Fizz : n }
end
puts (1..100).map(&fizzbuzz)

オープンクラス、エイリアス、===

fizzbuzz_open.rb
class Fixnum
  IS_FIZZBUZZ = -> m, n { n % m == 0 }.curry
  alias _to_s to_s
  def to_s
    case self
    when IS_FIZZBUZZ[15]
      "FizzBuzz"
    when IS_FIZZBUZZ[5]
      "Buzz"
    when IS_FIZZBUZZ[3]
      "Fizz"
    else
      _to_s
    end
  end
end
puts [*1..100]  

例外、===

fizzbuzz_rescue.rb
def fizzbuzz(limit)
  e ||= 0
  ( e += 1 ) > limit ? return : raise
rescue lambda { |_| e % 15 == 0 }
  puts "FizzBuzz" ; retry
rescue lambda { |_| e % 5  == 0 }
  puts "Buzz"     ; retry
rescue lambda { |_| e % 3  == 0 }
  puts "Fizz"     ; retry
rescue lambda { |_| e }
  puts e          ; retry
end
fizzbuzz(100)

Enumerator、メソッドチェイン

fizzbuzz_chain.rb
puts 1.upto(100).with_object(nil)
                .map { |n, o| ( o ||= [] ) << :Fizz if n % 3 == 0; [n, o] }
                .map { |n, o| ( o ||= [] ) << :Buzz if n % 5 == 0; [n, o] }
                .map { |n, o| ( o || [n] ) * "" }

Converter、Filter、to_proc

fizzbuzz_converter.rb
class Converter

  def initialize
    @specs = []
  end

  def specs( value , &cond )
    @specs << lambda { |e| cond[e] ? value : nil }
  end

  def to_proc
    lambda { |e| 
      conved = @specs.map{ |spec| spec[e] }.join
      conved.empty? ? e : conved
    }
  end

end

if __FILE__ == $0

  arg   = ARGV[0] || 100
  limit = arg.to_i

  fizzbuzz  = Converter.new

  fizzbuzz.specs( "Fizz" ) { |n| n % 3 == 0 }
  fizzbuzz.specs( "Buzz" ) { |n| n % 5 == 0 }

  puts 1.upto(limit).map(&fizzbuzz)

end

クラス化

fizzbuzz_class.rb
class FizzBuzz

  def initialize( from = 1, to = 30 )
    @from, @to = [ from, to ].minmax
    block_given? ? yield( self ) : self
  end

  def spec( out, &cond )
    ( @specs ||= [] ) << lambda { |e| cond[ e ] ? out : nil }
  end

  def edit( &editor )
    @editor  = editor
  end

  def editor
    @editor || lambda { |e| e }
  end

  def format( &formatter )
    @formatter = formatter
  end

  def output( &formatter )
    @formatter = formatter if formatter
    result = @from.upto( @to ).map( &self )
    @formatter ?  result.map { |e| @formatter[ e ] } : result
  end

  def to_proc
    lambda { |i| 
      outs = @specs.map { |spec| spec[ i ] }
      editor[ i, outs ]
    }
  end  

end

実行方法

ruby fizzbuzz_main.rb

fizzbuzz_main.rb
require "./fizzbuzz"

# Pattern 1 : (1..30)
FizzBuzz.new do |fizzbuzz|

  fizzbuzz.spec( :Fizz ) { |e| e % 3 == 0 }
  fizzbuzz.spec( :Buzz ) { |e| e % 5 == 0 }

  fizzbuzz.edit { |i, outs| 
    out = outs.join
    out.empty? ? i : out
  }

end.output do |e|
  puts e
end

# Pattern 2 : (31..69)
fizzbuzz = FizzBuzz.new(31, 69)
fizzbuzz.edit { |i, outs| 
  out = outs.join
  out.empty? ? i : out
}
fizzbuzz.spec( :B ) { |e| e % 5 == 0 }
fizzbuzz.spec( :F ) { |e| e % 3 == 0 }
result = fizzbuzz.output
puts result * " "

# Pattern 3 : (70..105)
FizzBuzz.new(70, 105) do |fizzbuzz|

  fizzbuzz.spec( :Pizz ) { |e| e % 3 == 0 }
  fizzbuzz.spec( :Quzz ) { |e| e % 5 == 0 }
  fizzbuzz.spec( :Razz ) { |e| e % 7 == 0 }

  fizzbuzz.edit { |i, outs| 
    out = outs.join
    out.empty? ? i : out
  }

  fizzbuzz.format { |e| puts e }

end.output
8
7
0

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
8
7