どう書く?org(重複なし乱数)

こんな所があった>http://ja.doukaku.org/

どう書く?org」へようこそ!このサイトは出されたお題をいかに解くか競い合う、プログラマのためのコロシアムです

わー、初心者お断りっていう感じかな?
なんとなく、入りづらいので日記で問題を解いてみる。
そのうちのここhttp://ja.doukaku.org/46/lang/ruby/の問題をやってみた
(これぐらいなら、すぐにでも分かる感じ)

問題

単純に、重複せずに数字を表示できるような関数を作れば良いみたい

いろんな人の実装(勝手に自分も混ざる)

def bingo1 n #rubykitchさんの作った関数
  (1..n).to_a.sort_by { rand}
end

def bingo2 n #riowさんの作った関数
  xs = *1..n
  n.times{|i| xs << xs.slice!(rand(n-i))}
  xs
end

def bingo3 n #自分で作った関数(というより、recipebookに載っていたのを記憶していたもの)
  xs = *1..n
  xs.each_index { |i| j = rand(i+1); xs[i],xs[j] = xs[j], xs[i]}
end

すごい人の中に混ざると自分もすごくなったような気分??(・_・)

速度はどうなんだろ

こんな感じのコードを付け足して試してみる

if $0 == __FILE__
  require 'benchmark'
  Benchmark.bmbm do |x|
    def x.f(name,i,arg)
      report(name.to_s) { send("bingo"+(i+1).to_s,arg) }
    end
    n=10000
    printf "N = %s\n" %n
    %w{ rubykitch riow trotr}.each_with_index{ |name,i| x.f(name,i,n)}
  end
end

結果

N = 10000
Rehearsal ---------------------------------------------
rubykitch   0.070000   0.020000   0.090000 (  0.089359)
riow        0.550000   0.000000   0.550000 (  0.551619)
trotr       0.060000   0.000000   0.060000 (  0.061744)
------------------------------------ total: 0.700000sec

                user     system      total        real
rubykitch   0.060000   0.000000   0.060000 (  0.060777)
riow        0.540000   0.020000   0.560000 (  0.555098)
trotr       0.060000   0.000000   0.060000 (  0.060849)

感想

これなら、ぜったいrubykitchさんの書き方だね。*1楽だし。


*1:1.9ならArray#shuffleの方が楽