Skip to content

Commit c53a5c7

Browse files
committed
Added day 2018-13 (buggy v1 + version with works)
1 parent d434828 commit c53a5c7

File tree

2 files changed

+347
-0
lines changed

2 files changed

+347
-0
lines changed

2018/13-Mine Cart Madness.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# -------------------------------- Input data -------------------------------- #
2+
import os, pathfinding, re
3+
4+
test_data = {}
5+
6+
test = 1
7+
test_data[test] = {"input": """/->-\\
8+
| | /----\\
9+
| /-+--+-\ |
10+
| | | | v |
11+
\-+-/ \-+--/
12+
\------/ """,
13+
"expected": ['7,3', 'Unknown'],
14+
}
15+
16+
test += 1
17+
test_data[test] = {"input": r"""/>-<\
18+
| |
19+
| /<+-\
20+
| | | v
21+
\>+</ |
22+
| ^
23+
\<->/""",
24+
"expected": ['Unknown', '6,4'],
25+
}
26+
27+
test = 'real'
28+
input_file = os.path.join(os.path.dirname(__file__), 'Inputs', os.path.basename(__file__).replace('.py', '.txt'))
29+
test_data[test] = {"input": open(input_file, "r+").read(),
30+
"expected": ['124,130', '143, 123'],
31+
}
32+
33+
# -------------------------------- Control program execution -------------------------------- #
34+
35+
case_to_test = 'real'
36+
part_to_test = 2
37+
verbose = 3
38+
39+
# -------------------------------- Initialize some variables -------------------------------- #
40+
41+
puzzle_input = test_data[case_to_test]['input']
42+
puzzle_expected_result = test_data[case_to_test]['expected'][part_to_test-1]
43+
puzzle_actual_result = 'Unknown'
44+
45+
46+
# -------------------------------- Actual code execution -------------------------------- #
47+
48+
cart_to_track = {'^': '|', '>': '-', '<': '-', 'v': '|'}
49+
up, right, left, down = ((0, -1), (1, 0), (-1, 0), (0, 1))
50+
directions = {'^': up, '>': right, '<': left, 'v': down}
51+
new_dirs = {
52+
'^':['<', '^', '>'],
53+
'>':['^', '>', 'v'],
54+
'<':['v', '<', '^'],
55+
'v':['>', 'v', '<'],
56+
'/': {'^': '>', '>': '^', '<': 'v', 'v': '<'},
57+
'\\':{'^': '<', '>': 'v', '<': '^', 'v': '>'},
58+
}
59+
60+
61+
def move_cart (track, cart):
62+
(x, y), dir, choice = cart
63+
64+
x += directions[dir][0]
65+
y += directions[dir][1]
66+
67+
if track[y][x] == '+':
68+
dir = new_dirs[dir][choice]
69+
choice += 1
70+
choice %= 3
71+
elif track[y][x] in ('\\', '/'):
72+
dir = new_dirs[track[y][x]][dir]
73+
74+
return ((x, y), dir, choice)
75+
76+
# Setting up the track
77+
track = []
78+
cart_positions = []
79+
carts = []
80+
for y, line in enumerate(puzzle_input.split('\n')):
81+
track.append([])
82+
for x, letter in enumerate(line):
83+
if letter in cart_to_track:
84+
track[y].append(cart_to_track[letter])
85+
carts.append(((x, y), letter, 0))
86+
cart_positions.append((x, y))
87+
else:
88+
track[y].append(letter)
89+
90+
# Run them!
91+
tick = 0
92+
93+
carts.append('new')
94+
while len(carts) > 0:
95+
cart = carts.pop(0)
96+
if cart == 'new':
97+
if len(carts) == 1:
98+
break
99+
tick += 1
100+
# print ('tick', tick, 'completed - Remaining', len(carts))
101+
carts = sorted(carts, key=lambda x: (x[0][1], x[0][0]))
102+
cart_positions = [c[0] for c in carts]
103+
cart = carts.pop(0)
104+
carts.append('new')
105+
cart_positions.pop(0)
106+
107+
108+
109+
cart = move_cart(track, cart)
110+
111+
# Check collisions
112+
if cart[0] in cart_positions:
113+
if part_to_test == 1:
114+
puzzle_actual_result = cart[0]
115+
break
116+
else:
117+
print ('collision', cart[0])
118+
carts = [c for c in carts if c[0] != cart[0]]
119+
cart_positions = [c[0] for c in carts]
120+
else:
121+
carts.append(cart)
122+
cart_positions.append(cart[0])
123+
124+
if part_to_test == 2:
125+
puzzle_actual_result = carts[0][0]
126+
127+
128+
129+
# -------------------------------- Outputs / results -------------------------------- #
130+
131+
print ('Expected result : ' + str(puzzle_expected_result))
132+
print ('Actual result : ' + str(puzzle_actual_result))
133+
134+
135+
136+

2018/13-Mine Cart Madness.v1.py

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
2+
3+
# This v1 works for part 1, not part 2
4+
# Since it's also quite slow, I've done a v2 that should be better
5+
6+
7+
8+
9+
10+
11+
# -------------------------------- Input data -------------------------------- #
12+
import os, pathfinding, re
13+
14+
test_data = {}
15+
16+
test = 1
17+
test_data[test] = {"input": """/->-\\
18+
| | /----\\
19+
| /-+--+-\ |
20+
| | | | v |
21+
\-+-/ \-+--/
22+
\------/ """,
23+
"expected": ['Unknown', 'Unknown'],
24+
}
25+
26+
test += 1
27+
test_data[test] = {"input": r"""/>-<\
28+
| |
29+
| /<+-\
30+
| | | v
31+
\>+</ |
32+
| ^
33+
\<->/""",
34+
"expected": ['Unknown', 'Unknown'],
35+
}
36+
37+
test = 'real'
38+
input_file = os.path.join(os.path.dirname(__file__), 'Inputs', os.path.basename(__file__).replace('.py', '.txt'))
39+
test_data[test] = {"input": open(input_file, "r+").read(),
40+
"expected": ['124,130', '99, 96'],
41+
}
42+
43+
# -------------------------------- Control program execution -------------------------------- #
44+
45+
case_to_test = 'real'
46+
part_to_test = 2
47+
48+
# -------------------------------- Initialize some variables -------------------------------- #
49+
50+
puzzle_input = test_data[case_to_test]['input']
51+
puzzle_expected_result = test_data[case_to_test]['expected'][part_to_test-1]
52+
puzzle_actual_result = 'Unknown'
53+
54+
55+
# -------------------------------- Actual code execution -------------------------------- #
56+
57+
58+
def grid_to_vertices (self, grid, wall = '#'):
59+
self.vertices = []
60+
track = {}
61+
y = 0
62+
63+
for line in grid.splitlines():
64+
line = line.replace('^', '|').replace('v', '|').replace('>', '-').replace('<', '-')
65+
for x in range(len(line)):
66+
if line[x] != wall:
67+
self.vertices.append((x, y))
68+
track[(x, y)] = line[x]
69+
70+
y += 1
71+
72+
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
73+
right, left, down, up = directions
74+
75+
for coords in self.vertices:
76+
for direction in directions:
77+
x, y = coords[0] + direction[0], coords[1] + direction[1]
78+
79+
if track[coords] == '-' and direction in [up, down]:
80+
continue
81+
if track[coords] == '|' and direction in [left, right]:
82+
continue
83+
84+
if (x, y) in self.vertices:
85+
if track[coords] in ('\\', '/'):
86+
if track[(x, y)] in ('\\', '/'):
87+
continue
88+
if track[(x, y)] == '-' and direction in [up, down]:
89+
continue
90+
elif track[(x, y)] == '|' and direction in [left, right]:
91+
continue
92+
if coords in self.edges:
93+
self.edges[(coords)].append((x, y))
94+
else:
95+
self.edges[(coords)] = [(x, y)]
96+
97+
return True
98+
99+
pathfinding.Graph.grid_to_vertices = grid_to_vertices
100+
101+
def turn_left (direction):
102+
return (direction[1], -direction[0])
103+
104+
def turn_right (direction):
105+
return (-direction[1], direction[0])
106+
107+
108+
109+
110+
111+
# Analyze grid
112+
grid = puzzle_input
113+
graph = pathfinding.Graph()
114+
graph.grid_to_vertices(puzzle_input, ' ')
115+
116+
intersections = graph.grid_search(grid, '+')['+']
117+
118+
directions = {'^': (0, -1), '>': (1, 0), '<': (-1, 0), 'v': (0, 1)}
119+
dirs = {(0, -1): '^', (1, 0): '>', (-1, 0): '<', (0, 1): 'v'}
120+
121+
122+
# Find carts
123+
list_carts = graph.grid_search(grid, ('^', '<', '>', 'v'))
124+
carts = []
125+
cart_positions = []
126+
for direction in list_carts:
127+
dir = directions[direction]
128+
for cart in list_carts[direction]:
129+
carts.append((cart, dir, 0))
130+
cart_positions.append(list_carts[direction])
131+
del list_carts
132+
carts = sorted(carts, key=lambda x: (x[0][1], x[0][0]))
133+
134+
# Run them!
135+
subtick = 0
136+
tick = 0
137+
138+
nb_carts = len(carts)
139+
collision = 0
140+
while True:
141+
cart = carts.pop(0)
142+
cart_positions.pop(0)
143+
pos, dir, choice = cart
144+
new_pos = (pos[0] + dir[0], pos[1] + dir[1])
145+
146+
print (pos, choice, dirs[dir])
147+
148+
149+
# We need to turn
150+
if new_pos not in graph.edges[pos]:
151+
options = [((pos[0] + x[0], pos[1] + x[1]), x)
152+
for x in directions.values()
153+
if x != (-dir[0], -dir[1])
154+
and (pos[0] + x[0], pos[1] + x[1]) in graph.edges[pos]]
155+
new_pos, dir = options[0]
156+
157+
# Intersection
158+
if new_pos in intersections:
159+
if choice % 3 == 0:
160+
dir = turn_left(dir)
161+
elif choice % 3 == 2:
162+
dir = turn_right(dir)
163+
choice += 1
164+
choice %= 3
165+
166+
new_cart = (new_pos, dir, choice)
167+
168+
169+
170+
171+
172+
# Check collisions
173+
if new_cart[0] in cart_positions:
174+
if part_to_test == 1:
175+
puzzle_actual_result = new_cart[0]
176+
break
177+
else:
178+
print ('collision', new_cart[0])
179+
collision += 1
180+
carts = [c for c in carts if c[0] != new_cart[0]]
181+
cart_positions = [c[0] for c in carts]
182+
else:
183+
carts.append(new_cart)
184+
cart_positions.append(new_cart[0])
185+
186+
187+
# Count ticks + sort carts
188+
subtick += 1
189+
if subtick == nb_carts - collision:
190+
tick += 1
191+
subtick = 0
192+
collision = 0
193+
nb_carts = len(carts)
194+
carts = sorted(carts, key=lambda x: (x[0][1], x[0][0]))
195+
cart_positions = [c[0] for c in carts]
196+
197+
print ('End of tick', tick, ' - Remaining', len(carts))
198+
if len(carts) == 1:
199+
break
200+
201+
if part_to_test == 2:
202+
puzzle_actual_result = carts
203+
#99, 96
204+
# -------------------------------- Outputs / results -------------------------------- #
205+
206+
print ('Expected result : ' + str(puzzle_expected_result))
207+
print ('Actual result : ' + str(puzzle_actual_result))
208+
209+
210+
211+

0 commit comments

Comments
 (0)