-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday13.py
106 lines (93 loc) · 3.7 KB
/
day13.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# Sadly not my solution - I needed a correct solution to help debugging mine
# https://www.reddit.com/r/adventofcode/comments/a5qd71/2018_day_13_solutions/ebolyq6/
from collections import defaultdict
from typing import List, Tuple, Dict
class Cart:
def __init__(self, pos: complex, di: complex):
self.position = pos
self.direction = di
self.cross_mod = 0
self.dead = False
def setup(input_file_lines: List[str]) -> Tuple[Dict[complex, str], List[Cart]]:
tracks = defaultdict(lambda: "") # only stores important tracks: \ / +
carts = []
for y, line in enumerate(input_file_lines):
for x, char in enumerate(line):
if char == "\n":
continue
if char in "<v>^":
direction = {
"<": -1,
"v": +1j,
">": +1,
"^": -1j,
}[char]
carts.append(Cart(x + y * 1j, direction)) # location, direction, crossings
part = {
"<": "-",
"v": "|",
">": "-",
"^": "|",
}[char]
else:
part = char
if part in "\\/+":
tracks[(x + y * 1j)] = part
return tracks, carts
def turn_cart(cart: Cart, part: str):
"""This space uses a downwards-facing Y axis, which means all calculations
must flip their imaginary part. For example, rotation to the left
(counterclockwise) would be multiplying by -1j instead of by +1j."""
if not part: # empty track is impossible, and | or - don't matter
return
if part == "\\":
if cart.direction.real == 0:
cart.direction *= -1j # ⮡ ⮢
else:
cart.direction *= +1j # ⮧ ⮤
if part == "/":
if cart.direction.real == 0:
cart.direction *= +1j # ⮣ ⮠
else:
cart.direction *= -1j # ⮥ ⮦
if part == "+":
cart.direction *= -1j * 1j ** cart.cross_mod # rotate left, forward, or right
cart.cross_mod = (cart.cross_mod + 1) % 3
def solve_a(input_file_lines: List[str]) -> str:
tracks, carts = setup(input_file_lines)
while True:
carts.sort(key=lambda c: (c.position.imag, c.position.real))
for ci, cart in enumerate(carts):
cart.position += cart.direction
if any(c2.position == cart.position for c2i, c2 in enumerate(carts) if c2i != ci):
return str(int(cart.position.real)) + "," + str(int(cart.position.imag))
# 14, 42
part = tracks[cart.position]
turn_cart(cart, part)
def solve_b(input_file_lines: List[str]) -> str:
tracks, carts = setup(input_file_lines)
while len(carts) > 1:
carts.sort(key=lambda c: (c.position.imag, c.position.real))
for ci, cart in enumerate(carts):
if cart.dead:
continue
cart.position += cart.direction
for ci2, cart2 in enumerate(carts):
if ci != ci2 and cart.position == cart2.position and not cart2.dead:
cart.dead = True
cart2.dead = True
break
if cart.dead:
continue
part = tracks[cart.position]
turn_cart(cart, part)
carts = [c for c in carts if not c.dead]
if not carts:
return "ERROR: there's an even number of carts, there's isn't 1 cart left at the end!"
cart = carts[0]
return str(int(cart.position.real)) + "," + str(int(cart.position.imag))
# 8,7
with open('day13-input.txt') as f:
lines = f.read().splitlines()
print(solve_a(lines))
print(solve_b(lines))