My Advent of Code solutions in Python. kevinyap.ca/2019/12/going-fast-in-advent-of-code/
advent-of-code python
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add solution for 2019/20

+109
+109
2019/day20.py
··· 1 + import fileinput 2 + from string import ascii_uppercase 3 + from collections import defaultdict 4 + 5 + from utils import Point, DIRS 6 + 7 + 8 + MAZE = defaultdict(lambda: '#') 9 + PORTALS = defaultdict(set) 10 + PORTAL_MAP = {} 11 + 12 + AA = None 13 + ZZ = None 14 + 15 + INNERS = set() 16 + OUTERS = set() 17 + 18 + MAX_X = 0 19 + MAX_Y = 0 20 + 21 + # Read problem input 22 + for y, line in enumerate(fileinput.input()): 23 + for x, c in enumerate(line[:-1]): 24 + MAZE[Point(x, y)] = c 25 + MAX_X = max(MAX_X, x) 26 + MAX_Y = max(MAX_Y, y) 27 + 28 + # Determine the true label name and grid position of portals 29 + for p, c in MAZE.items(): 30 + if c in ascii_uppercase: 31 + name = '' 32 + if MAZE[p + Point(-1, 0)] in ascii_uppercase: 33 + name = MAZE[p + Point(-1, 0)] + c 34 + op = p + Point(-1, 0) 35 + elif MAZE[p + Point(1, 0)] in ascii_uppercase: 36 + name = c + MAZE[p + Point(1, 0)] 37 + op = p + Point(1, 0) 38 + elif MAZE[p + Point(0, -1)] in ascii_uppercase: 39 + name = MAZE[p + Point(0, -1)] + c 40 + op = p + Point(0, -1) 41 + elif MAZE[p + Point(0, 1)] in ascii_uppercase: 42 + name = c + MAZE[p + Point(0, 1)] 43 + op = p + Point(0, 1) 44 + 45 + for np in p.neighbours_4(): 46 + if MAZE[np] == '.': 47 + portal_loc = np 48 + for np in op.neighbours_4(): 49 + if MAZE[np] == '.': 50 + portal_loc = np 51 + 52 + if name == 'AA': 53 + AA = portal_loc 54 + elif name == 'ZZ': 55 + ZZ = portal_loc 56 + else: 57 + PORTALS[name].add(portal_loc) 58 + 59 + # Map portal positions and track inner/outer edges 60 + for x in PORTALS: 61 + a, b = list(PORTALS[x]) 62 + PORTAL_MAP[a] = b 63 + PORTAL_MAP[b] = a 64 + if a.x == 2 or a.x == (MAX_X - 2) or a.y == 2 or a.y == (MAX_Y - 2): 65 + OUTERS.add(a) 66 + INNERS.add(b) 67 + else: 68 + OUTERS.add(b) 69 + INNERS.add(a) 70 + 71 + 72 + def bfs(start, end, recursive=False): 73 + horizon = [(start, 0)] 74 + seen = set() 75 + steps = 1 76 + 77 + while horizon: 78 + new_horizon = [] 79 + for p, level in horizon: 80 + neighbours = p.neighbours_4() 81 + if p in PORTAL_MAP: 82 + if not (p in OUTERS and level == 0) or not recursive: 83 + neighbours.append(PORTAL_MAP[p]) 84 + for np in neighbours: 85 + new_level = level 86 + if recursive: 87 + if p in INNERS and np in OUTERS: 88 + new_level += 1 89 + elif p in OUTERS and np in INNERS and level > 0: 90 + new_level -= 1 91 + 92 + if (np, new_level) in seen: 93 + continue 94 + 95 + if MAZE[np] != '.': 96 + continue 97 + 98 + if np == end and new_level == 0: 99 + return steps 100 + 101 + seen.add((np, new_level)) 102 + new_horizon.append((np, new_level)) 103 + 104 + horizon = new_horizon 105 + steps += 1 106 + 107 + 108 + print "Steps in basic maze:", bfs(AA, ZZ) 109 + print "Steps in recursive maze:", bfs(AA, ZZ, recursive=True)