66 lines
1.5 KiB
Python
66 lines
1.5 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
import itertools
|
||
|
import sys
|
||
|
from typing import Iterator, Set, Tuple
|
||
|
|
||
|
Point = Tuple[int, int, int]
|
||
|
Grid = Set[Point]
|
||
|
|
||
|
|
||
|
def update(grid: Grid) -> Grid:
|
||
|
def neightbours(p: Point) -> Iterator[Point]:
|
||
|
for dx, dy, dz in itertools.product(range(-1, 2), repeat=3):
|
||
|
if dx == 0 and dy == 0 and dz == 0:
|
||
|
continue
|
||
|
yield p[0] + dx, p[1] + dy, p[2] + dz
|
||
|
|
||
|
def count_neighbours(p: Point) -> int:
|
||
|
return sum(n in grid for n in neightbours(p))
|
||
|
|
||
|
new_grid: Grid = set()
|
||
|
seen: Set[Point] = set()
|
||
|
for p in grid:
|
||
|
for n in itertools.chain(neightbours(p), [p]):
|
||
|
if n in seen:
|
||
|
continue
|
||
|
seen |= {n}
|
||
|
active = n in grid
|
||
|
num_neighbours = count_neighbours(n)
|
||
|
|
||
|
if active and num_neighbours in [2, 3]:
|
||
|
new_grid |= {n}
|
||
|
elif active:
|
||
|
continue
|
||
|
elif num_neighbours == 3:
|
||
|
new_grid |= {n}
|
||
|
else:
|
||
|
continue
|
||
|
|
||
|
return new_grid
|
||
|
|
||
|
|
||
|
def solve(grid: Grid) -> int:
|
||
|
for __ in range(6):
|
||
|
grid = update(grid)
|
||
|
|
||
|
return len(grid)
|
||
|
|
||
|
|
||
|
def main() -> None:
|
||
|
input = [line.strip() for line in sys.stdin.readlines()]
|
||
|
print(
|
||
|
solve(
|
||
|
{
|
||
|
(i, j, 0)
|
||
|
for i, line in enumerate(input)
|
||
|
for j, x in enumerate(line)
|
||
|
if x == "#"
|
||
|
}
|
||
|
)
|
||
|
)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|