Skip to content

Instantly share code, notes, and snippets.

@Coldsp33d
Last active May 3, 2018 12:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Coldsp33d/dfabf0eb9f5f1c52d024fd61684a766f to your computer and use it in GitHub Desktop.
Save Coldsp33d/dfabf0eb9f5f1c52d024fd61684a766f to your computer and use it in GitHub Desktop.
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