• ベストアンサー

1から20までの整数から、重複なくランダムに3つ数づつを取り出す

1から20までの整数から、重複なくランダムに3つの数を取り出したいんですけど、簡単に出来るのでしょうか ?

質問者が選んだベストアンサー

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.5

高級言語は配列のランダム機能があったり するのでみなさんローレベルのランダム化 にはなれていないのでしょうか? 残念ながらみなさんのコーディングには 問題があります。 重複したら、リトライするという方式は 一番してはいけない方法です。 1000個の要素から1000個抜き出すときに、 999番目の要素は約0.1%の確率でしか重複 しない数値がヒットしません。 要素数が増えると加速度的に時間のかかる プログラムです。 また#4さんのように、適当な回数要素数 の中で入れ替えをするというの、よさそうに 見えますが、初期要素からいれかわらない 可能性が強く、かなり偏りがでるランダム です。 そもそも3つの要素を抜き出すのであれば ランダム処理は3回やればじゅうぶんのはずです。 以下の例はざっとかいたものなのでバグがある かもしれませんがランダム化のフローを 理解いただく参考までに。 <script language="javascript"> function rndview(min,max,num){ var a=new Array(); for (var i=min;i<=max;i++){ a[i]=i; } for (var i=min;i<=(min+num-1);i++){ var p1 = i+Math.floor(Math.random() * (max-i+1)); var p2 = a[i]; a[i]=a[p1]; a[p1]=p2; } txt=""; for (var i=min;i<=(min+num-1);i++){ txt+=(txt=="")?a[i]:","+a[i]; } alert(txt); } </script> <input type="button" value="ランダム" onClick="rndview(1,20,3)">

その他の回答 (12)

noname#17489
noname#17489
回答No.13

ソートが重いならこちらをどうぞ。 配列から既に選択した要素を取り除きながらランダムに選んでいく方法です。 ただ、10000個のとかから選ぶとなると要素数10000個の配列を用意しなければなりませんが。 function rnd_sel(min,max,num) {  var arr = new Array();  var results = new Array(num);  for (var i=0;i<max-min+1;i++) arr[i]=i+min;  for (var i=0;i<num;i++) {   var rnd = Math.floor((max-min+1-i)*Math.random());   results[i] = arr[rnd];   var tmp = arr[max-min-i]; //last   if (rnd!=(max-min-i)) arr[rnd] = tmp;  }  return results; } //インデントは全角スペースなのでご注意を...

  • UKY
  • ベストアンサー率50% (604/1207)
回答No.12

No. 9 の、比較関数でランダムな比較結果を返すというのはアイデアとしてはいいと思いますけど、sort メソッドの仕様としては比較関数が 'a consistent comparison function' でない場合の動作は 'implementation-defined' だから、やっぱりまずいと思います。 確かに主要なブラウザではエラーは出ないようですが、仕様上エラーが出ないという保証はないわけですし。 (ところで、単にランダムな比較結果を返すだけならわざわざ 100 倍して引かなくても function() { return Math.random() - 0.5; } で十分だと思います)

回答No.11

IE,NN,FFで確認してますがエラーは出ないはずです。 それとも、sort(-1.3...)とか直接値を代入した場合の話ですか? それはエラーになりますよw sortには比較式 return (b - a); など比較関数で 負数~0~正数の範囲でソート順序を返すようにします。 あとはご自分でお調べ下さい・・ .

  • B-Happy
  • ベストアンサー率0% (0/1)
回答No.10

横からすいません。 arr.sort(function(){return Math.random()*100 - Math.random()*100;}); って、どういうことなのでしょうか。 sort(-1.3...)とかだと、もちろんエラーになってしまうのですが。

回答No.9

シャッフルの手法としては不完全なんですが この程度のケースなら充分かと思います。 <script language="javascript"> arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]; arr.sort(function(){return Math.random()*100 - Math.random()*100;}); document.write(arr[0]+","+arr[1]+","+arr[2]); </script> .

noname#19175
noname#19175
回答No.8

http://otd8.jbbs.livedoor.jp/javascript/bbs_tree?base=15264&range=1 内容が似てますが、、、? あちらのBBSでは、回答はつきそうにないですけどね。 方法は何種類かありますが、どの方法が良いか、というのは状況次第じゃないでしょうか? >重複したら、リトライするという方式は一番してはいけない方法です。 基本的にはそうなんですが、分母がとてつもなく大きく、取り出したい数(分子)がごく小さな場合は、 重複したらリトライの方が早いことがあります。 (重複確認の方法によっては、とてつもなく遅くなります) http://itmedia.okwave.jp/kotaeru.php3?q=2037528 ちょっと、こういう疑問がありますので、このBBSでの回答は控えさせて頂きます。 (アルゴリズム自体は一般的ですが、、、) 1つの方法として、参考URLを見てください。

参考URL:
http://www.openspc2.org/reibun/javascript/form_textarea/015/
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.7

>高級言語は配列のランダム機能があったりするのでみなさんローレベルのランダム化にはなれていないのでしょうか? >残念ながらみなさんのコーディングには問題があります。 >重複したら、リトライするという方式は一番してはいけない方法です。 >1000個の要素から1000個抜き出すときに、999番目の要素は約0.1%の確率でしか重複しない数値がヒットしません。 >要素数が増えると加速度的に時間のかかるプログラムです。 もちろんおっしゃることは、わかります、 #3のプログラムについて言えば、ある範囲の中から範囲に比べて少ない数が選ばれるということを想定したものです。 例えば、 1~10000(あるいはもっと大きい?)までの範囲の数の中から、3コ数を選びたいだけなのに、いちいちその範囲の数を重複させないためだけに候補を作るのは、いかにもムダです。 逆に、範囲のほとんど全数が必要になるなら、#3は、向かないのはおっしゃる通りですね。 そういったことは、ケースバイケースのように思われます。 #4については、いちいち評を挟みませんでしたが、#5でおっしゃる通りでかなり高コストだなあと思っていました。

  • don_go
  • ベストアンサー率31% (336/1059)
回答No.6

1~20までの値と乱数の結果を入れる為の配列テーブルを用意して 1~20までの数値と乱数値をセットした後、乱数テーブルの値を用いて ソートすれば求める結果が得られると思いますが?

回答No.4

少し違う考え方を書いておきます。 トランプと同じようなものだと考えて、20要素の整数を入れておく配列を作り、そこに1から20までの数値を入れておきます。それから乱数で0~19までの値を2つ作り、その値が違っていたらそれに対応する配列の位置の値を入れ換えます。これはトランプのシャッフルのようなイメージです。なので回数が多ければ多いほど順序がバラバラになります。で、十分にシャッフルしたら先頭の3つの値を残してあとは全部捨てれば終りです。 例) ボタンを押すたびに1~20の整数が重複なくランダムに3つカンマ区切りでテキストエリアに出て来ます。 <html> <head> <title>Random Test</title> <script language="JavaScript"> <!-- function setrand() { var max = 20; var a = new Array(max); var i; for (i = 0; i < max; i++) a[i] = i + 1; for (i = 0; i < 100; i++) { var p1 = Math.floor(Math.random() * max); var p2 = Math.floor(Math.random() * max); if (p1 != p2) { var tmp = a[p1]; a[p1] = a[p2]; a[p2] = tmp; } } document.f.t.value = a[0] + "," + a[1] + "," + a[2]; } // --> </script> </head> <body> <form name="f"> <input type="button" value="PushMe" onClick="setrand()"> <input type="text" name="t"> </form> </body> </html>

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

//配列=randomInt(範囲の下限, 範囲の上限, 個数) function randomInt(startRange, endRange, num){ if(endRange-startRange+1<num){//ムリ return []; } var a = new Array(); var c = 0; while(c < num){ var r = Math.round((endRange-startRange)*Math.random()+startRange); if(a[r]==undefined){//まだ無い a[r]=r; c++; } } var ret = new Array(); c=0; for(var x in a){//整理 ret[c++]=x; } return ret; } var rand3; //10~20までの範囲の重複しない3つの数の配列:randomInt(10, 20, 3) rand3=randomInt(10, 20, 3); alert(rand3.join(",")); for(i=0;i<rand3.length;i++){ alert(rand3[i]); }

関連するQ&A