Skip to content

Instantly share code, notes, and snippets.

@Coldsp33d
Last active May 3, 2018
Embed
What would you like to do?
import numpy as np
import time
from enum import Enum
from typing import List, Iterator, Sequence, Tuple
NEIGHBOURS = [(i, j) for i in range(-1, 2) for j in range(-1, 2) if i or j]
class State(Enum):
''' enum class to represent possible cell states '''
DEAD = 0
ALIVE = 1
class Board:
''' Board class to represent the game board '''
def __init__(self, rows : int, columns : int, init : Sequence[Sequence[int]]):
self.rows = rows # the number of rows
self.columns = columns # the number of columns
self.board_ = [
[
State(init[i][j])
for j in range(self.columns)
]
for i in range(self.rows)
]
def __str__(self) -> str:
''' return the __str__ representation of a Board object
* represents a live cell, and a space represents a dead one
'''
return '\n'.join([
''.join([
u" *"[cell.value]
for cell in row
])
for row in self.board_
])
@property
def population(self) -> int:
''' population — the number of live cells on the board '''
return sum(cell.value for row in self.board_ for cell in row)
def has_live_cells(self) -> bool:
''' return whether there are any live cells or not '''
return any(cell.value for row in self.board_ for cell in row)
def neighbours(self, x: int, y: int) -> Iterator[Tuple[State, int, int]]:
for i, j in ((x + i, y + j) for i, j in NEIGHBOURS if x + i >= 0 and y + j >= 0):
try:
yield self.board_[i][j], i, j
except IndexError:
pass
def count_live_neighbours(self, x : int, y : int) -> int:
''' count the live neighbours of a cell '''
return sum(cell.value for cell, _, _ in self.neighbours(x, y))
def next_cell_state(self, x : int, y : int) -> State:
count = self.count_live_neighbours(x, y)
if count == 3 or (count == 2 and self.board_[x][y] == State.ALIVE):
return State.ALIVE
return State.DEAD
def next_board_state(self) -> List[List[State]]:
''' return board configuration for the next state '''
return [
[
self.next_cell_state(i, j)
for j in range(self.columns)
]
for i in range(self.rows)
]
def advance_state(self):
''' update the board configuration with the config for the next state '''
self.board_ = self.next_board_state()
if __name__ == '__main__':
arr = np.random.choice([0, 1], (20, 50), p=[0.85, 0.15])
board = Board(arr.shape[0], arr.shape[1], init=arr.tolist())
step = 0
while board.has_live_cells():
step += 1
print(
'\x1bc',
'\033[91m',
board,
'\033[0m',
f'\nStep: {step:<3d}\tPopulation: {board.population:<4d}',
sep='',
end='\n\n'
)
board.advance_state()
time.sleep(.1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment