シャッフルについて

http://www.hyuki.com/d/200510.html#i20051020190000

以下、サイズをsとする。
正しいシャッフルは長さsの置換全体(対称群)からランダムに選ばなければならない。

void shuffle(int music[], int size)
{
    int i;
    for (i = 0; i < size; i++) {
        int r = random(0, size);
        int m = music[i];
        music[i] = music[r];
        music[r] = m;
    }
}

このプログラムはi step目でmusic[i]とmusic[r]を置き換えている。ということはs step終了時にはs回の互換が行われている。
従ってsが偶数なら偶置換のみ, sが奇数なら奇置換のみが行われる。よって、これは完全なシャッフルでは無い。以上。

嘘。間違えた。自分自身との交換があるので、偶置換も奇置換も取り得る。
正しくは以下か。
i step目でrが取る値をr_iとする。するとr_iの取り方はs^s通り。一方、長さがsの対称群の要素数は1-sまでの順列と考えてよいので、s!通り。s ≧ 3のときs^s/s!は割り切れないので等確率で取れていないことになる。

本当にシャッフルしたいならば、i step目で長さがiの置換からランダムに選んでおいて、その0〜i-1とiをランダムに入れかえればいいわけか。成る程。