添え字を使わずに2次元配列を回転・反転させる方法
ここでは、2次元配列とは Array の Array を意味することにします。外側の親配列が同じ長さの小配列を持っている、
matrix = [[1,2,3],[4,5,6],[7,8,9]]
のようなやつですね。
視覚的にはこんな数字の表を表していると考えましょう。1 5 9 の軸が主対角線で 3 5 7 の軸が副対角線です。
1 2 3 4 5 6 7 8 9
はじめに表示用の関数を定義しておきます。
def ap ary ary.each do |row| puts row.join end puts end
ap matrix 123 456 789
この配列を回転させたり、オモテウラを反転させたりしていきます。
こういった処理は添え字の変換で行うのが一般的なのでしょうが、あえて添え字を使わずに実装したいと思います。コードは Array クラスのメソッドとして追加していきます。
左右反転
それぞれの小配列を reverse で逆順にします。垂直の軸でひっくりかえすので vflip という名前にしましょう。
class Array def vflip map(&:reverse) end end
ap matrix.vflip 321 654 987
上下反転
今度は親配列を逆順にします。
class Array def hflip reverse end end
ap matrix.hflip 789 456 123
転置
主対角線にそって裏返して、行を列に、列を行にする変換です。すでに Array クラスに transpose メソッドが用意されています。
ap matrix.transpose 147 258 369
右に90°回転
転置の後に左右反転を行うと右に90°回転させたのと同じことになります。想像してみましょう。
class Array def right_rotate transpose.vflip end end
ap matrix.right_rotate 741 852 963
上下反転してから転置してもできます。
右に180°回転
90°回転を2回行えば実現できます。
class Array def turn right_rotate.right_rotate end end
ap matrix.turn 987 654 321
左に90°回転
左右反転の後に転置を行います。
class Array def left_rotate vflip.transpose end end
ap matrix.left_rotate 369 258 147
あるいは転置のあとに上下反転してもできます。
副対角線にそった転置
左右反転、転置、左右反転の処理をこの順番で行うと副対角線にそって裏返すことができます。*1
class Array def atranspose vflip.transpose.vflip end end
ap matrix.atranspose 963 852 741
どの操作もまだ別のやりかたがあるのでしょうね。あんまり深く考えると添え字アクセスよりも難しそうなので、このくらいで切り上げることにしましょう。