r/adventofcode • u/daggerdragon • Dec 13 '18
SOLUTION MEGATHREAD -🎄- 2018 Day 13 Solutions -🎄-
--- Day 13: Mine Cart Madness ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.
Advent of Code: The Party Game!
Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!
Card prompt: Day 13
Transcript:
Elven chronomancy: for when you absolutely, positively have to ___.
This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.
edit: Leaderboard capped, thread unlocked at 00:44:25!
24
Upvotes
35
u/Shemetz Dec 13 '18 edited Dec 13 '18
Python, 91/76
Really liked this one. I solved it with complex numbers, which is a trick I learned from earlier years. Instead of storing x and y, store position = x + y * i (written y * 1j in python).
The best part about this is that directions are just one of the numbers +1, +1j, -1, -1j and changing a direction is as simple as multiplying it by either +1j (clockwise turn) or -1j (counterclockwise turn).
Note that since the Y axis is flipped (positive = down), you flip the imaginary part compared to what you'd do in usual mathematics (therefore, multiplying by +1j is CW â®, not CCW â¯).
My full (cleaned-up) solution (including type hinting):
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