1〜100の整数をランダムに並び替え

ランダムに並んだ1〜100の整数に用があった。

取り急ぎ、思いつくまま作ってみる。

max=100
a=Array.new
while a.size<max
  i=rand(max)+1
  a<<i if not a.include?i
end

1〜100の整数がユニークに揃うまで、100以下の乱数を発生させ続ける。ループ回数は確率任せという乱暴な手口だが、レンジが1〜100なら実行時間はたかが知れる。

ループを一定回数にするなら、あらかじめ用意した1〜100の配列をランダムに取り出して並べ直せばいい。

max=100
a=Array.new
b=[*(1..max)]

1.upto(max){|i|a<<b.slice!(rand(max-i))}

破壊的メソッドArray#slice!で配列bの任意位置の要素を切り出す。指定位置は、maxからiを引くことでループ毎に配列bが削られていく分を補正する。

むろん、n回のループで1〜nが揃う方がいいので、下の方が無駄がない。

……のだが、maxが3回参照されるのは違和感がある。maxは、配列b自身が自分の配列長として知る情報だ。同様に(max-i)もまた、b自身が知っている情報であるはず。

max=100
a=Array.new
b=[*(1..max)]

1.upto(b.size){a<<b.slice!(rand(b.size-1))}

とか、こねくり回してたら。

a=[*(1..100)].sort{rand(3)-1}

こんなんでいいことに気がついた。