- ベストアンサー
乱数について
今、あるデータの順番をばらばらにするプログラムを作ろうとしています。 たとえば、a,b,c,dとあったら、d,b,c,aとするように、この時考えられるプログラムは、データの数だけ配列を用意して、乱数で、どのデータを出力させるかを決定し、出力し終わったら、その配列のところに印を立てて、次にくるデータに対して、2重にならないように順次、出力していく方法が考えられるのですが。。。 膨大なデータをこのように、すると、二重になる確立が出力するたびに、高くなっていって、なかなか終わらなくなってしまいます。 そこで、残ったデータから、ランダムに選び出すアルゴリズムまたは、関数はないでしょうか?よろしくお願いします。
- Nickee
- お礼率79% (107/134)
- C・C++・C#
- 回答数4
- ありがとう数4
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
データの数だけ配列を用意して、乱数で適当な回数、場所を入れ替えて (シャフルして)から 先頭から順番に取れば?
その他の回答 (3)
- ymmasayan
- ベストアンサー率30% (2593/8599)
No.1の方の方式(仮にAとします)とNo.3の方の方式(仮にBとします)がよく使われます。 バッチ的な処理ではAが適しています。(前処理に時間がかかってもいいが、処理をはじめたら高速) 一方、リアルタイム処理ではBが適しています。(前処理がいらず、毎回一定時間で処理可能) 全部終わったら又、対象を広げて続けると言う場合、Aでは、又、シャッフルが必要ですが、Bでは対象範囲を広げるだけでいいので一瞬ですみます。 特別にまずいという理由がなければ、B方式をお勧めします。私はいつもB方式を使っています。
お礼
なるほど。勉強になります。 2種類の方法がでているので、ポイントはあげられませんが、ありがとうございました。m (_ _) m
乱数の範囲を狭めていき、選択されたものを次に選択されない位置に移動させるようにします。 #define N 10 int a[N]; int i, r, t; for (i = 0; i < (N - 1); i++) { // i の位置から最後までの中で1つ選択 r = i + rand() % (N - i); // 選択したものを i の位置と交換する t = a[i]; a[i] = a[r]; a[r] = t; } for (i = 0; i < N; i++) { 出力(a[i]); }
お礼
ほ~ 非常に勉強になりました。そういう方法もあるんですね。 ありがとうございました。
- ranx
- ベストアンサー率24% (357/1463)
実データとは別に、それに対するインデックスまたはポインタの配列を作ります。 例えば 1 - a 2 - b 3 - c 4 - d という感じです。 乱数で、インデックスを選択し、対応するデータを出力します。 例えば上の例で3が選択されたらcです。 選択されたインデックスを取り除きます。すると 1 - a 2 - b 4 - d cはインデックスなし となります。 残ったインデックスから乱数で一つを選択し、インデックスが 無くなるまでこれを続けます。
お礼
>残ったインデックスから乱数で一つを選択し いや、その残ったインデックスから、どのように選択するのか知りたかったものですから。。乱数で選択すると、重なる部分が出てくるわけじゃないですか。そうすると、選択するたびに、重なる部分が多くなるので、処理速度が遅くなるので、残ったインデックスからどのように、乱数で選択するのかを聞きたかったのですが。。。 ご意見 ありがとうございました。
関連するQ&A
- 乱数ってなんですか?
なんどもすいません。配列のはなしなんですが、まずAという配列の中の0~10番目の中身をランダムに動かして、Bという配列に再編成させたいのですが、 乱数を使えば簡単になるよと知り合いにはいわれたのですが、乱数がどうゆうもの だかあまりよくわかりません。 自分は今VC++のMFCで作ってるのですが、乱数自体がわからないので教えてください。 それとこの方法でいくと日本語の時は配列を2個づつランダムに変えることになると思うのですが、それはぜんぜん予想もできません。教えていただけると助かります。お願いします。
- ベストアンサー
- C・C++・C#
- 配列と乱数を使ったプログラム
配列と乱数を使ったプログラムについて 今年からプログラミングについて勉強する事になったのですが、 配列と乱数を上手く使うことができません。やりたいと思っていることが おみくじのプログラムで 大吉 中吉 小吉 という3つの配列からウィンドウ上にランダムで 一つ表示するというプログラムです。 【おみくじの結果は *** です。】 ←***の部分がランダムに配列から表示される結果です。(分かりづらなかったら、ごめんなさい) 病欠で2週ほど授業に出席する事が出来なかったので、配列と乱数についてよく分かりません。 PENというソフトで学習しているので、出来るならPENにそって教えてもらえると、嬉しいです。 宜しくお願いしますm(_ _)m
- ベストアンサー
- C・C++・C#
- 重複せず担当を割り振りたい
人数をX人とします。 担当が同数のX個あります。 これらを「ランダム」に「1人1担当」で「過去に担当したものは重複しない」結果を出すプログラムを検討しています。 何かいいアルゴリズムや方法はないでしょうか? 例:4人(A、B、C、D) 出力結果 担当1:A→B→C→D 担当2:B→D→A→C 担当3:C→A→D→B 担当4:D→C→B→A このような結果を、ランダムで出力したいです。
- ベストアンサー
- その他([技術者向] コンピューター)
- プログラミングの乱数
c言語、c++の乱数rand()の使い方がよくわかりません。わかりやすい説明をお願いします。 あと、プログラミングが得意な方にお願いです。 [0,1]乱数で平均と分散を求めるプログラムを配列なしで作ってください。
- ベストアンサー
- 科学
- 重複しない乱数を作り配列に入れる(AS3.0)
Flash Pro CS5 AS3.0 で記述しています。 1~10の整数をランダムかつ重複せずに配列に格納したいと考えています。 そこで,ネット上で参考になるソースを見つけ, 以下のように書き直しました。 var int_a = new Array(); var int_b = new Array(); function RandomInt():void{ //ここだけ変更すればよい var maxN:Number = 10;//乱数の最大値 //0~maxNの数字を全部配列に入れる for (var i:int=0; i< maxN; i++) { int_a[i] = i+1; } var j:Number = 0; var a_length:Number = int_a.length; //要は配列をシャッフルする while (a_length) { var int_r:Number = Math.floor(Math.random()*(maxN+1-j)); //乱発生した整数を配列int_bに順番に入れ、int_aから削除する int_b[j] = int_a.splice(int_r, 1); j++; //配列int_a内の数字が一つずつ減っていく a_length = int_a.length; } //ここで配列int_bがシャッフルされた trace(int_b); } RandomInt(); としました。 しかし出力結果がなぜか 8,2,4,9,,7,6,5,10,3,1のように抜けている部分があり, 次のフレームで for(var j:int=1; j <= 10; j++){ trace(int_b[j]); } として確認してもやはり 2 4 9 7 6 5 10 3 1 となってしまします。 どの部分がおかしいのか教えていただきたいです。 また,乱数発生の部分で Math.floor(Math.random()*(maxN+1-j)); という風に記述してあったのですが,ここは間違いではないのでしょうか? jを引いていくと発生する乱数の範囲が徐々に狭くなっていってしまうと思ったのですが; それとも元のソースコードを使って ttp://www.renowan.com/blog/?p=143 0~9までの乱数を発生させてそれぞれに1を足す方が簡単でしょうか? よろしくお願いします。
- ベストアンサー
- Flash
お礼
なるほど!以外に単純でしたね。 ありがとうがございました。