-
Notifications
You must be signed in to change notification settings - Fork 0
/
better_way_56.py
133 lines (110 loc) · 3.19 KB
/
better_way_56.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
""" better way 57, 58, 59 에서는 동시성을 설명하기 위해 이 코드를 기반삼아 이용한다.
팬아웃(fan-out)은 동시에 실행되는 여러 실행 흐름을 만들어내는 과정을 의미한다.
팬인(fan-in)은 동시 작업 단위의 작업이 모두 끝날 때까지 기다리는 과정을 의미한다.
"""
import typing
import time
from utils import colorprint
ALIVE = '*'
EMPTY = '_'
class Grid:
def __init__(
self, /, *,
width: int = 0,
height: int = 0,
):
assert width > 0 and height > 0
self.width = width
self.height = height
self.rows = []
for _ in range(self.height):
self.rows.append([EMPTY] * self.width)
def get(self, y, x):
return self.rows[y % self.height][x % self.width]
def set(self, y, x, state):
assert state in [ALIVE, EMPTY]
self.rows[y % self.height][x % self.width] = state
def __str__(self) -> str:
lines = []
for row in self.rows:
line = ''.join(row)
lines.append(line)
return '\n'.join(lines)
def count_neighbors(
y: int,
x: int,
get: typing.Callable,
) -> int:
n_ = get(y - 1, x + 0)
ne = get(y - 1, x + 1)
e_ = get(y + 0, x + 1)
se = get(y + 1, x + 1)
s_ = get(y + 1, x + 0)
sw = get(y + 1, x - 1)
w_ = get(y + 0, x - 1)
nw = get(y - 1, x - 1)
neighbor_states = [n_, ne, e_, se, s_, sw, w_, nw]
count = 0
for state in neighbor_states:
if state == ALIVE:
count += 1
return count
def game_logic(
state,
neighbors,
io_blocking_time: float = 0.01,
io_error: bool = False
):
""" 특정 셀과 해당 셀 근처에 몇 개의 이웃이 있는지를 확인하여
해당 셀이 다음 세대에 생존할 수 있는지 판단합니다.
"""
if io_blocking_time:
# print('I/O Blocking ... ')
time.sleep(io_blocking_time)
if io_error:
raise IOError
if state == ALIVE:
if neighbors < 2:
return EMPTY
elif neighbors > 3:
return EMPTY
else:
if neighbors == 3:
return ALIVE
return state
def step_cell(
y: int,
x: int,
get: typing.Callable,
set: typing.Callable,
) -> None:
""" 그리드 내 특정 위치 주변의 상태를 확인한 뒤
다음 세대의 결과에 해당 값을 반영합니다.
"""
state = get(y, x)
neighbors = count_neighbors(y, x, get)
next_state = game_logic(state, neighbors)
set(y, x, next_state)
def simulate(grid: Grid) -> Grid:
h, w = grid.height, grid.width
next_grid = Grid(width=w, height=h)
for y in range(h):
for x in range(w):
step_cell(y, x, grid.get, next_grid.set)
return next_grid
if __name__ == '__main__':
grid = Grid(width=5, height=5)
grid.set(0, 3, ALIVE)
grid.set(1, 4, ALIVE)
grid.set(2, 2, ALIVE)
grid.set(2, 3, ALIVE)
grid.set(2, 4, ALIVE)
colorprint('게임 시작')
s = time.time()
print(grid)
for i in range(5):
grid = simulate(grid)
print('..')
print(grid)
e = time.time()
colorprint(f'게임 끝, {e-s:.2f}초 소요됨.')