Rubyで組み合わせと順列
Array#combination(組み合わせ)
Arrayからn個の組み合わせを取り出すことができる
ruby-1.9.2-p0 > array = [1,2,3] => [1, 2, 3] ruby-1.9.2-p0 > array.combination(2) => #<Enumerator: [1, 2, 3]:combination(2)> ruby-1.9.2-p0 > array.combination(2).to_a => [[1, 2], [1, 3], [2, 3]]
Array#product(順列)
複數のArrayの順列
ruby-1.9.2-p0 > array = [0,1,2,3] => [0, 1, 2, 3] ruby-1.9.2-p0 > array.product(array) => [[0, 0], [0, 1], [0, 2], [0, 3], [1, 0], [1, 1], [1, 2], [1, 3], [2, 0], [2, 1], [2, 2], [2, 3], [3, 0], [3, 1], [3, 2], [3, 3]]
これで何をしたかったのかというと多次元配列(Narray)において、ある座標?(2,2)とかの近傍値の計算を順列で計算出来ないかなと思ったわけです。
たとえば
0,0 | 1,0 | 2,0 |
0,1 | 1,1 | 2,1 |
0,2 | 1,2 | 2,2 |
だとして(1,1)の8近傍の座標を知りたい時に
(1,1)の値をそれぞれ+-1する。
(0,0) (2,2)
その時
0~2の値の順列が全座標と等しくなるので
ruby-1.9.2-p0 > array = (0..2).to_a => [0, 1, 2] ruby-1.9.2-p0 > array.product(array) => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
のそれぞれの座標に対して処理を与えればよいです。
ただ適応出来ない場合もあります
その後一般化
これまでのだと座標が(1,1)のように同じでないと使い物にならないので、こうします
ruby-1.9.2-p0 > narray = NArray.float(4,4).collect{rand(10)} => NArray.float(4,4): [ [ 2.0, 7.0, 5.0, 8.0 ], [ 2.0, 8.0, 4.0, 6.0 ], [ 8.0, 1.0, 8.0, 2.0 ], [ 1.0, 4.0, 9.0, 4.0 ] ] ruby-1.9.2-p0 > narray[2,1] => 4.0
4x4のグラフから座標(2,1)の8近傍を取りたい場合
2-1と2+1で横軸を1~3として
1-1と1+1で縦軸を0~2とする。
その上で
ruby-1.9.2-p0 > w = (1..3).to_a => [1, 2, 3] ruby-1.9.2-p0 > h =(0..2).to_a => [0, 1, 2] ruby-1.9.2-p0 > w.product(h) => [[1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2], [3, 0], [3, 1], [3, 2]]
でいける