2006-08-28
気づいたら会社に一人きり
寂しい><
ユビキタス
間違える!よな!
JavaScript 配列のランダム化
そういやノゾキング作の ruby の spidermonkey binding 使うと簡単に書けるじゃん!と思った。素直に spidermonke インタプリタを使ったほうg(ry
Fisher-Yates の方は綺麗にランダムな結果だなー。あと Fisher-Yates のほうが全然速い。
結果
shuffle
[[825, 790, 747, 576, 622, 874, 1041, 1382, 1964, 1179],
[500, 566, 712, 1147, 903, 702, 910, 1280, 2032, 1248],
[1601, 1555, 1024, 898, 1127, 1344, 1080, 520, 543, 308],
[1140, 1175, 1392, 779, 867, 933, 1168, 1614, 608, 324],
[837, 767, 1076, 1739, 999, 781, 916, 1056, 1199, 630],
[833, 788, 953, 1352, 1599, 746, 896, 1016, 1175, 642],
[1586, 1609, 1184, 1255, 1451, 1845, 280, 308, 343, 139],
[1247, 1314, 1102, 1039, 1162, 1414, 1977, 309, 294, 142],
[1100, 1091, 1412, 779, 858, 925, 1180, 1712, 633, 310],
[331, 345, 398, 436, 412, 436, 552, 803, 1209, 5078]]
shuffleFisherYates
[[974, 990, 1005, 962, 988, 1008, 1036, 1040, 1000, 997],
[1009, 1016, 979, 1006, 979, 1005, 980, 992, 1035, 999],
[986, 977, 954, 1026, 1039, 985, 1000, 995, 996, 1042],
[988, 1000, 1031, 975, 1017, 999, 981, 1018, 1016, 975],
[1049, 1001, 986, 1052, 954, 947, 980, 1015, 982, 1034],
[956, 898, 1071, 1061, 1016, 999, 1017, 962, 989, 1031],
[1036, 991, 984, 969, 996, 1020, 972, 1016, 998, 1018],
[975, 1015, 951, 1015, 1039, 1034, 1001, 973, 1041, 956],
[1021, 1038, 1024, 941, 990, 996, 1022, 998, 975, 995],
[1006, 1074, 1015, 993, 982, 1007, 1011, 991, 968, 953]]
コード
require './spidermonkey'
require 'pp'
cs = SpiderMonkey::Context.new
cs.eval <<-EOF;
Array.prototype.shuffle = function() {
return this.concat().sort(function(){ return Math.random() - 0.5 });
};
Array.prototype.shuffleFisherYates = function() {
var list = this.concat();
var i = list.length;
while (--i) {
var j = Math.floor(Math.random() * (i + 1));
if (i == j) continue;
var k = list[i];
list[i] = list[j];
list[j] = k;
}
return list;
};
var a = new Array(0,1,2,3,4,5,6,7,8,9);
EOF
def shuffle_result(cs, func)
(1..10000).inject([]) do |result,|
cs.evalget("a.#{func}()").to_a.each_with_index do |val, i|
result[val] ||= []
result[val][i] ||= 0
result[val][i] += 1
end
result
end
end
puts 'shuffle'
pp shuffle_result(cs, 'shuffle')
puts 'shuffleFisherYates'
pp shuffle_result(cs, 'shuffleFisherYates')
Ruby の配列~二次元配列をはてなの table 記法に
ときたま使うので。
class Array
def to_hatena_table
if self.first.kind_of?(Array)
self.map {|a| a.to_hatena_table }.join("\n")
else
"|#{self.join('|')}|"
end
end
end
puts ary.to_hatena_table
|181|94|62|59|67|57|44|32|51|353|
|217|149|77|101|50|62|65|81|145|53|
|160|158|71|80|116|182|24|43|51|115|
|132|141|171|67|59|78|128|191|13|20|
|102|106|91|228|59|56|59|51|222|26|
|58|82|81|112|347|50|54|63|74|79|
|33|40|51|65|118|293|62|83|100|155|
|48|89|155|66|79|86|402|24|23|28|
|45|100|178|34|56|70|88|333|45|51|
|24|41|63|188|49|66|74|99|276|120|
みたいなー。
Math.random の間違った考察
http://subtech.g.hatena.ne.jp/secondlife/20060827/1156679433
まず一つめは Array.prototype.sort は破壊的だったということを忘れていたこと。二つめは Array.prototype.sort に関数を渡した場合、
sort メソッドは、指定された Array オブジェクト内の要素を並べ替えます。このメソッドを実行しても、新しい Array オブジェクトは作成されません。
引数 sortFunction に指定する場合は、次の戻り値を返すような関数を指定する必要があります。
- 1 つ目の引数が 2 つ目の引数よりも小さい場合は、負の値を返す関数。
- 2 つの引数が等しい場合は 0 を返す関数。
- 1 つ目の引数が 2 つ目の引数よりも大きい場合は、正の値を返す関数。
という仕様だということ。
つまりこうしなくちゃダメだった。
var a = new Array(0,1,2,3,4,5,6,7,8,9);
for(var i = 0; i < 1000; i++) console.log(a.concat().sort(function(){ return Math.random() - 0.5 }));
とする必要があった。というわけで1000回ループまわして統計を取ったらばっちりランダムに!ならねええええ。なんなんだ…
-
0
1
2
3
4
5
6
7
8
9
0
181
94
62
59
67
57
44
32
51
353
1
217
149
77
101
50
62
65
81
145
53
2
160
158
71
80
116
182
24
43
51
115
3
132
141
171
67
59
78
128
191
13
20
4
102
106
91
228
59
56
59
51
222
26
5
58
82
81
112
347
50
54
63
74
79
6
33
40
51
65
118
293
62
83
100
155
7
48
89
155
66
79
86
402
24
23
28
8
45
100
178
34
56
70
88
333
45
51
9
24
41
63
188
49
66
74
99
276
120
出社
そういえばどうしてアレ系のイベントって T-shirt を配布したがるんだろう。当日ぐらいしか普通の人は着れないし、また当日着てるのもスタッフ+αぐらいだ。家の寝間着つーのもちょっとなぁ。T-shirtいらないから1000円安くして欲しい!という人の方が多そう、特に学生はお金無いし…。
そんなぽっくんはアレT-shirt 着まくり今日もLLRing のだお><。自転車通勤(電車じゃ恥ずかしすぎる)でアレな会社じゃないと無理だわぁ…。mixi, hatena, るびカ, YAPC, LL Ring, LL night が最近のアレTヴァリエーション。