ruby本体にメソッドを足してみる
Rubyのオープンクラスというのは、メソッドを勝手に足していいってことらしいので、RubyレベルとCレベルの2通りの方法でやってみた。Cのほうは破壊検査的な学習法かも。
Numeric#dividable?というメソッドがあってもいいだろうと思って、
class Numeric def dividable?(n) self % n == 0 end end ary = (1..100).map do |i| case when i.dividable?(15) then "FizzBuzz" when i.dividable?(3) then "Fizz" when i.dividable?(5) then "Buzz" else i end end # puts ary
のように書いた。このメソッド定義を、numeric.cにnum_dividableという関数で加えてみた。
--- a/numeric.c +++ b/numeric.c @@ -361,6 +361,19 @@ num_modulo(VALUE x, VALUE y) return rb_funcall(x, '%', 1, y); } +// experimental + +static VALUE +num_dividable(VALUE x, VALUE y) +{ + int m = FIX2INT(rb_funcall(x, '%', 1, y)); + if (m == 0) { + return Qtrue; + } else { + return Qfalse; + } +} + /* * call-seq: * num.remainder(numeric) => result @@ -3118,6 +3131,7 @@ Init_Numeric(void) rb_define_method(rb_cNumeric, "div", num_div, 1); rb_define_method(rb_cNumeric, "divmod", num_divmod, 1); rb_define_method(rb_cNumeric, "modulo", num_modulo, 1); + rb_define_method(rb_cNumeric, "dividable?", num_dividable, 1); rb_define_method(rb_cNumeric, "remainder", num_remainder, 1); rb_define_method(rb_cNumeric, "abs", num_abs, 0); rb_define_method(rb_cNumeric, "magnitude", num_abs, 0);
makeしたら、
$ ./ruby -e 'puts 10.methods' |grep -i div div divmod fdiv dividable? $
とか、
10.dividable?(3) =>false 10.dividable?(2) =>true 10.dividable?(4) =>false 10.dividable?(5) =>true
とかなって、いちおう動いている。FizzBuzzの上限を100じゃなくて500万ぐらいにして計測したら、
$ time ./ruby fizz.rb real 0m4.498s user 0m4.324s sys 0m0.104s $ time ./ruby fizz2.rb real 0m0.572s user 0m0.536s sys 0m0.020s
と、速いような気もする。しかし、ふつうに「割ってゼロか?」と書いたものに比べると、むしろ遅くなっている。
require 'benchmark' n = 1000000 Benchmark.bm do |x| x.report { (1..n).each do |i| if ((i % 3) == 0) then "Fizz" end if ((i % 5) == 0) then "Buzz" end end } x.report { (1..n).each do |i| if i.dividable?(3) then "Fizz" end if i.dividable?(5) then "Buzz" end end } end
$ ./ruby fizz_bench.rb user system total real 0.360000 0.000000 0.360000 ( 0.381753) 0.820000 0.000000 0.820000 ( 0.844860)
Ruby 1.9では算術命令はメソッド呼ばずにやる最適化をしているから、メソッドを呼ぶのより速いってことかしら。