--Apple-Mail-1--496755143
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset-ASCII;
	format竟wed

Begin forwarded message:

> From: Hirotsugu Asari <asari / mac.com>
> Date: May 19, 2007 6:57:27 PM CDT
> To: submission / rubyquiz.com
> Subject: Please Forward: Ruby Quiz Submission
>
> Here's my solution and the tests.
>

--Apple-Mail-1--496755143
Content-Transfer-Encoding: 7bit
Content-Type: text/x-ruby-script;
	x-unix-mode44;
	x-mac-creatorT784D74;
	name
gic_square.rb
Content-Disposition: attachment;
	filename
gic_square.rb

#!/usr/bin/env ruby -wKU

# Ruby Quiz #124
# Magic Square -- build an NxN magic square

require 'matrix'

class Matrix
  def magic?
    return false if ! self.square?
    
    size  elf.row_size
    
    # compute the sum of each row, each column and the diagonals
    magic_sum  1..size**2).inject{ |s,i| s +  } / size

    begin
      # checks rows and columns
      self.row_vectors.each { |v|
        if v.to_a.inject { |s,i| s +  } ! agic_sum
          raise RuntimeError, "row #{v} doesn't add up to #{magic_sum}"
        end
      }
      self.column_vectors.each { |v|
        if v.to_a.inject { |s,i| s +  } ! agic_sum
          raise RuntimeError, "column #{v} doesn't add up to #{magic_sum}"
        end
      }

      # check diagonals
      if (0..size-1).inject(0) {|s,i| s + elf[i,i] } ! agic_sum
        raise RuntimeError, "the main diagonal doesn't add up to #{magic_sum}"
      end

      # finally.... check the other main diagonal
      if (0..size-1).inject(0) {|s,i| s + elf[i, -1-i] } ! agic_sum
        raise RuntimeError, "the other diagonal doesn't add up to #{magic_sum}"
      end
      
    rescue
      return false
    end
    
    # it passed all checks
    return true

  end
  
  def to_s_pretty
    if ! self.square?
      return self.to_s
    end
    array       elf.to_a
    max_length  rray.flatten.sort.last.to_s.length # the length of the largest number to fit in
    s           "
    
    until array.empty? do
      row  rray.shift
      s  + +" + "-" * ((max_length+2)*row.length + row.length-1) + "+\n"
      s  + | " + row.map{ |i| i.to_s.rjust(max_length) }.join(" | ") + " |\n"
    end
    s + +" + "-" * ((max_length+2)*row.length + row.length-1) + "+"
    
  end
  
  # See <http://mathworld.wolfram.com/MagicSquare.html>
  def Matrix.new_magic_square(n0
    n  .to_i
    if n 2
      raise ArgumentError, "2x2 magic square does not exist"
    elsif n < 1
      raise ArgumentError, "Cannot create a magic square of size #{n}"
    end
    
    if n % 2 ! 
      return Matrix.new_odd_magic_square(n)
    elsif n % 4 0
      return Matrix.new_doubly_even_magic_square(n)
    else
      return Matrix.new_singly_even_magic_square(n)
    end
  end
  
  private
  def Matrix.new_odd_magic_square(n)
    if ! n.integer? || n%2 ! 
      raise RuntimeError, "Internal error on line #{__LINE__}"
    end    
    # generate the NxN magic square by the Siamese method
    a  ]
    0.upto(n-1) { |i|
      a[i]
    }

    m  n-1)/2
    # put 1 in a[0][m], then 2 goes to a[-1][m+1], 3 to a[-2][m+2], ...
    x    y    1.upto(n**2) { |i|
      if (a[x][y]).nil?
        a[x][y]  
      else
        # this cell is already filled, so we move to the cell below; we had
        # already moved to the upper right cell, so we must offset that move, too
        x + 
        y - 
        a[x%n][y%n]  
      end
      x  x-1)%n # move up
      y  y+1)%n # then right
    }
    
    Matrix.rows(a)
    
  end
  
  def Matrix.new_doubly_even_magic_square(n)
    if ! n.integer? || n%4 ! 
      raise RuntimeError, "Internal error on line #{__LINE__}"
    end    
    
    # first fill the cells in order
    a
    1.upto(n) do |i|
      first  i-1)*n+1 # first element
      a << (first..(first+n-1)).to_a
    end
    # then replace the entries
    0.upto(n-1) do |i|
      0.upto(n-1) do |j|
        if (i-j)%4 0 || (i+j)%4 3
          a[i][j]  **2+1-a[i][j]
        end
      end
    end
    Matrix.rows(a)
  end
  
  def Matrix.new_singly_even_magic_square(n)
    if ! n.integer? || n%4 ! 
      raise RuntimeError, "Internal error on line #{__LINE__}"
    end    
    
    # first generate the magic square of size n/2
    m  n-2)/4
    matrix  atrix.new_odd_magic_square(2*m+1).to_a
    
    lux # identifier for "L,U,X" for each 4x4 squares
    # m+1 rows of L's
    1.upto(m+1) do |i|
      lux << (1..(2*m+1)).to_a.map{"L"}
    end
    # 1 row of U's
    lux << (1..(2*m+1)).to_a.map{"U"}
    # m-1 rows of X's
    1.upto(m-1) do |i|
      lux << (1..(2*m+1)).to_a.map{"X"}
    end
    # swap an L and a U as required by the method
    lux[m][m]"
    lux[m+1][m]"
    
    # finally, fill up the cells
    a  ]
    0.upto(n-1) do |i|
      a[i]
      0.upto(n-1) do |j|
        k  /2
        l  /2
        case
        when lux[k][l] "L"
          # 4 1
          # 2 3
          if i%2 0
            if j%2 0
              a[i][j]atrix[k][l]-1)*4+4
            else
              a[i][j]atrix[k][l]-1)*4+1
            end
          else
            if j%2 0
              a[i][j]atrix[k][l]-1)*4+2
            else
              a[i][j]atrix[k][l]-1)*4+3
            end
          end # end of case "L"
        when lux[k][l] "U"
          # 1 4
          # 2 3
          if i%2 0
            if j%2 0
              a[i][j]atrix[k][l]-1)*4+1
            else
              a[i][j]atrix[k][l]-1)*4+4
            end
          else
            if j%2 0
              a[i][j]atrix[k][l]-1)*4+2
            else
              a[i][j]atrix[k][l]-1)*4+3
            end
          end # end of case "U"
        when lux[k][l] "X"
          # 1 4
          # 3 2
          if i%2 0
            if j%2 0
              a[i][j]atrix[k][l]-1)*4+1
            else
              a[i][j]atrix[k][l]-1)*4+4
            end
          else
            if j%2 0
              a[i][j]atrix[k][l]-1)*4+3
            else
              a[i][j]atrix[k][l]-1)*4+2
            end
          end # end of case "X"
        else
          raise RuntimeError, "Internal error on line #{__LINE__}"
        end
      end
    end
    
    return Matrix.rows(a)
  end
  
end
--Apple-Mail-1--496755143
Content-Transfer-Encoding: 7bit
Content-Type: text/x-ruby-script;
	x-unix-mode44;
	x-mac-creatorT784D74;
	name4_test.rb
Content-Disposition: attachment;
	filename4_test.rb

#!/usr/bin/env ruby -wKU

require "test/unit"
require "magic_square.rb"

class MagicSquareTest < Test::Unit::TestCase
  def test_magicness
    
    # here's a magic square of size 5
    m  atrix[
      [15, 8, 1,24,17],
      [16,14, 7, 5,23],
      [22,20,13, 6, 4],
      [ 3,21,19,12,10],
      [ 9, 2,25,18,11]
    ]
    assert m.magic?

    # here's another
    m  atrix[
      [19,21, 3,10,12],
      [25, 2, 9,11,18],
      [ 1, 8,15,17,24],
      [ 7,14,16,23, 5],
      [13,20,22, 4, 6]
    ]
    assert m.magic?
    
    # one of size 9
    m  atrix[
      [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]
    ]
    assert m.magic?
    
  end
  
  def test_exceptions
    assert_raise ArgumentError do 
      m  atrix.new_magic_square(2)
    end
    
    assert_raise ArgumentError do
      m  atrix.new_magic_square(-1)
    end
  end
  
  def test_generator
    assert_equal Matrix.new_magic_square(1), Matrix[[1]]
    
    3.upto(100) do |n|
      s  rocess.times
      m  atrix.new_magic_square(n)
      t  rocess.times
      # puts sprintf("size: %10d generated in utime: %8.2f\tstime: %8.2f", n, t.utime-s.utime, t.stime-s.stime)
      assert m.magic?
      u  rocess.times
      # puts sprintf("size: %10d tested in utime: %8.2f\tstime: %8.2f", n, u.utime-t.utime, u.stime-t.stime)
    end
  end
end
--Apple-Mail-1--496755143
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset-ASCII;
	delspサ
	竟

セ
セ ノ  コッッョョッヘモョ    
セ      ョ
セ
セ ヤ   テイト ヘツ ミ  ョ
セ
セ 、  ゜゜ョ
セ  ァ゜ァ
セ
セ  ヘョ゜゜ィチメヌヨローンゥョ゜゜
セ
セ 、   ゜゜ョ ケ
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ  エキ  オク  カケ  クー   ア  アイ  イウ  ウエ  エオ 
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ  オキ  カク  キケ   ケ  アア  イイ  ウウ  エエ  エカ 
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ  カキ  キク   ク  アー  イア  ウイ  エウ  オエ  オカ 
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ  キキ   キ  アク  イー  ウア  エイ  オウ  オオ  カカ 
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ   カ  アキ  アケ  ウー  エア  オイ  カウ  カオ  キカ 
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ  アカ  イキ  イケ  エー  オア  カイ  カエ  キオ   オ 
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ  イカ  イク  ウケ  オー  カア  キイ  キエ   エ  アオ 
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ  ウカ  ウク  エケ  カー  キア  キウ   ウ  アエ  イオ 
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ  ウキ  エク  オケ  キー  クア   イ  アウ  イエ  ウオ 
セ ォュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュュォ
セ
セ     ーーョーアキ
セ     ーーョーアー
セ      ーーョーーキ
セ
セ 、    イケク ウーーサ 
セ セ   ゜゜ョ 、 セ ッッ
セ セ 
セ
セ     ーアョオアウ
セ     ーアョーーカ
セ      ーーョオーオ
セ
セ     ーアョウエエ
セ     ーーョクウカ
セ      ーーョオーカ


ュュチュヘュアュュエケカキオオアエウュュ