2

I am trying to take in a 2D array, search for any space that is greater than 0, then increment the surrounding spaces by 1.

array = [[0,0,0], [0,1,0], [0,0,0]]

The final output should look like this

new_array = [[0,1,0], [1,1,1], [0,1,0]]

The way I have it set up currently is returning

[1,1,1,1]

It is incrementing the correct spaces, I think, I just am not sure how to put them back into the original arrays and then return the 2D array. Clearly some steps are missing, any help would be greatly appreciated. I understand why it is returning the way it is, just not clear on the next step.

def dilate(array)
  new_array = []
  array.each_with_index do |row, rowIndex|
    row.each_with_index do |col, colIndex|
      if (array[rowIndex][colIndex] > 0)
        new_array << (array[rowIndex][colIndex -1] +1)
        new_array << (array[rowIndex -1][colIndex] +1)
        new_array << (array[rowIndex][colIndex +1] +1)
        new_array << (array[rowIndex +1][colIndex] +1)
      end
    end
  end
  return new_array
end

enter image description here

0

2 Answers 2

2

What you're doing is initializing an empty array, new_array, and appending elements to it. You're appending the incremented values to a new array instead of changing the values in the array. Something like this should work:

def dilate(array)
  new_array=[]
  array.each{|i|new_array<<i.dup}
  array.each_with_index do |row, rowIndex|
    row.each_with_index do |col, colIndex|
      if (array[rowIndex][colIndex] > 0)
        new_array[rowIndex][colIndex -1] += 1 if colIndex > 0
        new_array[rowIndex -1][colIndex] += 1 if rowIndex > 0
        new_array[rowIndex][colIndex +1] += 1 if colIndex < array.first.size-1
        new_array[rowIndex +1][colIndex] += 1 if rowIndex < array.size-1
      end
    end
  end
  return new_array
end

I'm creating a new array, new_array, that's a copy of array, then incrementing its elements.

By the way, you say in your question that you want to "search for any space that contains a 1", but what this is doing is searching for spaces containing values greater than zero. I'm not sure if that's what you wanted.

Sign up to request clarification or add additional context in comments.

10 Comments

First, thank you for responding so quickly with your answer. Yes greater than zero is what I meant to say. I tested it out in irb but I am getting undefined method + for nil class. Not sure if it is something I am doing? It looks like it should work...any idea on that?
@DannySullivan Yeah, the second line was wrong. I messed up duplicating the original array. It's fixed now. It is not in-place, by the way. Is that what you wanted?
Please double-check your work. I'm not getting correct results. #1: arr = [[1,0],[0,0]]; dilate(arr) #=> [[1, 2], [2, 0]]. #2: arr = [[1,0,0],[0,0,0],[0,0,0]]; dilate(arr) #=> [[1, 1, 1], [1, 0, 0], [1, 0, 0]]. #3 NoMethodError: undefined method '+' for nil:NilClass for the last (4x4) example in my answer.
The problem is that if colIndex == 0, new_array[rowIndex][colIndex -1] += 1 becomes new_array[rowIndex][-1] += 1, which adds one to the last element of the array new_array[rowIndex]. What you want is new_array[rowIndex][colIndex -1] += 1 if colIndex > 0. Similar for new_array[rowIndex -1][colIndex] += 1.
You also need new_array[rowIndex][colIndex +1] += 1 if colIndex < arr.first.size-1 and new_array[rowIndex +1][colIndex] += 1 if rowIndex < arr.size-1. Just a reminder of the Ruby convention that names of variable and methods are to be snake_case; e.g. row_index and col_index.
|
1

I suggest you use the class Matrix for this. It makes it easy to do and easy to read.

Code

require 'matrix'

def dilate(arr)
  nrows, ncols = arr.size, arr[0].size
  m = Matrix[*arr]
  m.each_with_index.reduce(m.dup) { |mout, (e, row, col)|
    mout + Matrix.build(nrows, ncols) { |i,j|
      adjacent?(i,j,row,col) ? e : 0 } }.to_a
end

def adjacent?(r0,c0,r1,c1)
  ((r0-r1).abs == 1 && (c0==c1)) || ((c0-c1).abs == 1 && (r0==r1))
end

I have assumed that, when the value of an element, x, is non-zero, you want to increase the values of adjacent elements by x. If you want to increase the values of adjacent elements by 1, change:

Matrix.build(nrows, ncols) { |i,j| adjacent?(i,j,row,col) ? e : 0 }

to:

Matrix.build(nrows, ncols) { |i,j| adjacent?(i,j,row,col) ? 1 : 0 }

Examples

arr = [[0, 0, 0],
       [0, 1, 0],
       [0, 0, 0]]           
dilate(arr)
  #=> [[0, 1, 0],
  #    [1, 1, 1],
  #    [0, 1, 0]] 

arr = [[0, 0, 0, 0],
       [0, 1, 0, 0],
       [0, 0, 0, 0]]           
dilate(arr)
  #=> [[0, 1, 0, 0],
  #    [1, 1, 1, 0],
  #    [0, 1, 0, 0]]

arr = [[1, 0, 0],
       [0, 0, 0],
       [0, 0, 0]]
dilate(arr)
  #=> [[1, 1, 0],
  #    [1, 0, 0],
  #    [0, 0, 0]] 

arr = [[0, 0, 0],
       [1, 0, 0],
       [0, 0, 0]]
dilate(arr)
  #=> [[1, 0, 0],
  #    [1, 1, 0],
  #    [1, 0, 0]] 

arr = [[0, 0, 1],
       [0, 0, 0],
       [0, 0, 0]]
dilate(arr)
  #=> [[0, 1, 1],
  #    [0, 0, 1],
  #    [0, 0, 0]]

arr = [[0, 0, 0, 3],
       [0, 1, 1, 0],
       [0, 4, 1, 0],
       [2, 0, 0, 0]]    
dilate(arr)
  #=> [[0, 1, 4, 3],
  #    [1, 6, 3, 4],
  #    [6, 6, 6, 1],
  #    [2, 6, 1, 0]] 

1 Comment

Thank you @CarySwoveland for helping out. I am going to check my work and test out what you suggested as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.