From: Daniel Moore Date: 2009-06-22T03:16:53+09:00 Subject: [QUIZ][SUMMARY] Matrix Rotator (#209) --0015175cb27271e5da046cdfa9d1 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit The goal for this week's quiz was to rotate a two dimensional matrix counter-clockwise. I provided a simple test suite to make the process easier. Robert Dober and brabuhr straightened out my mix-up about the order of arguments for `assert_equal`. For the record, it's , then . Robert also shared three alternative test suites using RSpec[1], testy[2], and Verify[3]. They are included in the quiz attachment. Check them out if you are interested in alternatives to Test::Unit. Another alternative is shoulda[4]. I find the primary advantage of testing, aside from knowing when your code is correct, is that it frees you up to refactor your code, knowing that at each step of the way you haven't broken anything. Now, on to the solutions submitted for this week's quiz. brabuhr's solution creates and returns a new matrix by transposing the row and column index, and populating the elements in reversed order. module Matrix def self.rotate(o) rows, cols = o.size, o[0].size Array.new(cols){|i| Array.new(rows){|j| o[j][cols - i - 1]}} end end The secret is knowing that a counterclockwise rotation is equivalent to transposing, then reversing the matrix. Robert showed a simple way to accomplish this using the standard Ruby API. matrix.transpose.reverse list had an interesting solution: it can rotate a matrix any number of times, even a negative number. This is accomplished by using the mod operator, since four rotations would leave you back where you started. def rotate(n=1) (n%4).times {self.replace(self.reverse.transpose)} end One note about list's solution is that it rotates clockwise. It is interesting that changing the order in which the operations are called changes the direction that the rotation occurs in, but it makes sense because most matrix operations are non-commutative. The 'direction' in which the operations are performed determines the direction of the rotation. Thank you everyone for your solutions! [1]: http://rspec.info/ [2]: http://github.com/ahoward/testy/tree/master [3]: http://www.ruby-forum.com/topic/183354 [4]: http://thoughtbot.com/projects/shoulda --0015175cb27271e5da046cdfa9d1 Content-Type: application/x-gzip; name="209.tar.gz" Content-Disposition: attachment; filename="209.tar.gz" Content-Transfer-Encoding: base64 X-Attachment-Id: f_fw82our20 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 --0015175cb27271e5da046cdfa9d1--