day 20
This commit is contained in:
parent
4ed2e4cb41
commit
b0a5826b3f
|
@ -0,0 +1,99 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def cmp2dir(char):
|
||||
# Return (X,Y) translations corresponding to compass directions
|
||||
return {"N": (0, -1),
|
||||
"E": (1, 0),
|
||||
"S": (0, 1),
|
||||
"W": (-1, 0)}[char]
|
||||
|
||||
|
||||
def addpts(a, b):
|
||||
return (a[0] + b[0], a[1] + b[1])
|
||||
|
||||
|
||||
def parseregex(regex):
|
||||
ptr = 0
|
||||
|
||||
def parseblock():
|
||||
nonlocal ptr
|
||||
# recurses the () sections of a regex
|
||||
# we want to return the length of the longest sub path
|
||||
children = []
|
||||
curchild = []
|
||||
while True:
|
||||
if ptr == len(regex):
|
||||
children.append(curchild)
|
||||
return max(children)
|
||||
char = regex[ptr]
|
||||
ptr += 1
|
||||
if char == "(":
|
||||
curchild.append(parseblock())
|
||||
elif char == "|":
|
||||
children.append(curchild)
|
||||
curchild = []
|
||||
elif char == ")":
|
||||
children.append(curchild)
|
||||
curchild = []
|
||||
return children
|
||||
else: # Some NESW direction
|
||||
curchild.append(char)
|
||||
|
||||
return parseblock()
|
||||
|
||||
|
||||
def parselinks(res):
|
||||
|
||||
links = defaultdict(set) # mapping of roomA -> (roomB, ...) AND roomB -> (roomA, ...)
|
||||
|
||||
def parseres(sub, coords):
|
||||
nonlocal links
|
||||
for unit in sub:
|
||||
if isinstance(unit, str):
|
||||
# Step into another room
|
||||
# Add link from previous room to this room
|
||||
newroom = addpts(coords, cmp2dir(unit))
|
||||
links[newroom].update([coords])
|
||||
links[coords].update([newroom])
|
||||
coords = newroom
|
||||
else:
|
||||
parseres(unit, coords)
|
||||
|
||||
parseres(res, (0, 0))
|
||||
return links
|
||||
|
||||
|
||||
def main():
|
||||
with open("input.txt") as f:
|
||||
regex = f.read().strip()[1:-1]
|
||||
|
||||
# Parse a regex like 'NE(S|WW)' into a structure like [N, E, [[S], [W, W]]]
|
||||
res = parseregex(regex)
|
||||
# Parse the above output into coordinate links
|
||||
# E.g. the initial N creates a link between 0,0 and 0,-1 and vice-versa
|
||||
links = parselinks(res)
|
||||
|
||||
# Explore the links until all rooms have been visited
|
||||
frontier = [(0, 0)]
|
||||
room_distance = dict()
|
||||
dist = 0
|
||||
while frontier:
|
||||
new_frontier = []
|
||||
for room in frontier:
|
||||
if room in room_distance: # already found room
|
||||
continue
|
||||
room_distance[room] = dist
|
||||
new_frontier.extend(links[room])
|
||||
frontier = new_frontier
|
||||
dist += 1
|
||||
|
||||
print(max(room_distance.values()))
|
||||
print(len([i for i in filter(lambda x: x>=1000, room_distance.values())]))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue