Closed ytgui closed 5 years ago
import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
class Coord(list):
def __init__(self, x, y):
list.__init__(self, (x, y))
@property
def x(self):
return self.__getitem__(0)
@x.setter
def x(self, x):
self.__setitem__(0, x)
@property
def y(self):
return self.__getitem__(1)
@y.setter
def y(self, y):
self.__setitem__(1, y)
class Size(list):
def __init__(self, height, width):
list.__init__(self, (height, width))
@property
def height(self):
return self.__getitem__(0)
@height.setter
def height(self, height):
self.__setitem__(0, height)
@property
def width(self):
return self.__getitem__(1)
@width.setter
def width(self, width):
self.__setitem__(0, width)
class Conway:
def __init__(self, size=Size(90, 120), cell_probability=0.5, block_probability=0.1):
self.size = size
self.map = np.zeros(shape=size, dtype=np.uint8)
self.cell_probability = cell_probability
# generate and fill sub block
block_size = Size(int(np.sqrt(block_probability) * size.height),
int(np.sqrt(block_probability) * size.width))
src = Coord(random.randrange(size.width - block_size.width),
random.randrange(size.height - block_size.height))
dst = Coord(src.x + block_size.width, src.y + block_size.height)
self.random_fill(src, dst)
def random_fill(self, src, dst):
for y in range(src.y, dst.y):
for x in range(src.x, dst.x):
if random.random() < self.cell_probability:
self.map[y, x] = 1
else:
self.map[y, x] = 0
def init_replace_mode(self):
# 0: 0 -> 0
# 1: 0 -> 1
# 2: 1 -> 0
# 3: 1 -> 1
self.map = np.multiply(self.map, 3)
def conway_step(self):
table =[[0, 0, 0, 1, 0, 0, 0, 0, 0],
[2, 2, 3, 3, 2, 2, 2, 2, 2]]
def get_count(xx, yy):
summed = 0
for vx, vy in [(-1, 0), (1, 0), (0, -1), (0, 1),
(-1, -1), (-1, 1), (1, -1), (1, 1)]:
cur_x, cur_y = xx + vx, yy + vy
if cur_x < 0 or cur_x > self.size.width - 1:
continue
if cur_y < 0 or cur_y > self.size.height - 1:
continue
if cur_x > xx and cur_y > yy:
summed += self.map[cur_y, cur_x] % 2
else:
summed += self.map[cur_y, cur_x] // 2
return summed
for y in range(self.size.height):
for x in range(self.size.width):
n_neighbors = get_count(x, y)
self.map[y, x] = table[self.map[y, x] % 2][n_neighbors]
def finish_replace_mode(self):
self.map = np.mod(self.map, 2)
class ConwayAnimation(Conway):
def __init__(self):
Conway.__init__(self)
# ready for canvas
self.fig = plt.figure()
_ = animation.FuncAnimation(self.fig,
func=self.on_draw,
init_func=self.on_init,
interval=100,
blit=True)
plt.show()
def on_init(self):
self.im = plt.imshow(self.map, cmap='gray', animated=True)
return self.im,
def on_draw(self, frame_id):
print(frame_id)
self.init_replace_mode()
self.conway_step()
self.finish_replace_mode()
self.im.set_array(self.map)
return self.im,
def main():
ConwayAnimation()
if __name__ == "__main__":
main()
import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
class Coord(list):
def __init__(self, x, y):
list.__init__(self, (x, y))
@property
def x(self):
return self.__getitem__(0)
@x.setter
def x(self, x):
self.__setitem__(0, x)
@property
def y(self):
return self.__getitem__(1)
@y.setter
def y(self, y):
self.__setitem__(1, y)
class Size(list):
def __init__(self, height, width):
list.__init__(self, (height, width))
@property
def height(self):
return self.__getitem__(0)
@height.setter
def height(self, height):
self.__setitem__(0, height)
@property
def width(self):
return self.__getitem__(1)
@width.setter
def width(self, width):
self.__setitem__(0, width)
class Conway:
def __init__(self, size=Size(90, 120), cell_probability=0.5, block_probability=0.1):
self.size = size
self.map = np.zeros(shape=size, dtype=np.uint8)
self.cell_probability = cell_probability
# generate and fill sub block
block_size = Size(int(np.sqrt(block_probability) * size.height),
int(np.sqrt(block_probability) * size.width))
src = Coord(random.randrange(size.width - block_size.width),
random.randrange(size.height - block_size.height))
dst = Coord(src.x + block_size.width, src.y + block_size.height)
self.random_fill(src, dst)
def random_fill(self, src, dst):
for y in range(src.y, dst.y):
for x in range(src.x, dst.x):
if random.random() < self.cell_probability:
self.map[y, x] = 1
else:
self.map[y, x] = 0
def init_replace_mode(self):
# 0: 00
# 1: 01
# 2: 10
# 3: 11
# self.map = np.multiply(self.map, 3)
pass
def conway_step(self):
# n_neighbor status
# 2 keep
# 3 live
# others died
table =[[0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0, 0, 0]]
def get_count(xx, yy):
summed = 0
for vx, vy in [(-1, 0), (1, 0), (0, -1), (0, 1),
(-1, -1), (-1, 1), (1, -1), (1, 1)]:
cur_x, cur_y = xx + vx, yy + vy
# out of border
cur_x = (cur_x + self.size.width) % self.size.width
cur_y = (cur_y + self.size.height) % self.size.height
#
summed += self.map[cur_y, cur_x] & 0x1
return summed
for y in range(self.size.height):
for x in range(self.size.width):
n_neighbors = get_count(x, y)
self.map[y, x] += table[self.map[y, x] % 2][n_neighbors] << 1
def finish_replace_mode(self):
self.map = np.right_shift(self.map, 1)
class ConwayAnimation(Conway):
def __init__(self):
Conway.__init__(self)
# ready for canvas
self.fig = plt.figure()
_ = animation.FuncAnimation(self.fig,
func=self.on_draw,
init_func=self.on_init,
interval=0,
blit=True)
plt.show()
def on_init(self):
self.im = plt.imshow(self.map, cmap='gray', animated=True)
return self.im,
def on_draw(self, frame_id):
print(frame_id)
self.init_replace_mode()
self.conway_step()
self.finish_replace_mode()
self.im.set_array(self.map)
return self.im,
def main():
ConwayAnimation()
if __name__ == "__main__":
main()
https://stackoverflow.com/questions/40485/optimizing-conways-game-of-life