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 2023/17

+72
+72
2023/day17.py
··· 1 + import fileinput 2 + import heapq 3 + 4 + from utils import Point, DIRS, N, S, E, W 5 + 6 + 7 + def minimize_heat_loss(graph, start, goal=None, part_2=False): 8 + def gen_neighbours(node, hist): 9 + for d in DIRS: 10 + n = node + d 11 + if n not in graph: 12 + continue 13 + 14 + if hist: 15 + # No U-turns allowed. 16 + if hist[-1] == -d: 17 + continue 18 + 19 + if part_2: 20 + # Early ultra crucible turn. 21 + if len(hist) < 4 and d != hist[-1]: 22 + continue 23 + 24 + # Early ultra crucible turn. 25 + if len(set(hist[-4:])) != 1 and d != hist[-1]: 26 + continue 27 + 28 + # Wobbly ultra crucible. 29 + if len(hist) == 10 and all(x == d for x in hist): 30 + continue 31 + else: 32 + # Unstable regular crucible. 33 + if len(hist) >= 3 and all(x == d for x in hist[-3:]): 34 + continue 35 + 36 + yield n, graph[n], d 37 + 38 + horizon = [(0, start, ())] 39 + seen = set() 40 + buf_len = 10 if part_2 else 4 41 + 42 + while horizon: 43 + depth, curr, hist = heapq.heappop(horizon) 44 + 45 + if (curr, hist) in seen: 46 + continue 47 + 48 + seen.add((curr, hist)) 49 + 50 + # Check if at the bottom-right, and that our last 4 moves 51 + # were in the same direction if we're solving part 2. 52 + if curr == goal and (not part_2 or len(set(hist[-4:])) == 1): 53 + return depth 54 + 55 + for neighbour, weight, nd in gen_neighbours(curr, hist): 56 + new_cost = weight + depth 57 + new_hist = hist + (nd,) 58 + heapq.heappush(horizon, (new_cost, neighbour, new_hist[-buf_len:])) 59 + 60 + 61 + # Read problem input. 62 + graph = {} 63 + for y, line in enumerate(fileinput.input()): 64 + for x, c in enumerate(line.strip()): 65 + graph[Point(x, y)] = int(c) 66 + 67 + start = Point(0, 0) 68 + end = Point(x, y) 69 + 70 + # Solve problem. 71 + print("Part 1:", minimize_heat_loss(graph, start, end, part_2=False)) 72 + print("Part 2:", minimize_heat_loss(graph, start, end, part_2=True))