You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
3.1 KiB
Python

6 years ago
from pprint import pprint
from copy import deepcopy
from time import sleep
from asciimatics.screen import Screen
from random import randint
m = []
fix_map = {
'\n': ' ',
'^': '|',
'v': '|',
'>': '-',
'<': '-'
}
r_turns = { '^': '>', '>': 'v', 'v': '<', '<': '^' }
l_turns = { '^': '<', '>': '^', 'v': '>', '<': 'v' }
cart_symbols = ['^', 'v', '>', '<']
carts = []
class Cart:
def __init__(self, x, y, dir):
self.x = x
self.y = y
self.dir = dir
self.turn_counter = 0
@property
def pos(self):
return (self.y, self.x)
def turn_intersection(self):
if self.turn_counter == 0:
self.dir = l_turns[self.dir]
if self.turn_counter == 2:
self.dir = r_turns[self.dir]
self.turn_counter = (self.turn_counter + 1) % 3
def turn_corner(self, corner):
my_map = {
('/', '^'): '>',
('/', '>'): '^',
('/', 'v'): '<',
('/', '<'): 'v',
('\\', '^'): '<',
('\\', '>'): 'v',
('\\', 'v'): '>',
('\\', '<'): '^',
}
self.dir = my_map[(corner, self.dir)]
def move(self):
if self.dir == '^':
self.y -= 1
elif self.dir == '>':
self.x += 1
elif self.dir == 'v':
self.y += 1
elif self.dir == '<':
self.x -= 1
symbol = m[self.y][self.x]
if symbol in ['/', '\\']:
self.turn_corner(symbol)
if symbol == '+':
self.turn_intersection()
with open('input.txt', 'r') as f:
for y, line in enumerate(f.readlines()):
row = []
for x, symbol in enumerate(line):
row.append(fix_map.get(symbol) or symbol)
if symbol in cart_symbols:
carts.append(Cart(x, y, symbol))
m.append(row)
def print_map(screen):
m_cpy = deepcopy(m)
for cart in carts:
m_cpy[cart.y][cart.x] = cart.dir
for i, row in enumerate(m_cpy):
screen.print_at(''.join(row), 0, i)
def anim(screen):
while 1:
carts.sort(key=lambda x: x.pos)
for cart in carts:
cart.move()
# sleep(1)
print_map(screen)
ev = screen.get_key()
if ev in (ord('Q'), ord('q')):
return
screen.refresh()
# Screen.wrapper(anim)
def crashers():
to_rem = set()
for c1 in carts:
for c2 in carts:
if c1 is not c2 and c1.pos == c2.pos:
# print('crash at:', c1.pos)
to_rem.add(c1)
to_rem.add(c2)
return to_rem
def get_remaining():
while len(carts) > 1:
num_carts = len(carts)
carts.sort(key=lambda x: x.pos)
to_rem = set()
for cart in carts:
cart.move()
to_rem = to_rem.union(crashers())
for cart in to_rem:
carts.remove(cart)
if len(carts) != num_carts:
print(f'Reduces carts from {num_carts} to {len(carts)}')
return carts[0]
pos = get_remaining().pos
print(f'{pos[1]},{pos[0]}')