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/22

+114
+114
2023/day22.py
··· 1 + import fileinput 2 + import copy 3 + from itertools import permutations 4 + 5 + from utils import parse_nums 6 + 7 + 8 + def supports(b1, b2): 9 + # Returns true if b1 supports b2. 10 + ax, ay, az, bx, by, bz = b1 11 + cx, cy, cz, dx, dy, dz = b2 12 + 13 + b1_top = max(az, bz) 14 + b2_base = min(cz, dz) 15 + 16 + if b1_top + 1 != b2_base: 17 + return False 18 + 19 + ax, bx = min(ax, bx), max(ax, bx) 20 + ay, by = min(ay, by), max(ay, by) 21 + 22 + cx, dx = min(cx, dx), max(cx, dx) 23 + cy, dy = min(cy, dy), max(cy, dy) 24 + 25 + # can't support because off on one axis 26 + if bx < cx or ax > dx: 27 + return False 28 + 29 + if by < cy or ay > dy: 30 + return False 31 + 32 + return True 33 + 34 + def simulate(bricks): 35 + """Returns the set of brick IDs that moved in the simulation.""" 36 + all_touched = set() 37 + stationary = set() 38 + while True: 39 + moved = False 40 + for i, brick in enumerate(bricks): 41 + if i in stationary: 42 + continue 43 + 44 + # If the brick is on the ground, it can't fall more. 45 + if brick[2] == 1 or brick[5] == 1: 46 + stationary.add(i) 47 + continue 48 + 49 + # See if brick is supported by any other b2 50 + supported = False 51 + for j, b2 in enumerate(bricks): 52 + if i == j: 53 + continue 54 + 55 + if supports(b2, brick): 56 + # Can't fall because b2 supports brick, 57 + # but it might fall in a later tick. 58 + supported = True 59 + 60 + if j in stationary: 61 + # Nah, it won't. 62 + stationary.add(i) 63 + break 64 + 65 + if not supported: 66 + # Make the brick fall one tick. 67 + brick[2] -= 1 68 + brick[5] -= 1 69 + 70 + # Brick i has now moved in this simulation. 71 + all_touched.add(i) 72 + moved = True 73 + break 74 + 75 + if not moved: 76 + break 77 + 78 + return all_touched 79 + 80 + 81 + # Read problem input. 82 + BRICKS = [] 83 + for line in fileinput.input(): 84 + BRICKS.append(list(parse_nums(line.strip()))) 85 + 86 + # Try to simulate bricks lower to the ground first. 87 + BRICKS.sort(key=lambda b: min(b[2], b[5])) 88 + simulate(BRICKS) 89 + 90 + # graph[a] -> b means a supports b. 91 + graph = {i: set() for i in range(len(BRICKS))} 92 + for i, j in permutations(range(len(BRICKS)), 2): 93 + if supports(BRICKS[i], BRICKS[j]): 94 + graph[i].add(j) 95 + 96 + part_1 = 0 97 + part_2 = 0 98 + 99 + for k in graph: 100 + # Nothing above this brick. 101 + if not graph[k]: 102 + part_1 += 1 103 + continue 104 + 105 + # Simulate removing the brick. 106 + without_brick = [copy.copy(BRICKS[i]) for i in range(len(BRICKS)) if i != k] 107 + num_moved = len(simulate(without_brick)) 108 + if num_movedd == 0: 109 + part_1 += 1 110 + else: 111 + part_2 += num_moved 112 + 113 + print("Part 1:", part_1) 114 + print("Part 2:", part_2)