57501c8a3e6ab9ad33df9a6203df8860

Hi

I made this piece of code to do some rule training.
I produces a square with an odd side number, in which you can add the numbers horizontally, vertically and diagonally, and the result will be the same.

Smallest output that makes sense is:
8 1 6
3 5 7
4 9 2

The rules are:
Always try to go one up and one to the right.
If you're at the top, try to go one to the right, and all way down.
If you're at the right side, go one up, and all left.
And if non of the above works, go one down.

/Claus :)

#!/usr/bin/ruby

# Makes a multidimension array (matrix) with the width and height of n
def define_matrix(n)
	@square = Array.new(n) { Array.new(n) }
	fill_matrix_with_zeroes(n)
	@size = n
	@max = @size * @size
end

# Fills the matrix with zeroes
def fill_matrix_with_zeroes(n)
	n.times do | i |
		n.times do | j |
			@square[i][j] = 0
		end
	end
end

# Writes to the matrix
def input(i, j, input)
	if @square[j-1][i-1] == 0
		@square[j-1][i-1] = input
	end
end

# Tests if the place in the matrix is free
def is_zero(x, y)
	if @square[y-1][x-1] == 0 && y > 0 && x > 0
		return true
	else
		return false
	end
end

# Finds the next place to write
def next_pos
	x = @pos[0]
	y = @pos[1]
	
	if is_zero(x+1, y-1)
		@pos = [x+1, y-1]
	elsif x == @size && is_zero(1, y-1)
		@pos = [1, y-1]
	elsif y == 1 && is_zero(x+1, @size)
		@pos = [x+1, @size]
	elsif is_zero(x, y+1)
		@pos = [x, y+1]
	else
		unless @num == @max
			puts "Rule error!!!"
			puts "X: #{x}"
			puts "Y: #{y}"
			output
			exit
		end
	end
end

# Finds the start position
def start_pos
	@pos = [(@size.to_f/2+0.5).to_i, 1]
end

# Prints the table nicely
def output
	out = ""
	@square.each do | line |
		line.each do | number |
		out << number.to_s.rjust(@max.to_s.length + 1)
		end
	out << "\n"
	end
	puts out
end

#================ Running the program ===============

if $0 == __FILE__
	if ARGV.length > 0 && (ARGV[0].to_i % 2 > 0)
		define_matrix(ARGV[0].to_i)
		start_pos
	
		for k in 1..@max
			input(@pos[0], @pos[1], k)
			unless k == @max
				next_pos
			end
		end
	
		output
	else
		puts "Call with an odd number!"
	end
end

Refactorings

No refactoring yet !

D41d8cd98f00b204e9800998ecf8427e

bob

June 3, 2010, June 03, 2010 20:38, permalink

No rating. Login to rate!

by the way, it is called magic square: http://en.wikipedia.org/wiki/Magic_square

7855792dbc5f3b4c365344314e2b1ad6

arvanasse

June 4, 2010, June 04, 2010 13:11, permalink

No rating. Login to rate!
#!/usr/bin/ruby

class MagicSquare
  def initialize(size)
    initialize_matrix size
    build_matrix
  end

  def output
    max_width = @max.to_s.length + 1
    out = @square.collect do | line |
      line.collect{| number | number.to_s.rjust(max_width) }.join
    end.join("\n")
    puts out
  end

  private
    def initialize_matrix(n)
      # By specifying zero as the default object there 
      # is no need to fill with zeroes
      @square = Array.new(n) { Array.new(n, 0) }
      @size = n
      @max = @size * @size
    end

    def build_matrix
      set_starting_position
    
      1.upto(@max) do |k| 
        set(@pos[0], @pos[1], k)
        next_pos unless k == @max
      end
    end

    def is_zero(x, y)
      y > 0 && x > 0 && get(x-1, y-1) == 0
    end

    def get(x, y)
      @square[y][x]
    end

    def set(i, j, input)
      @square[j-1][i-1] = input if is_zero(i, j)
    end

    def set_starting_position
      @pos = [(@size.to_f/2+0.5).to_i, 1]
    end

    def next_pos
      x, y = @pos
      
      @pos = case
        when is_zero( x+1, y-1 )           then @pos = [x+1, y-1]
        when x == @size && is_zero(1, y-1) then @pos = [1, y-1]
        when y == 1 && is_zero(x+1, @size) then @pos = [x+1, @size]
        when is_zero(x, y+1)               then @pos = [x, y+1]
        else                                    report_rule_error unless @num == @max
      end
    end

    def report_rule_error
      puts "Rule error!!!"
      puts "X: #{x}"
      puts "Y: #{y}"
      output
      exit
    end

end

#================ Running the program ===============

if $0 == __FILE__	
  unless ARGV.length > 0 && (ARGV[0].to_i % 2 > 0)
    raise ArgumentError, "Please call with an odd number!"
  end

  square = MagicSquare.new ARGV[0].to_i
  square.output	
end

Your refactoring





Format Copy from initial code

or Cancel