Write the Grid
I’m using a data class, which if you haven’t seen these before, they’re a shortcut for creating a class with specific attributes. In this case, those attributes are
name for the pattern and a set of tuples where the tuples are pairs of
ints. Data classes use Python type hinting to specify what is to be stored in an attribute.
The ability to use the built-in types like
tuple as type hints was added in Python 3.9. If you’re using something earlier, you’ll have to import the corresponding type hint classes from the
typing module instead.
01:21 The next class here is the one that abstracts the grid. It stores the current frame as data and provides a method for calculating the next frame. At the top of the class, I have a couple of constants that get used when displaying the grid, showing a heart for alive and dot for dead.
You’ll recall these values from the previous lesson. When I introduced the algorithm for counting neighbors, I mentioned that I’d use a
defaultdict By creating a
defaultdict with an
int, any key that doesn’t exist will get created with an integer value.
02:26 This loop is what calculates the neighbor counts. Remember, this is being done the backwards way by looping through the alive cells. Then for each cell, I loop through the neighbor deltas and increment the value in the neighbor counting dict.
03:02 I’ve always found this a bit problematic personally, the fact that both set and dictionaries use the same symbols, but hey, no language is perfect. To read a comprehension like this, I tend to start in the middle and work my way outwards.
num_neighbors dict is being iterated over. That’s the middle part, and each iteration is returning a cell coordinate and a number. If that number is in the set containing two and three, then the corresponding cell coordinate is put in the outer set.
This corresponds to that first grid with blue cells I covered in the last lesson. I then take the newly calculated set containing cells with two or three neighbors and perform an
and operation on that and the currently alive cells.
03:49 This gives me a set with the coordinates of cells that are staying alive, staying alive. Really? Did you not expect me to make that joke at some point? The next comprehension is for the reproduction sequence.
This leaves me with dead cells that have three neighbors. Those are the ones that come alive. And finally, I
or these two new sets together, storing it in the pattern object, and giving me the next frame.
Let me scroll down a bit more here. I’m implementing a
__str__ method to help with debugging and make sure that everything is working. This method simply returns the name of the starter pattern and the current list of alive cells.
as_string() method of the grid class is going to convert the alive cells list into a visual representation of the grid. It takes one argument, which is a tuple of the bounding area of the grid to display.
06:34 Then I build a title string based on the pattern name, but centered. Then I loop through the rows, constructing each, printing out a dot if the cell is not in the alive list and a heart if it is. Remember the alive and dead constants at the top of the file, which were heart and dot respectively.
Become a Member to join the conversation.