• 締切済み

N個の整数の並び替えるアルゴリズム

N個の整数1,2,3,...Nから任意のM個(M < N )を取り出すのですが、重複はダメという場合、どのようなアルゴリズムがあるでしょうか。重複ありなら、Nまでの一様乱数を発生させて整数化して取り出すことは可能です。今回は重複なしです。重複があったらやり直して重複なしになるまでやり続けるというのはダメだなと思っています。 データ処理言語のRはコマンド1つのようですが。言語はFortranなのですが、アルゴリズムのレベルだとどれでも同じと考えています。よろしくお願いします。

みんなの回答

  • pooh26
  • ベストアンサー率49% (66/134)
回答No.4

f272さんが紹介しているのは、Fisher–Yates shuffle ですね。 Wikipediaにもありますが、実装さえ間違えなければ大丈夫です。

skmsk1941093
質問者

お礼

回答ありがとうございました。標準のアルゴリズムのようですね。 たぶん、python, Rなどのライブラリは間違いのないものが実装されていてそのような個別パーツは自分で考えて作り出すのではなく、出来上がっている間違いのないものを使うべきだということではないかと思います。Fortranにもそういうライブラリ集があるのでしょうか。大昔からテキストに載っているようなものの以外にですが。

  • f272
  • ベストアンサー率46% (8530/18260)
回答No.3

乱数発生が完全に一様であれば,このアルゴリズムですべての場合が等確率で出てきますから,これ以上よけいなことをする必要はありません。

skmsk1941093
質問者

お礼

回答ありがとうございます。すでに実績のある標準アルゴリズムということですね。これをサブルーチン化して外部から呼び込めるようにしたいと思います。

  • f272
  • ベストアンサー率46% (8530/18260)
回答No.2

こんな感じ? program test implicit none integer,parameter :: n=10 integer,parameter :: m=5 integer :: t, i, j integer,dimension(n) :: ar=(/(i,i=1,n)/) real :: rnd(n) call random_number(rnd) do i=n,2,-1 j=int(rnd(i)*i)+1 t=ar(i) ar(i)=ar(j) ar(j)=t enddo print*,(ar(i),i=1,m) end program test

skmsk1941093
質問者

お礼

回答ありがとうございます。このアルゴリズムは乱数に基づいた交換というシャッフルをカードの枚数回、しかもすべてのカードが必ずシャッフルの対象となるようにすればそのカードの先頭から順番に抜き出せば重複のないランダムな取り出しになっているということですね。 この場合、最初が順番どおりになっているので初期の影響が完全に消えるということをするため、再度シャッフル(2枚の交換)をした方がいいというようなことはないでしょうか。どこまでやると最初の条件の影響が消えていくのだろうと思いますが。案外すぐに消えるものでしょうか。

回答No.1

ざっと、 今取り出した物aを、 既に取り出した物bと比較して、 a=bのとき、aを破棄する。 を、bがm個になるまで繰り返す。

関連するQ&A

専門家に質問してみよう