scientific-programming-exer.../exam/ex13/backend.py

68 lines
2.0 KiB
Python

import numpy as np
CELL_IS_ALIVE = 0b1
CELL_WILL_BE_ALIVE = 0b10
CELL_WILL_BE_DEAD = 0b100
def is_alive(model, i, j):
return model[i][j] & CELL_IS_ALIVE
def get_cells_around(model, i, j):
# Most common case. Handle this first.
# Fortunately the most common case is also the fastets to handle.
if(i > 2 and j > 2 and i < model.shape[0] and j < model.shape[1]):
return model[i - 2: i + 2, j - 2: j + 2]
# Neither negative indices nor indices that overflow
# are handled properly by numpy. So basically I have to do that manually:
cells_around = np.zeros([3, 3], np.int8)
for k, m in enumerate(range(i - 1, i + 2)):
for l, n in enumerate(range(j - 1, j + 2)):
real_m = m
if(m >= model.shape[0]):
real_m = m - model.shape[0]
if(m < 0):
real_m = m + model.shape[0]
real_n = n
if(n >= model.shape[1]):
real_n = n - model.shape[1]
if(n < 0):
real_n = n + model.shape[1]
cells_around[k][l] = model[real_m][real_n]
return cells_around
def count_living_cells_around(model, i, j):
cells_around = get_cells_around(model, i, j)
living_cells_around = (cells_around & CELL_IS_ALIVE) == 1
living_cells_around[1][1] = False
unique, counts = np.unique(living_cells_around, return_counts=True)
if(True not in unique):
return 0
return counts[np.where(unique == True)[0]]
def handle_cell(model, i, j):
living_cells_around = count_living_cells_around(model, i, j)
if(not is_alive(model, i, j)):
if(living_cells_around == 3):
model[i][j] = CELL_WILL_BE_ALIVE
return
if(living_cells_around > 3 or living_cells_around < 2):
model[i][j] = CELL_WILL_BE_DEAD
def after_tick_finished(model):
# kill the cells that have died
model[(model & CELL_WILL_BE_DEAD) != 0] = 0
# create the new cells
model[(model & CELL_WILL_BE_ALIVE) != 0] = 1
def total_living_cells(model):
living_cells = (model & CELL_IS_ALIVE) == 1
unique, counts = np.unique(living_cells, return_counts=True)
if(True not in unique):
return 0
return counts[np.where(unique == True)[0]]