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