# Solution: Magic Squares (#124)

**URL:** <https://www.ruby-forum.com/t/solution-magic-squares-124/104642>\
**Category:** Ruby\
**Created:** [May 21, 2007, 3:40am UTC](https://www.ruby-forum.com/t/solution-magic-squares-124/104642 "2007-05-21T03:40:54Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![croese](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/839c29/32.png) [@croese](https://www.ruby-forum.com/u/croese)\
**Post date:** [May 21, 2007, 3:40am UTC](https://www.ruby-forum.com/t/solution-magic-squares-124/104642/1 "2007-05-21T03:40:54Z")

</div>

Here goes!

#!/usr/bin/ruby -w  
#########################

# Author: Christian R.

# Filename: magicsquare.rb

# Date: 20-05-07

#########################

# Ruby Q. #124 - Magic Squares

# behold, a rhodes magic square class!

class MagicSquare  
def initialize(size)  
@size = size  
@square = Array.new(size)  
@square.each\_index { |i| @square[i] = Array.new(size, 0) } # create  
multidimensional array of zeroes  
# let’s get started building this thing  
create  
end

# primary function in this class; takes care of all the legwork by

filling  
in the magic

# square with successive numbers

def create  
stop = @size \*\* 2  
row = 0  
col = (@size - 1) / 2 # handy trick to find middle of zero-based  
array  
1.upto(stop) do |num|  
@square[row][col] = num  
temp\_row, temp\_col = row - 1, col - 1  
temp\_row = @size - 1 if temp\_row \< 0 # handle going off the  
deep  
end and adjust accordingly  
temp\_col = @size - 1 if temp\_col \< 0 # …and here, too  
if @square[temp\_row][temp\_col] != 0 # check if prospective  
spot is  
already filled  
temp\_row, temp\_col = row + 1, col # if so, move down one  
spot  
from initial square  
end  
# get ready for next iteration  
row = temp\_row  
col = temp\_col  
end  
end

# pretty-printing function that displays the magic square in a box

# looks alright until numbers get above 1,000…

def pp  
rowsep = “+” + “-” \* (@size \* 6 - 1) + “+” # IMPROVE ME: more  
dynamic  
string for larger squares - perhaps dependent on @size^2  
rowfmt = “|” + " %3d |" \* @size +"\n" # IMPROVE ME: more  
dynamic  
string for larger squares - perhaps dependent on @size^2  
puts rowsep  
@square.each do |sub|  
printf(rowfmt, \*sub)  
puts rowsep  
end  
end

# helper function to check row sum

def magic\_number(row=0)  
@square[row].inject { |sum, n| sum + n }  
end  
private :create  
end

# grab cmd-line arg and convert it to a number

# NOTE: if to\_i fails here, it returns a 0 which is then caught by the

if-then clause - no exceptions needed!  
input = ARGV.shift.to\_i

# prevent bad input

# NOTE: ignoring size == 1 since it’s a trivial square

E\_BADARG = 1  
if input \<= 2 || input % 2 == 0  
puts “Bad argument - must be an odd integer \> 2”  
exit E\_BADARG  
end

# make a new square, print it fancily(?), and spit out the magic number

for  
kicks  
sq = MagicSquare.new(input)  
sq.pp  
puts “magic number = #{sq.magic\_number}”

---

<div class="post-metadata">

**Author:** ![croese](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/839c29/32.png) [@croese](https://www.ruby-forum.com/u/croese)\
**Post date:** [May 21, 2007, 3:47am UTC](https://www.ruby-forum.com/t/solution-magic-squares-124/104642/2 "2007-05-21T03:47:32Z")

</div>

sorry about the formatting folks, first time poster!

CURSE MY LONG COMMENTS!!!
