Magic Squares (#124)

奇数のみ

class OddMagicSquare
   attr_reader :square, :order
   def initialize(order)
      @order = order
      @square = case
                when order % 2 == 1 then odd_order
                else                     make_square(@order)
                end
   end

   def show
      @square ? @square.map {|l| l.join(",") }.join("\n") : ""
   end

   private

   def make_square(order)
      Array.new(order) {|i| Array.new(order) {|i| 0}}
   end

   def inc(now)
      now.succ == @order ? 0 : now + 1
   end
   def dec(now)
      now - 1 < 0 ? @order - 1 : now - 1
   end
   def odd_order
      square = make_square(@order)

      row = 0
      column = @order.div(2)
      (1..@order**2).each do|i|
         square[row][column] = i
         next_r = dec(row)
         next_c = inc(column)
         if square[next_r][next_c] != 0
            row = inc(row)
         else
            row = next_r
            column = next_c
         end
      end
      square
   end
end
puts OddMagicSquare.new(ARGV[0].to_i).show

後から気づいたこと

偶数の魔方陣を解くLUXアルゴリズムってのがあるらしい。Wikipediaにも載ってる。
Wikipediaみてやったのにアルゴリズムの紹介に気づかなかったorz