From: Dan Manges Date: 2007-05-21T05:44:05+09:00 Subject: Re: Magic Squares (#124) #!/usr/bin/env ruby # # Dan Manges - http://www.dcmanges.com # Ruby Quiz #124 - http://rubyquiz.com/quiz124.html module ArrayExtension def sum inject { |x,y| x + y } || 0 end end Array.send :include, ArrayExtension class MagicSquare def initialize(size) @size = size end def row result end def column row[0].zip(*row[1..-1]) end def diagonal first_diagonal = (0...@size).map { |index| row[index][index] } second_diagonal = (0...@size).map { |index| row[index][@size-index-1] } [first_diagonal, second_diagonal] end protected def result @result ||= MagicSquareGenerator.new(@size).generate end def method_missing(method, *args, &block) result.send(method, *args, &block) end end class MagicSquareGenerator def initialize(size) @size = size end def generate square = (0...@size).map { [nil] * @size } x, y = 0, @size / 2 1.upto(@size**2) do |current| x, y = add(x,2), add(y,1) if square[x][y] square[x][y] = current x, y = add(x, -1), add(y, -1) end square end private def add(x,y) value = x + y value = @size + value if value < 0 value = value % @size if value >= @size value end end class MagicSquareFormatter def initialize(magic_square) @magic_square = magic_square end def formatted_square formatting = "|" + " %#{number_width}s |" * size rows = @magic_square.map { |row| formatting % row } body = rows.join("\n#{row_break}\n") "#{row_break}\n#{body}\n#{row_break}" end private def row_break dashes = '-' * (row_width-2) '+' + dashes + '+' end def number_width (@magic_square.size**2).to_s.length end def row_width (number_width+3) * size + 1 end def size @magic_square.size end end if ARGV.first =~ /^\d+$/ size = ARGV.first.to_i puts "Generating #{size}x#{size} magic square..." magic_square = MagicSquare.new(size) puts MagicSquareFormatter.new(magic_square).formatted_square elsif __FILE__ == $0 require 'test/unit' class MagicSquare3x3Test < Test::Unit::TestCase def setup @magic_square = MagicSquare.new(3) end def test_sum_of_rows_columns_and_diagonals (0...3).each do |index| assert_equal 15, @magic_square.row[index].sum assert_equal 15, @magic_square.column[index].sum end assert_equal 15, @magic_square.diagonal[0].sum assert_equal 15, @magic_square.diagonal[1].sum end def test_expected_values assert_equal [1,2,3,4,5,6,7,8,9], @magic_square.flatten.sort end end class MagicSquare9x9Test < Test::Unit::TestCase def setup @magic_square = MagicSquare.new(9) end def test_sum_of_rows_columns_and_diagonals (0...9).each do |index| assert_equal 369, @magic_square.row[index].sum assert_equal 369, @magic_square.column[index].sum end assert_equal 369, @magic_square.diagonal[0].sum assert_equal 369, @magic_square.diagonal[1].sum end def test_expected_values assert_equal (1..81).to_a, @magic_square.flatten.sort end end end __END__ $ ruby rubyquiz124.rb 9 Generating 9x9 magic square... +--------------------------------------------+ | 45 | 34 | 23 | 12 | 1 | 80 | 69 | 58 | 47 | +--------------------------------------------+ | 46 | 44 | 33 | 22 | 11 | 9 | 79 | 68 | 57 | +--------------------------------------------+ | 56 | 54 | 43 | 32 | 21 | 10 | 8 | 78 | 67 | +--------------------------------------------+ | 66 | 55 | 53 | 42 | 31 | 20 | 18 | 7 | 77 | +--------------------------------------------+ | 76 | 65 | 63 | 52 | 41 | 30 | 19 | 17 | 6 | +--------------------------------------------+ | 5 | 75 | 64 | 62 | 51 | 40 | 29 | 27 | 16 | +--------------------------------------------+ | 15 | 4 | 74 | 72 | 61 | 50 | 39 | 28 | 26 | +--------------------------------------------+ | 25 | 14 | 3 | 73 | 71 | 60 | 49 | 38 | 36 | +--------------------------------------------+ | 35 | 24 | 13 | 2 | 81 | 70 | 59 | 48 | 37 | +--------------------------------------------+ -- Posted via http://www.ruby-forum.com/.