Here's my solution. It only works for odd-sized squares at the moment, maybe I'll get ambitious later and go for the extra credit. # file: magic_square.rb # author: Drew Olson class MagicSquare # access to the raw square (not used here, maybe used by others?) attr_reader :square # check that size is odd, then store size and build our square def initialize size raise "Size must be odd" unless size%2 == 1 @size = size build_square size self end # scary looking method for pretty printing def to_s # find the largest number of digits in the numbers we # are printing digits = max_digits @size**2 # create the row divider. flexible based on size of numbers # and the square. divider = "+"+("-"*(@size*(3+digits)-1))+"+\n" # build each row by formatting the numbers to the max # digits needed and adding pipe dividers (0...@size).inject(divider) do |output,i| output + "| " + @square[i].map{|x| "%#{digits}d" % x}.join(" | ") + " |\n" + divider end end private # get the highest digit count up to size def max_digits size (1..size).map{|x| x.to_s.size}.max end # initialize our 2d array (probably slicker ways to do this) def init_array size (0...size).inject(Array.new) do |arr,i| arr[i] = [] arr end end # build square based on the algorithm from wikipedia. # start in the middle of the first row, move up and right. # if new space is occupied, move down one space and continue. def build_square size #starting positions x,y = size/2,0 # build square @square = (1..size**2).inject(init_array(size)) do |arr,i| # store current number in square arr[y][x] = i # move up and left x = (x+1)%size y = (y-1)%size # undo move and move down if space is taken if arr[y][x] y = (y+2)%size x = (x-1)%size end arr end end end # build and print out square if __FILE__ == $0 puts MagicSquare.new(ARGV[0].to_i) end -- Posted via http://www.ruby-forum.com/.