← Back to Upcase

Code review - Spiral Traverse


(Nate Eckerson) #1

Here’s my solution to the classic “traverse a matrix in a spiral pattern” problem in Ruby!

After finishing this up, I took a look at other solutions and realized you can do cool things with the Matrix class, which I was unaware of. Also, other solutions tend to dismantle the original matrix & rebuild it into a new one-dimensional array, whereas I leave the original intact.

Does anyone know how I might refactor the repetitive if statements in my private methods traverse_top(i), etc? They are necessary to check whether or not the matrix has been iterated through. I feel like there is something obvious that would render them redundant, but it’s escaping me.

All thoughts / constructive feedback welcome!

class SpiralTraverse

  def initialize
    @matrix = []
    @width = ""
    @height = ""
    @num_elements = ""
  end

  def traverse(matrix)
    @matrix = matrix
    @width = matrix.first.length
    @height = matrix.length
    @num_elements = matrix.flatten.length
    run
  end

  def run

    @x = 0

    (0...@width).each do |i|

      traverse_top(i)

      traverse_right(i)

      traverse_bottom(i)

      traverse_left(i)
    end
  end

  private

  def end_of_matrix?
    @x < @num_elements
  end

  def traverse_top(i)
    if end_of_matrix?
      (i...@width - i).each do |top|
        puts "#{@matrix[i][top]}"
        @x += 1
      end
    else
      return
    end
  end

  def traverse_right(i)
    if end_of_matrix?
      (i+1..@height-1-i).each do |right|
        puts "#{@matrix[right][@width - 1 - i]}"
        @x += 1
      end
    else
      return
    end
  end

  def traverse_bottom(i)
    if end_of_matrix?
      (i+1..@width-2-i).reverse_each do |bottom|
        puts "#{@matrix[@height-1-i][bottom]}"
        @x += 1
      end
    else
      return
    end
  end

  def traverse_left(i)
    if end_of_matrix?
      (i+1..@height-1-i).reverse_each do |left|
        puts "#{@matrix[left][i]}"
        @x += 1
      end
    else
      return
    end
  end

end