advent-of-code/2015/d18/ex2/ex2.py

70 lines
1.7 KiB
Python
Executable file

#!/usr/bin/env python
import itertools
import sys
from collections.abc import Iterator
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
def solve(input: str) -> int:
def parse(input: str) -> set[Point]:
return {
Point(x, y)
for x, line in enumerate(input.splitlines())
for y, c in enumerate(line)
if c == "#"
}
def neighbours(p: Point) -> Iterator[Point]:
for dx, dy in itertools.product((-1, 0, 1), repeat=2):
if dx == 0 and dy == 0:
continue
yield Point(p.x + dx, p.y + dy)
def step(lights: set[Point], dimensions: Point) -> set[Point]:
res = {
# Four corners are stuck on
Point(0, 0),
Point(0, dimensions.y - 1),
Point(dimensions.x - 1, 0),
Point(dimensions.x - 1, dimensions.y - 1),
}
for p in map(
Point._make,
itertools.product(range(dimensions.x), range(dimensions.y)),
):
num_alive = sum(n in lights for n in neighbours(p))
if p in lights and num_alive not in (2, 3):
continue
if p not in lights and num_alive != 3:
continue
res.add(p)
return res
lights = parse(input)
dimensions = Point(100, 100)
lights |= {
# Four corners are stuck on
Point(0, 0),
Point(0, dimensions.y - 1),
Point(dimensions.x - 1, 0),
Point(dimensions.x - 1, dimensions.y - 1),
}
for _ in range(100):
lights = step(lights, dimensions)
return len(lights)
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()