# Part 1

``````

In [24]:

import numpy as np

``````
``````

In [25]:

def parse(fn):
levels = []
with open(fn, 'rt') as f:
for l in f.readlines():
levels.append(l.rstrip('\n'))
return levels

``````
``````

In [69]:

class BluePrint:

def __init__(self, fn):
self.tracks = {}
self.carts  = []
levels = parse(fn)
under = dict(zip('^v<>|-/\\+ ', '||--|-/\\+ '))
for j, lev in enumerate(levels):
lev = list(lev)
for i, c in enumerate(lev):
pos = (i, j)
if c in '^>v<':
self.carts.append(Cart(pos, c))
self.tracks[pos] = under[c]

class Cart:

def __init__(self, pos, face):
self.pos       = pos
self.face      = face
self.turn      = 'l'

def step(self):

clockwise = [[0,-1],[1,0],[0,1],[-1,0]]
moves     = dict(zip('^>v<', map(np.array, clockwise)))
left      = dict(zip('^<v>', '<v>^'))
right     = dict(zip('^>v<', '>v<^'))
straight  = dict(zip('^<v>', '^<v>'))
turn      = dict(zip('lsr', [left, straight, right]))
next_turn = dict(zip('lsr', 'srl'))
corner    = {'/': dict(zip('^>v<', '>^<v')), '\\': dict(zip('^>v<', '<v>^'))}

self.pos = tuple(np.array(self.pos) + moves[self.face])
new = blueprint.tracks[self.pos]
if new == '+':
self.face = turn[self.turn][self.face]
self.turn = next_turn[self.turn]
if new in ['/', '\\']:
self.face = corner[new][self.face]

def first_collision():

carts = blueprint.carts
keep_moving = True
while keep_moving:
carts     = sorted(carts, key=lambda x: x.pos[::-1])
counter   = len(carts)
current   = list(map(lambda x: x.pos, carts))
while counter > 0:
cart = carts.pop(0)
current.pop(0)
cart.step()
carts.append(cart)
if cart.pos in current:
print(','.join(map(str, cart.pos)))
keep_moving = False
break
else:
current.append(cart.pos)
counter -= 1

``````

## Test

``````

In [80]:

blueprint = BluePrint('input_test1.txt')
first_collision()

``````
``````

7,3

``````

## Solution

``````

In [81]:

blueprint = BluePrint('input.txt')
first_collision()

``````
``````

41,17

``````

# Part 2

``````

In [87]:

def cartnage():

carts = blueprint.carts
while len(carts) > 1:
carts     = sorted(carts, key=lambda x: x.pos[::-1])
tick      = [1 for x in carts]
current   = list(map(lambda x: x.pos, carts))
while sum(tick) > 0:
cart = carts.pop(0)
current.pop(0)
tick.pop(0)
cart.step()
if cart.pos in current:
indices = [i for i, c in enumerate(carts) if c.pos != cart.pos]
carts = [carts[i] for i in indices]
tick = [tick[i] for i in indices]
current = [x.pos for x in carts]
else:
current.append(cart.pos)
carts.append(cart)
tick.append(0)
print(','.join(map(str, cart.pos)))

``````

## Test

``````

In [88]:

blueprint = BluePrint('input_test2.txt')
cartnage()

``````
``````

6,4

``````
``````

In [89]:

blueprint = BluePrint('input.txt')
cartnage()

``````
``````

134,117

``````