import fileinput import numpy DIRS = ["^", ">", "v", "<"] NORTH = 0 EAST = 1 SOUTH = 2 WEST = 3 TURN_LEFT = 0 TURN_STRAIGHT = 1 TURN_RIGHT = 2 carts = 0 cart_pos = [] cart_dirs = [] cart_turns = [] def get_cart(x, y): try: pos = cart_pos.index((x, y)) return pos except ValueError: raise IndexError def move_cart(cart, dx, dy): x, y = cart_pos[cart] cart_pos[cart] = (x + dx, y + dy) def remove_cart(cart): global carts carts -= 1 cart_pos.pop(cart) cart_dirs.pop(cart) cart_turns.pop(cart) def add_cart(x, y, dir_, turn=TURN_LEFT): global carts carts += 1 cart_pos.append((x, y)) cart_dirs.append(dir_) cart_turns.append(turn) def print_field(field): for y, row in enumerate(field): for x, value in enumerate(row.decode("ascii")): try: cart = get_cart(x, y) print("\033[31;1;4m" + DIRS[cart_dirs[cart]], end="\033[0m") if value == '-': print("\u0335", end="") elif value == '|': print("\u20D2", end="") except IndexError: print(value, end="") print() print() for cart in range(carts): x, y = cart_pos[cart] dir_ = DIRS[cart_dirs[cart]] turn = cart_turns[cart] print(f"- ({x:>3d}, {y:>3d}) {dir_} {turn}") print() inp = [] for y, line in enumerate(fileinput.input()): row = [] for x, value in enumerate(line.rstrip("\n")): if value == "^": add_cart(x, y, NORTH); row.append("|") elif value == ">": add_cart(x, y, EAST); row.append("-") elif value == "v": add_cart(x, y, SOUTH); row.append("|") elif value == "<": add_cart(x, y, WEST); row.append("-") else: row.append(value) inp.append(row) field = numpy.chararray((len(inp), len(inp[0]))) field[:] = inp one_more = False def step(): # Move the carts order = sorted(range(carts), key=lambda cart: cart_pos[cart], reverse=True) while order: cart = order.pop() if cart_dirs[cart] == NORTH: move_cart(cart, 0, -1) elif cart_dirs[cart] == EAST: move_cart(cart, 1, 0) elif cart_dirs[cart] == SOUTH: move_cart(cart, 0, 1) elif cart_dirs[cart] == WEST: move_cart(cart, -1, 0) value = field[cart_pos[cart][::-1]] if value == b"+": cart_dirs[cart] += cart_turns[cart] - 1 cart_dirs[cart] %= 4 cart_turns[cart] = (cart_turns[cart] + 1) % 3 elif value == b"/": if cart_dirs[cart] in (NORTH, SOUTH): cart_dirs[cart] = (cart_dirs[cart] + 1) % 4 else: cart_dirs[cart] = (cart_dirs[cart] - 1) % 4 elif value == b"\\": if cart_dirs[cart] in (EAST, WEST): cart_dirs[cart] = (cart_dirs[cart] + 1) % 4 else: cart_dirs[cart] = (cart_dirs[cart] - 1) % 4 elif value not in (b"-", b"|"): raise ValueError(value) u, c = numpy.unique(cart_pos, axis=0, return_counts=True) if len(u[c > 1]): for pos in u[c > 1]: print("crash at", pos) print(order) cart = get_cart(*pos) order = [x if x < cart else x - 1 for x in order if x != cart] remove_cart(cart) cart = get_cart(*pos) order = [x if x < cart else x - 1 for x in order if x != cart] remove_cart(cart) print(order) if carts == 1: print(cart_pos[0]) return False return True print_field(field) while step(): pass