I'm looking for comments on both the micro (individual lines of code) and macro (overall design) scale. My input/output format is a single string, with newlines delimiting rows and '*'/' '
denoting alive and dead, respectively.
from itertools import product
from enum import Enum
class Direction(Enum): forwards = 1; backwards = 0
class State:
table = {'*':True, ' ':False}
def convert(self, grid, direction):
if direction == Direction.forwards:
table = self.table
elif direction == Direction.backwards:
table = {value:key for (key,value) in self.table.items()}
else:
raise ValueError("Invalid conversion direction!")
return [[table[x] for x in row] for row in grid]
def __init__(self, grid):
grid = list(filter(None, grid.split('\n')))
self.rows = len(grid); self.cols = len(grid[0])
if not all(len(grid[i]) == self.cols for i in range(self.rows)):
raise ValueError("Invalid game state!")
self.grid = self.convert(grid, Direction.forwards)
def __getitem__(self, i):
return self.grid[i]
def __str__(self):
return '\n'.join(map(lambda x: ''.join(x), self.convert(self.grid, Direction.backwards)))
def game(state):
''' Takes a state in the input format and yields states in the output format. '''
state = State(state)
def alive(x,y):
try:
return state[x][y]
except IndexError:
return False
while True:
state.grid = [
[2 <= sum(alive(xx,yy) for xx, yy in product([x-1,x+1], [y-1,y+1])) <= 3
for (y,col) in enumerate(row)]
for (x,row) in enumerate(state.grid)
]
yield str(state)