2018-12-13 - Mine Cart Madness
(original .ipynb)
puzzle_input = open("puzzle_input/day13.txt").readlines()
test_input = [
"/> <\\ ",
" ",
" /<+ \\",
" v",
"\\>+ ",
" ^",
" \\< >/",
]
class Elf(object):
def __init__(self, x, y, elf_char):
self.x = x
self.y = y
self.dir_x = 0
self.dir_y = 0
self.intersections = 0
self.active = True
if elf_char == "<":
self.dir_x = -1
elif elf_char == ">":
self.dir_x = 1
elif elf_char == "^":
self.dir_y = -1
elif elf_char == "v":
self.dir_y = 1
else:
raise Exception("INVALID ELF:", elf_char)
def any_collisions(self, elves):
return len([ elf for elf in elves if elf.x == self.x and elf.y == self.y ]) != 0
def corner(self, turn_type):
tmp = self.dir_x
if turn_type == "/":
self.dir_x = -self.dir_y
self.dir_y = -tmp
else:
self.dir_x = self.dir_y
self.dir_y = tmp
def intersection(self):
intersection_mod3 = self.intersections % 3
if intersection_mod3 == 0:
self.turn_left()
elif intersection_mod3 == 1:
pass
elif intersection_mod3 == 2:
self.turn_right()
self.intersections += 1
def turn_left(self):
if self.dir_x == 1 and self.dir_y == 0:
self.dir_x = 0
self.dir_y = -1
elif self.dir_x == 0 and self.dir_y == -1:
self.dir_x = -1
self.dir_y = 0
elif self.dir_x == -1 and self.dir_y == 0:
self.dir_x = 0
self.dir_y = 1
elif self.dir_x == 0 and self.dir_y == 1:
self.dir_x = 1
self.dir_y = 0
def turn_right(self):
if self.dir_x == 1 and self.dir_y == 0:
self.dir_x = 0
self.dir_y = 1
elif self.dir_x == 0 and self.dir_y == 1:
self.dir_x = -1
self.dir_y = 0
elif self.dir_x == -1 and self.dir_y == 0:
self.dir_x = 0
self.dir_y = -1
elif self.dir_x == 0 and self.dir_y == -1:
self.dir_x = 1
self.dir_y = 0
def step(self):
self.x += self.dir_x
self.y += self.dir_y
def split(str):
return [ c for c in str ]
def step_part_one(elves, track):
elves_to_move = list(sorted(elves, key=lambda elf: float(str(elf.y)+"."+str(elf.x))))
for i, elf in enumerate(elves_to_move):
if not elf.active:
continue
elf.step()
if track[elf.y][elf.x] in "/\\":
elf.corner(track[elf.y][elf.x])
elif track[elf.y][elf.x] == '+':
elf.intersection()
for j, other_elf in enumerate(elves_to_move):
if not other_elf.active:
continue
if i != j and elf.x == other_elf.x and elf.y == other_elf.y:
print("part one:", elf.x, elf.y)
return True
return False
def process_track(raw_track):
track = [ split(row) for row in raw_track ]
elves = []
for i, row in enumerate(track):
for j, col in enumerate(row):
if col in "<>^v":
elves.append(Elf(j, i, col))
track[i][j] = "."
return (elves, track)
def part_one(raw_track):
elves, track = process_track(raw_track)
done = False
while not done:
done = step_part_one(elves, track)
part_one(puzzle_input)
# def dump(elves, track):
# output = []
# for row in track:
# output.append([ c for c in row])
# for elf in elves:
# if elf.active:
# output[elf.y][elf.x] = "E"
# for row in output:
# print("".join(row))
# print()
part one: 123 18
def step_part_two(elves, track):
elves_to_move = list(sorted(elves, key=lambda elf: float(str(elf.y)+"."+str(elf.x))))
for i, elf in enumerate(elves_to_move):
if not elf.active:
continue
elf.step()
if track[elf.y][elf.x] in "/\\":
elf.corner(track[elf.y][elf.x])
elif track[elf.y][elf.x] == '+':
elf.intersection()
for j, other_elf in enumerate(elves_to_move):
if not other_elf.active:
continue
if i != j and elf.x == other_elf.x and elf.y == other_elf.y:
elf.active = False
other_elf.active = False
break
remaining_elves = [elf for elf in elves if elf.active]
if len(remaining_elves) == 1:
print("part two:", remaining_elves[0].x, remaining_elves[0].y)
return True
return False
def part_two(raw_track):
elves, track = process_track(raw_track)
done = False
while not done:
done = step_part_two(elves, track)
part_two(puzzle_input)
part two: 71 123
# let's animate this :D
from advent import grid_animated_render_frame, grid_animated_combine
palette = {
".": "orange",
"/": "orange",
"\\": "orange",
"/": "orange",
"-": "orange",
"|": "orange",
"+": "brown",
"e": "blue",
" ": "white",
"\n": "white"
}
def create_frame(elves, track):
frame = []
for row in track:
new_row = []
for tile in row:
new_row.append(tile)
frame.append(new_row)
for elf in elves:
frame[elf.y][elf.x] = "e"
return grid_animated_render_frame(frame, palette, cell_size=2)
def part_one_rendered(raw_track):
elves, track = process_track(raw_track)
done = False
frames = []
while not done:
done = step_part_one(elves, track)
frames.append(create_frame(elves, track))
if len(frames) == 500: # it goes too long
break
grid_animated_combine(frames, "day13-p1.gif", duration=33, show=True)
part_one_rendered(puzzle_input)
part one: 123 18