■Windowsでランダムを得るならば、powershellを使おう?。。。 ■まず、DOSのランダムはダサいです。 一見、一回づつだと正常に見えますが。。。 > set /a RANDVAL=%RANDOM% % 100 74 > set /a RANDVAL=%RANDOM% % 100 11 ■以下のように実行すると、全く同じ結果が続きます。 ※RANDOMを取り直していません。 > FOR /L %i IN (1,1,100) DO set /a RANDVAL=%RANDOM% % 100 > set /a RANDVAL=1833 % 100 33 > set /a RANDVAL=1833 % 100 33 > set /a RANDVAL=1833 % 100 33 ... ■MSも上記の問題は認識していたらしく、powershellでは「next」で 異なった結果を簡単に得られるようになっています。 VBScript の Rnd 関数の変換 http://technet.microsoft.com/ja-jp/library/ee176946.aspx > powershell PS> $a = new-object random PS> $b = $a.next(1,100); echo $b;$b = $a.next(1,100); echo $b 89 24 PS> $a = new-object random;for($i = 0;$i -lt 100;$i++){$b = $a.next(1,100); echo $b >> args_ps} ■上記を先日のスクリプトでチェック。 たった100のランダムを取得するだけで恐ろしいほどに遅いのですが、その辺はスルーで。。。 バッチのあの気持ち悪いループ構文がいくらかましになっただけ、良しとします。 USP友の会会長が出題した前半戦を解いてみた。 http://d.hatena.ne.jp/labunix/20121111 $ nkf -Lu args_ps > args;wc -l args 100 args $ awk '{print ($1-($1%10))/10}' args | sort -n | uniq -c | awk '{printf "%3d~%3d %3d\n",($2*10),($2*10)+9,$1}' 0~ 9 9 10~ 19 8 20~ 29 8 30~ 39 19 40~ 49 7 50~ 59 12 60~ 69 12 70~ 79 8 80~ 89 10 90~ 99 7 ■大量に実行すると、遅さが目立ちます。 結果が出るだけまだマシですが、軽く1時間を超えるという驚愕の遅さです。 「少なくとも大量の乱数を得る処理はWindowsには無理です。」と素直に諦めましょう。 PS> $a = new-object random;for($i = 0;$i -lt 1000;$i++){$b = $a.next(1,100); echo $b >> args_1000} PS> $a = new-object random;for($i = 0;$i -lt 10000;$i++){$b = $a.next(1,100); echo $b >> args_10000} PS> $a = new-object random;for($i = 0;$i -lt 100000;$i++){$b = $a.next(1,100); echo $b >> args_100000} PS> get-date;$a = new-object random;for($i = 0;$i -lt 1000000;$i++){$b = $a.next(1,100); echo $b >> args_1000000};get-date 2012年11月12日 22:57:15 2012年11月13日 1:07:34 ■ちなみにこのWindows(32bit)に乗る仮想マシン(vmplayer)上の256MBを割り当てたlinuxで実行すると。。。 まあ、確かにしょぼいスペックですけど、vmwre-toolsも入れていないゲストOSにこれだけ差をつけられます。 ちなみに別の64bitのLinuxでは約30秒で処理は完了しますが、スペックの問題では無いのは明らかです。 えっと。。。窓から投げ捨ててもいいですか?Windows先生w。。。 $ time for n in `seq 1 1000000`;do echo $*1;done > args real 3m46.452s user 2m51.479 sys 0m54.239s ■CPUもメモリもほとんど使用していないので、 純粋にロジックが問題なのでしょう(致命的)w。。。 まあ、結果が大事なので、なんとか気を取り直して精度を見てみます。 $ wc -l args_1000;nkf -Lu args_1000 > args 1000 args_1000 $ awk '{print ($1-($1%10))/10}' args | sort -n | uniq -c | awk '{printf "%3d~%3d %3f\n",($2*10),($2*10)+9,$1/10.0}' 0~ 9 9.300000 10~ 19 8.800000 20~ 29 10.700000 30~ 39 8.700000 40~ 49 10.700000 50~ 59 12.100000 60~ 69 9.800000 70~ 79 9.200000 80~ 89 11.400000 90~ 99 9.300000 $ wc -l args_10000; nkf -Lu args_10000 > args 10000 args_10000 $ awk '{print ($1-($1%10))/10}' args | sort -n | uniq -c | awk '{printf "%3d~%3d %3f\n",($2*10),($2*10)+9,$1/100.0}' 0~ 9 8.370000 10~ 19 10.230000 20~ 29 10.570000 30~ 39 10.240000 40~ 49 10.060000 50~ 59 10.580000 60~ 69 10.120000 70~ 79 10.090000 80~ 89 9.870000 90~ 99 9.870000 $ wc -l args_100000; nkf -Lu args_100000 > args 100000 args_100000 $ awk '{print ($1-($1%10))/10}' args | sort -n | uniq -c | awk '{printf "%3d~%3d %3f\n",($2*10),($2*10)+9,$1/1000.0}' 0~ 9 9.039000 10~ 19 10.145000 20~ 29 10.136000 30~ 39 10.358000 40~ 49 10.145000 50~ 59 10.042000 60~ 69 10.189000 70~ 79 10.023000 80~ 89 9.917000 90~ 99 10.006000 ■なぜか407も無駄にループしたようですが。。。 $ wc -l args_1000000 1000407 args_1000000 $ nkf -Lu args_1000000 > args $ awk '{print ($1-($1%10))/10}' args | sort -n | uniq -c | awk '{printf "%3d~%3d %3f\n",($2*10),($2*10)+9,$1/10000.0}' 0~ 9 9.113000 10~ 19 10.153800 20~ 29 10.077100 30~ 39 10.099300 40~ 49 10.120400 50~ 59 10.061200 60~ 69 10.095400 70~ 79 10.113600 80~ 89 10.093600 90~ 99 10.113300 ■精度としては百万未満であれば問題なさそうです。
*1:$RANDOM % 100