You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
1.7 KiB

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()