Search code examples
arraysrubysumconways-game-of-life

How do I convert nil to 0 in an array to get the sum?


Working on a version of Conway's Game of Life using 2d arrays and when trying too calculate the sum of each cell's "neighbors", I keeping getting blocked by the nil values.

  def neighbor_count
      grid.each_with_index do |row, idx|
          row.each_with_index do |column, idx2|
              [grid[idx - 1][idx2 - 1], grid[idx - 1][idx2], grid[idx - 1][idx2 + 1],
              grid[idx][idx2 - 1], grid[idx][idx2], grid[idx][idx2 + 1],
              grid[idx + 1][idx2 - 1], grid[idx + 1][idx2], grid[idx + 1][idx2 + 1]
              ].compact.sum

          end
      end
  end

.compact seems to yield the most results if include "puts" in front of the array but none of the options I've tried give me 100%. I've tried reduce(:+), inject, .to_i, reject (to get rid of the nil values), and so forth.

What's missing here?

Error: world.rb:35:in block (2 levels) in neighbor_count': undefined method[]' for nil:NilClass (NoMethodError)

Line 35 is the line above ].compact.sum


Solution

  • nil values are only a symptom of the illness. Don't treat the symptoms, get rid of the problem! Which is that you are violating array bounds.

    .each_with_index enumerates all indexes from the first to the last. And so idx + 1 on the last index will trigger this out-of-bounds situation. And idx - 1 on the first will produce an unexpected value instead of an error, which will impact your calculations. Good luck debugging that. :)

    Put some guard checks in your code, to make sure you never go out of bounds.


    Just to be absolutely clear, the problem is not that grid[idx + 1][idx2] is nil and messes up your calculations. It is that grid[idx + 1] is nil! And, naturally, you can't do nil[idx2]. That's the error.