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
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]}')
|