Lesson 5
Unique Grid Traversal with Ruby Methods
Introduction

Hello, and welcome back to our coding lesson series. In this unit, we have a fascinating problem at hand that uses the concept of 2D arrays or grids. What's interesting about this problem is that it involves not only the simple traversal of the grid but also performing this traversal in a unique manner. Initially, the concept might seem a bit tricky, but as we dissect the task and take it step by step, you're sure to enjoy how it unfolds. Are you ready to embark on this adventure? Let's dive right in!

Task Statement

The task before us involves the creation of a Ruby method named path_traverse. This method should perform a particularly ordered traversal through a 2D grid. The method will accept a grid, along with the starting cell coordinates, as parameters. Starting from the provided cell, the method should make moves in any one of the four possible directions toward an adjacent cell. However, a condition governs this selection: the new cell value should be strictly greater than the current cell's value.

This pattern would continue as we keep selecting the next available larger cell value. The traversal will halt when there are no cells left that satisfy our criteria. The final result of the method will be an array that includes all the visited cell values in the order of their visitation.

Consider a 3x3 grid:

11 2 3 24 5 6 37 8 9

If we start at the cell with the value 5, we can logically move to either 6 or 8. Let's say we choose 6; the only cell we can now move to is 9. After this, we have no more moves left that fit our criteria. Hence, the method returns [5, 6, 9].

Solution Building: Step 1

The first thing we need to do is determine the dimensions of our grid, which is relatively easy in Ruby with properties like size. We can also establish the directions that our traversal can take. In the context of matrices, when we say we are moving "up," we are moving one step towards the first row (decreasing the row index). Similarly, moving "down" corresponds to moving one step towards the last row (increasing the row index), and moving left or right relates to decrementing or incrementing the column index, respectively.

Ruby
1def path_traverse(grid, start_row, start_col) 2 rows = grid.size 3 columns = grid[0].size 4 directions = [ 5 [-1, 0], # Up 6 [1, 0], # Down 7 [0, -1], # Left 8 [0, 1] # Right 9 ]

In the directions array, each sub-array represents a direction in terms of a pair [row_offset, col_offset]. So, if we are at a cell (r, c), moving up corresponds to going to the cell (r-1, c), moving down corresponds to (r+1, c), moving left corresponds to (r, c-1), and moving right corresponds to (r, c+1).

Solution Building: Step 2

Once we have the grid's dimensions and the possible directions, we should validate the starting point and set up our visited cell recording mechanism.

Ruby
1def path_traverse(grid, start_row, start_col) 2 rows = grid.size 3 columns = grid[0].size 4 5 # Check the validity of the input 6 return "Invalid input" if start_row < 0 || start_row >= rows || start_col < 0 || start_col >= columns 7 8 # Define all four possible directions of movement 9 directions = [[1, 0], [-1, 0], [0, -1], [0, 1]] 10 11 # Start with the value at the starting cell 12 visited = [grid[start_row][start_col]]
Solution Building: Step 3

Let's initiate the grid traversal process in our method. We first set up an infinite loop that will only stop when we break it based on a condition.

Ruby
1loop do 2 # Initialize a current maximum as negative one 3 curr_max = -1 4 # Loop over each adjacent cell in all the directions 5 directions.each do |dir| 6 # Placeholder code here 7 end
Solution Building: Step 4

Inside the infinite loop, for each iteration, we'll have the method try to select the next cell with the maximum value among the adjacent cells. If we find such a cell, we'll capture its value, and it will be our next cell.

Ruby
1# Inside the loop 2directions.each do |dir| 3 # Calculate the new cell's row and column indices 4 new_row = start_row + dir[0] 5 new_col = start_col + dir[1] 6 7 # If the new cell is out of the grid boundary, ignore it 8 next if new_row < 0 || new_row >= rows || new_col < 0 || new_col >= columns 9 10 # If the new cell's value is greater than the current maximum 11 if grid[new_row][new_col] > curr_max 12 # Save it as the next cell to visit 13 next_row, next_col, curr_max = new_row, new_col, grid[new_row][new_col] 14 end 15end
Solution Building: Step 5

Finally, if there are no valid neighboring cells to visit, we'll break our infinite loop and return the list of visited cells' values.

Ruby
1# If we don't have any valid cell to visit, break from the loop 2if curr_max <= grid[start_row][start_col] 3 break 4end 5# Otherwise, go to the next cell 6start_row, start_col = next_row, next_col 7 8# Append the cell's value to the result list 9visited << curr_max

In the end, our beautiful method looks like this:

Ruby
1def path_traverse(grid, start_row, start_col) 2 rows = grid.size 3 columns = grid[0].size 4 5 return "Invalid input" if start_row < 0 || start_row >= rows || start_col < 0 || start_col >= columns 6 7 directions = [[1, 0], [-1, 0], [0, -1], [0, 1]] 8 visited = [grid[start_row][start_col]] 9 10 loop do 11 curr_max = -1 12 13 directions.each do |dir| 14 new_row = start_row + dir[0] 15 new_col = start_col + dir[1] 16 17 next if new_row < 0 || new_row >= rows || new_col < 0 || new_col >= columns 18 19 if grid[new_row][new_col] > curr_max 20 next_row, next_col, curr_max = new_row, new_col, grid[new_row][new_col] 21 end 22 end 23 24 if curr_max <= grid[start_row][start_col] 25 break 26 end 27 28 start_row, start_col = next_row, next_col 29 visited << curr_max 30 end 31 32 visited 33end
Lesson Summary

Bravo! You've successfully solved a complex problem involving the traversal of a grid in a unique pattern. This method has tested not only your skills in Ruby programming but also your ability to visualize spatial patterns.

Having digested this knowledge, it's now time to test your understanding and apply these concepts to similar problems. Watch out for the ensuing practice session, where you can dabble with more challenging problems and refine your problem-solving skills. Keep up the good work, and happy coding!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.