from lib import Grid2D, add2 CARTS = ( ("^", Grid2D.N, "|"), ("v", Grid2D.S, "|"), (">", Grid2D.E, "-"), ("<", Grid2D.W, "-"), ) TURNS = "lsr" DIRS = [(-1, 0), (0, 1), (1, 0), (0, -1)] def part_1(data): g = Grid2D(data) first_shown = False carts = [] occupied = set() for c, d, r in CARTS: for cart in g.find(c): carts.append((cart, d, "l")) g[cart] = r occupied.add(cart) for _ in range(1, 100_000): carts = sorted(carts) ncarts = [] i_to_skip = [] for i in range(len(carts)): if i in i_to_skip: continue pos, dir, turn = carts[i] occupied.remove(pos) pos = add2(pos, dir) # detect collision and remove carts if pos in occupied: if first_shown is False: print(f"{pos[1]},{pos[0]}") first_shown = True # either from carts that haven't moved, yet for j in range(len(carts)): jpos, _, _ = carts[j] if jpos == pos: i_to_skip.append(j) break else: # or from carts that have already moved ncarts = list(filter(lambda c: c[0] != pos, ncarts)) occupied.remove(pos) continue else: occupied.add(pos) if g[pos] == "+": if turn == "l": dir = DIRS[(DIRS.index(dir) - 1) % len(DIRS)] elif turn == "r": dir = DIRS[(DIRS.index(dir) + 1) % len(DIRS)] turn = TURNS[(TURNS.index(turn) + 1) % len(TURNS)] elif g[pos] == "/": if dir == g.E: dir = g.N elif dir == g.W: dir = g.S elif dir == g.N: dir = g.E elif dir == g.S: dir = g.W else: assert False elif g[pos] == "\\": if dir == g.E: dir = g.S elif dir == g.W: dir = g.N elif dir == g.N: dir = g.W elif dir == g.S: dir = g.E else: assert False ncarts.append((pos, dir, turn)) carts = ncarts if len(carts) == 1: pos = carts[0][0] print(f"{pos[1]},{pos[0]}") return def main(): input_file = __file__.replace(".py", ".txt") with open(input_file) as f: data = f.read() part_1(data) if __name__ == "__main__": main()