ランダム順列

id:succeed:20060127#1138378979
2番目のやつは間違ってるような。
ソートアルゴリズムが安定だと小さい数が先に出てくる確率が高いし、
そうでなくてもランダムではない。
例えば n=2 で、ソートアルゴリズムが安定で、
rand() の返り値が k 通りあるとすると
(k+1)/(2k) の確率で先に 1 が出る。
普通は k が大きすぎて分からないけど

my $n = 2;
my $m = 1;

my @array = map {[$_, int(rand(2))]} (1..$n);
@array = sort {$a->[1] <=> $b->[1]} @array;
foreach(0..$m-1){
  print $array[$_]->[0], "\n";
}

とかにして100回ほど実験すると 3/4 くらいの割合で 1 が出る。


関数型っぽく実装するなら木構造を使うのが無難かと。
以下 ocaml

module M = Map.Make
(struct
   type t = int
   let compare x y = x - y
 end)

let find x env = try M.find x env with Not_found -> x
let rec iter n env acc =
  if n <= 0 then acc
  else let r = Random.int n + 1 in
  iter (n-1) (M.add r (find n env) env) (find r env :: acc)

let random_list n =
  iter n M.empty []

アルゴリズムは3番目とほぼ同じで時間はO(n*log n)。