配列シャッフル

単純で正しそうなものが正しいとは限らない - Radium Software

英語のもとページ読んでないけど。


インデックスを足していくか引いていくかはどうでもよくて、むしろ本質が紛らわしくなってる気がする。

def shuffle1(a)
  a.size.times{|i|
    n = rand(a.size)
    t = a[i]; a[i] = a[n]; a[n] = t
  }
  a
end

def shuffle2(a)
  a.size.times{|i|
    n = i + rand(a.size - i)
    t = a[i]; a[i] = a[n]; a[n] = t
  }
  a
end

def test
  cards = 1..4
  h = Hash.new{0}

  100000.times{
    a = yield(cards.to_a)
    h[a[0]]+=1
  }
  p h
end

p "shuffle1"
test{|cards| shuffle1(cards)}

p "shuffle2"
test{|cards| shuffle2(cards)}
ruby shuffle.rb
"shuffle1"
{1=>24886, 2=>29201, 3=>24514, 4=>21399}
"shuffle2"
{1=>24809, 2=>25052, 3=>25215, 4=>24924}


俺的ナイーブなシャッフルは、配列からランダムな要素を切り出して新しい配列を作る感じ。

def shuffle3(a)
  b = a.dup
  ret = []
  until b.empty?
    ret << b.slice!(rand(b.size))
  end
  ret
end

メモリがーとかは考えません。安いから買え。