aoc2024/day06.py
2024-12-07 07:58:03 +01:00

81 lines
1.8 KiB
Python

#!/usr/bin/env python3
m = []
obstacles = set()
start = (-1,-1)
lx = ly = 0
with open('day06') as f:
for y,l in enumerate(f):
ly += 1
lx = lx or len(l)
for x,ll in enumerate(l):
match ll:
case '#': obstacles.add((y,x))
case '^': start = (y,x)
lookup = {
(-1, 0): ( 0, 1),
( 0, 1): ( 1, 0),
( 1, 0): ( 0,-1),
( 0,-1): (-1, 0)
}
# 1
def walk(pos, dir):
visited = []
visited.append((pos, dir))
npos = (pos[0]+dir[0], pos[1]+dir[1])
while True:
while npos not in obstacles:
pos = npos
visited.append((pos,dir))
npos = (pos[0]+dir[0], pos[1]+dir[1])
if npos[0]==ly or npos[0]==-1: return visited
if npos[1]==lx or npos[1]==-1: return visited
dir = lookup[dir]
npos = (pos[0]+dir[0], pos[1]+dir[1])
visited = walk(start, (-1,0))
vpos = set([v[0] for v in visited])
res1 = len(vpos)
# 2
def loop(pos, dir, sv, obstacles):
while True:
npos = (pos[0] + dir[0], pos[1] + dir[1])
if npos[0]==ly or npos[0]==-1: return False
if npos[1]==lx or npos[1]==-1: return False
while npos not in obstacles:
sv.add((pos,dir))
pos = npos
npos = (pos[0]+dir[0], pos[1]+dir[1])
if (pos, dir) in sv:
return True
if npos[0]==ly or npos[0]==-1: return False
if npos[1]==lx or npos[1]==-1: return False
dir = lookup[dir]
done = set()
res2 = 0
for k,(pos,_) in enumerate(visited):
if pos == start: continue
if pos in obstacles: continue
if pos in done: continue
done.add(pos)
start = visited[k-1][0]
dir = visited[k-1][1]
sv = set(visited[:k])
if loop(start, dir, sv, obstacles | {pos}):
res2 += 1