140 lines
3.6 KiB
Python
140 lines
3.6 KiB
Python
|
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
|
||
|
|