74 lines
1.7 KiB
Python
74 lines
1.7 KiB
Python
|
import sys
|
||
|
|
||
|
from grid import Grid, near8
|
||
|
|
||
|
|
||
|
def main():
|
||
|
lines = [line.rstrip() for line in sys.stdin]
|
||
|
|
||
|
# Part 1
|
||
|
g = Grid(value_factory=lambda: ".", lines=lines)
|
||
|
while update(g):
|
||
|
pass
|
||
|
print("Occupied:", sum(v == "#" for _, _, v in g.values_gen()))
|
||
|
|
||
|
# Part 2
|
||
|
g = Grid(value_factory=lambda: ".", lines=lines)
|
||
|
while update2(g):
|
||
|
pass
|
||
|
print("Occupied part 2:", sum(v == "#" for _, _, v in g.values_gen()))
|
||
|
|
||
|
|
||
|
def update(g):
|
||
|
changes = {}
|
||
|
for x, y, v in g.values_gen():
|
||
|
if v == ".":
|
||
|
continue
|
||
|
p = (x, y)
|
||
|
n = list(g.near_objects(p, near_f=near8).values())
|
||
|
if v == "L" and n.count("#") == 0:
|
||
|
changes[p] = "#"
|
||
|
elif v == "#" and n.count("#") >= 4:
|
||
|
changes[p] = "L"
|
||
|
for (x, y), v in changes.items():
|
||
|
g.setv(x, y, v)
|
||
|
return bool(changes)
|
||
|
|
||
|
|
||
|
RAYS_OFS = [
|
||
|
(-1, -1), ( 0, -1), ( 1, -1),
|
||
|
(-1, 0), ( 1, 0),
|
||
|
(-1, 1), ( 0, 1), ( 1, 1),
|
||
|
]
|
||
|
|
||
|
|
||
|
def update2(g):
|
||
|
changes = {}
|
||
|
for x, y, v in g.values_gen():
|
||
|
if v == ".":
|
||
|
continue
|
||
|
occ = 0
|
||
|
for ox, oy in RAYS_OFS:
|
||
|
n = 1
|
||
|
while True:
|
||
|
qx, qy = x + ox * n, y + oy * n
|
||
|
if not g.hasv(qx, qy):
|
||
|
break
|
||
|
if (rv := g.getv(qx, qy)) == "#":
|
||
|
occ += 1
|
||
|
break
|
||
|
elif rv == "L":
|
||
|
break
|
||
|
n += 1
|
||
|
if v == "L" and occ == 0:
|
||
|
changes[(x, y)] = "#"
|
||
|
elif v == "#" and occ >= 5:
|
||
|
changes[(x, y)] = "L"
|
||
|
for (x, y), v in changes.items():
|
||
|
g.setv(x, y, v)
|
||
|
return bool(changes)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|