行列回転の問題。今回は面白かったです。
CHALLENGE DESCRIPTION:
You are given a 2D N×N matrix. Each element of the matrix is a letter: from ‘a’ to ‘z’. Your task is to rotate the matrix 90° clockwise:
a b c g d a d e f => h e b g h i i f c
INPUT SAMPLE:
a b c d a b c d e f g h i j k l m n o p a b c d e f g h i
OUTPUT SAMPLE:
c a d b m i e a n j f b o k g c p l h d g d a h e b i f c
CONSTRAINTS:
- The N size of the matrix can be from 1 to 10
- The number of test cases is 100
My Code
とりあえず書いて見たコード。
#!/usr/bin/env ruby -w def generate_matrix(numbers) n = Math.sqrt(numbers.size).to_i numbers.each_slice(n).to_a end def rotate(matrix) matrix_size = matrix.size result = Array.new(matrix_size) { [] } matrix.each_with_index do |line, i| line.each_with_index do |elm, j| result[j][matrix_size - i - 1] = elm end end result end ARGF.each_line do |line| matrix = generate_matrix(line.chomp.split) puts rotate(matrix).join(" ") end
他のやり方
rotate メソッドがダサいので他の方法を調べてみました。
すると、Ruby Quiz というサイトで同様の問題が出題されていたようで Ruby-Forum でエレガントな解き方が紹介されていました。
Matrix Rotator (#209) - Ruby Forum
それがこれ。
def rotate(n=1) (n%4).times {self.replace(self.reverse.transpose)} end
self.reverse.transpose
。これすごい。これは思いつかない。
>> [["a", "b"], ["c", "d"]].reverse => [["c", "d"], ["a", "b"]] >> [["a", "b"], ["c", "d"]].reverse.transpose => [["c", "a"], ["d", "b"]]
別解
def generate_matrix(numbers) n = Math.sqrt(numbers.size).to_i numbers.each_slice(n).to_a end class Array def rotate(n = 1) (n % 4).times { self.replace(self.reverse.transpose) } self end end ARGF.each_line do |line| matrix = generate_matrix(line.chomp.split) puts matrix.rotate.join(" ") end