Right now I'm doing this tutorial for WebAssembly with Rust. The task is to implement Conways Game of Life in Rust. Writing a low-level language like Rust is new for me, but with my prior experience in coding I understand most of the syntax.
The problem I'm having is about the logic of this function:
fn live_neighbor_count(&self, row: u32, column: u32) -> u8 {
let mut count = 0;
for delta_row in [self.height - 1, 0, 1].iter().cloned() {
for delta_col in [self.width - 1, 0, 1].iter().cloned() {
if delta_row == 0 && delta_col == 0 {
continue;
}
let neighbor_row = (row + delta_row) % self.height;
let neighbor_col = (column + delta_col) % self.width;
let idx = self.get_index(neighbor_row, neighbor_col);
count += self.cells[idx] as u8;
}
}
count
}
In this implementation of Conways Game of Life the grid of cells is represented as an one-dimensional array. The task of this function is now to take coordinates (row
and column
) and iterate around the neighbours of this coordinates. Because the array is only one-dimensional, the tasks requires delta_row
and delta_col
which iterate over a array to calculate the neighbors.
My problem is now to understand why these arrays [self.height - 1, 0, 1]
and [self.height - 1, 0, 1]
are choosen to be iterated over.
I already tried to print out the iterated values and draw the grid on a pieces of paper to visualize the process. Right now I also try to implement a self-written function to understand the choices of the above function better.
Maybe you have already solved this or a similar problem and can give me a hints what's going on.
Thank you for reading and have a nice weekend!
It ends up looking a bit odd because of the constraint of unsigned integers (u32
). What we want to write is
for delta_row in [-1, 0, 1]
which gives every row within 1 of our original, but we can't use -1
because it has a sign. Notice later that we
let neighbor_row = (row + delta_row) % self.height;
so really we're effectively working in the integers modulo self.height
. In this case, -1 = self.height - 1
, so we are free to substitute the latter (which is legal for a u32
).
An easy way to see this is to substitute it in later. On the iteration when delta_row = self.height - 1
, we are doing
let neighbor_row = (row + self.height - 1) % self.height;
= (row - 1) % self.height - self.height % self.height;
= (row - 1) % self.height;
which is the row before row
(with wrapping at the edge).