Y
Yossef Mendelssohn
Ahh, this reminds me of college. Some other people may have had to
look up the algorithm or figure it out by the supplied magic squares,
but a decade later, I still remember. Of course, back then we started
at the bottom middle, not the top middle. Doesn't make much of a
difference in the end, though, and that's why it's for odd side
lengths.
#!/usr/bin/env ruby
class MagicSquare
Coords = Struct.new
x, :y)
def initialize(size)
@size = size.to_i
@final_num = @size**2
@coords = Coords.new(@size/2, 0)
create_square
end
def init_square
@square = []
1.upto(@size) do
@square << [0] * @size
end
end
def create_square
init_square
n = 1
while n <= @final_num
@square[@coords.y][@coords.x] = n
n += 1
next_coords
end
end
def to_s
output = []
num_length = @final_num.to_s.length
num_length+2 * @size
hline = '+' + Array.new(@size, '-' * (num_length + 2)).join('+') +
'+'
output.push(hline)
(0...@size).each do |x|
output.push('| ' + @square[x].collect { |n|
sprintf("%#{num_length}d", n) }.join(' | ') + ' |')
output.push(hline)
end
output.join("\n")
end
private
def next_coords
new_coords = Coords.new((@coords.x-1 + @size) % @size,
(@coords.y-1 + @size) % @size)
if @square[new_coords.y][new_coords.x] != 0
new_coords = Coords.new(@coords.x, (@coords.y+1) % @size)
end
@coords = new_coords
end
end
square = MagicSquare.new(ARGV[0])
puts square
look up the algorithm or figure it out by the supplied magic squares,
but a decade later, I still remember. Of course, back then we started
at the bottom middle, not the top middle. Doesn't make much of a
difference in the end, though, and that's why it's for odd side
lengths.
#!/usr/bin/env ruby
class MagicSquare
Coords = Struct.new
def initialize(size)
@size = size.to_i
@final_num = @size**2
@coords = Coords.new(@size/2, 0)
create_square
end
def init_square
@square = []
1.upto(@size) do
@square << [0] * @size
end
end
def create_square
init_square
n = 1
while n <= @final_num
@square[@coords.y][@coords.x] = n
n += 1
next_coords
end
end
def to_s
output = []
num_length = @final_num.to_s.length
num_length+2 * @size
hline = '+' + Array.new(@size, '-' * (num_length + 2)).join('+') +
'+'
output.push(hline)
(0...@size).each do |x|
output.push('| ' + @square[x].collect { |n|
sprintf("%#{num_length}d", n) }.join(' | ') + ' |')
output.push(hline)
end
output.join("\n")
end
private
def next_coords
new_coords = Coords.new((@coords.x-1 + @size) % @size,
(@coords.y-1 + @size) % @size)
if @square[new_coords.y][new_coords.x] != 0
new_coords = Coords.new(@coords.x, (@coords.y+1) % @size)
end
@coords = new_coords
end
end
square = MagicSquare.new(ARGV[0])
puts square