81 lines
1.8 KiB
Python
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
|