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.

Update solution for 2023/17

Represent state as the most recent direction moved and the number of
times we have moved in that direction sequentially, since that's the
only information that is actually relevant (essentially adding a 3rd
dimension to the traversal where we move down the Z-axis while moving
in the same direction and then pop up to layer z=0 when turning.)

+17 -20
+15 -20
2023/day17.py
··· 1 1 import fileinput 2 2 import heapq 3 3 4 - from utils import Point, DIRS, N, S, E, W 4 + from utils import Point, DIRS 5 5 6 6 7 7 def minimize_heat_loss(graph, start, goal=None, part_2=False): 8 - def gen_neighbours(node, hist): 8 + def gen_neighbours(node, last_dir, last_count): 9 9 for d in DIRS: 10 10 n = node + d 11 11 if n not in graph: 12 12 continue 13 13 14 - if hist: 14 + if last_dir is not None: 15 15 # No U-turns allowed. 16 - if hist[-1] == -d: 16 + if last_dir == -d: 17 17 continue 18 18 19 19 if part_2: 20 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]: 21 + if last_count < 4 and d != last_dir: 26 22 continue 27 23 28 24 # Wobbly ultra crucible. 29 - if len(hist) == 10 and all(x == d for x in hist): 25 + if last_count == 10 and d == last_dir: 30 26 continue 31 27 else: 32 28 # Unstable regular crucible. 33 - if len(hist) >= 3 and all(x == d for x in hist[-3:]): 29 + if last_count == 3 and last_dir == d: 34 30 continue 35 31 36 32 yield n, graph[n], d 37 33 38 - horizon = [(0, start, ())] 34 + horizon = [(0, start, None, 0)] 39 35 seen = set() 40 - buf_len = 10 if part_2 else 4 41 36 42 37 while horizon: 43 - depth, curr, hist = heapq.heappop(horizon) 38 + depth, curr, last_dir, last_count = heapq.heappop(horizon) 44 39 45 - if (curr, hist) in seen: 40 + if (curr, last_dir, last_count) in seen: 46 41 continue 47 42 48 - seen.add((curr, hist)) 43 + seen.add((curr, last_dir, last_count)) 49 44 50 45 # Check if at the bottom-right, and that our last 4 moves 51 46 # 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): 47 + if curr == goal and (not part_2 or last_count >= 4): 53 48 return depth 54 49 55 - for neighbour, weight, nd in gen_neighbours(curr, hist): 50 + for neighbour, weight, nd in gen_neighbours(curr, last_dir, last_count): 56 51 new_cost = weight + depth 57 - new_hist = hist + (nd,) 58 - heapq.heappush(horizon, (new_cost, neighbour, new_hist[-buf_len:])) 52 + new_count = 1 if nd != last_dir else last_count + 1 53 + heapq.heappush(horizon, (new_cost, neighbour, nd, new_count)) 59 54 60 55 61 56 # Read problem input.
+2
2023/utils.py
··· 458 458 return Point(-self.x, -self.y) 459 459 460 460 def __eq__(self, other): 461 + if type(other) != Point: 462 + return False 461 463 return self.x == other.x and self.y == other.y 462 464 463 465 def __ne__(self, other):