j0057 / aoc2018

Solutions to Advent of Code 2018

Home Page:https://adventofcode.com/2018

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Advent of Code 2018

Python solutions to Advent of Code 2018. Pytest is needed to run the tests as well as my new Pytest plugin pytest-aoc (GitHub, PyPI), to provide AoC test fixtures to the unit tests.

To run the Python code:

python3.7 -m pip install -r requirements.txt
python3.7 -m pytest

Day 1: Chronal Calibration

"Starting with a frequency of zero, what is the resulting frequency after all of the changes in frequency have been applied?" – solved with sum.

"What is the first frequency your device reaches twice?" – solved with a while loop, a set and itertools.cycle.

Day 2: Inventory Management System

"What is the checksum for your list of box IDs?" – it only took until day 2 for collections.Counter to save the day.

"What letters are common between the two correct box IDs?" – just zip and max.

Day 3: No Matter How You Slice It

"How many square inches of fabric are within two or more claims?" – used a collections.defaultdict.

"What is the ID of the only claim that doesn't overlap?" – used a set of all claims and removed all claims that were in a coordinate with more than one claim.

Day 4: Repose Record

"Find the guard that has the most minutes asleep. What minute does that guard spend asleep the most?" – first used itertools.groupby to make a dict of all the guards and their minutes, then max to find the sleepiest guard, then collections.Counter for the best time.

"Of all guards, which guard is most frequently asleep on the same minute?" – same as part one but a little different.

"What is the ID of the guard you chose multiplied by the minute you chose?"

Day 5: Alchemical Reduction

"How many units remain after fully reacting the polymer you scanned?" – used functools.reduce with a lambda that's a little too complex.

"What is the length of the shortest polymer you can produce by removing all units of exactly one type and fully reacting the result?" – same as part one but with an additional loop over the alphabet.

Day 6: Chronal Coordinates

"What is the size of the largest area that isn't infinite?" – did some research on properly calculating Voronoi diagrams, decided that the O(n log n) solution in Fortune's Algorithm looked like a lot of hard work, and went with the naive quadratic solution instead: for each cell, find the distances to all the points. For n=50, it runs fast enough on a Core i7-7700.

I did like calculating the bounding box using just two functools.reduce statements with min and max. Also used collections.Counter again, as well as functools.takewhile.

"What is the size of the region containing all locations which have a total distance to all given coordinates of less than 10000?" – not aware of any algorithms here so went with brute force again.

Day 7: The Sum of Its Parts

"In what order should the steps in your instructions be completed?" – this one was rather painful. I tried Depth-First Search recursively as well as iteratively, with the edges pointing from or to the dependencies, and got the wrong order every time. Found out I wanted a Topological Sorting instead, which I implemented using Kahn's Algorithm.

At least itertools.chain and itertools.groupby lessened the pain somewhat.

"With 5 workers and the 60+ second step durations described above, how long will it take to complete all of the steps?" – said "Fuck it", and hacked at Kahn's Algorithm until I got the right answer, but off by one. Said "Fuck it" again, added a -1 in the code, and AoC accepted the answer. Not my proudest moment.

Had to drag in collections.defaultdict again, to hold extremely hacky lambda function closures.

Day 8: Memory Maneuver

"What is the sum of all metadata entries?" – this was made really easy by Python's iterators, which can be consumed only once. The recursive Tree constructor uses itertools.islice to pluck values from the iterator.

"What is the value of the root node?" – could basically add the rules without too much thinking.

Day 9: Marble Mania

"What is the winning Elf's score?" – pretty straightforward implementation using a standard list.

"What would the new winning Elf's score be if the number of the last marble were 100 times larger?" – it turns out using list.insert and list.pop doesn't scale due to all the copying. Got referred to the blist package that acts as a fast drop-in replacement for Python's list. That one did get the job done. It did throw some warnings though and it's not compatible with PyPy, so I did the work to implement a Doubly-linked List. I opted for the 'hash linking' method, which cost me half an hour of pen-and-paper debugging. Also, it does take a good 5s to run...

Update: The solution from the reddit solution thread using collections.deque runs in 1.05s and reads much cleaner.

Day 10: The Stars Align

"What message will eventually appear in the sky?" – Implemented using an iterator. No unit tests, so I'll just link a screenshot:

day 10 output

"Exactly how many seconds would they have needed to wait for that message to appear?" – That's the number of iterations minus two...

Day 11: Chronal Charge

"What is the X,Y coordinate of the top-left fuel cell of the 3x3 square with the largest total power?" – just sum with two loops.

"What is the X,Y,size identifier of the square witoh the largest total power?" – wouldn't complete with approach from part one, had to implement a Summed-area table.

Day 12: Subterranean Sustainability

"After 20 generations, what is the sum of the numbers of all pots which contain a plant?"collections.defaultdict and itertools.islice, again.

"After fifty billion (50000000000) generations, what is the sum of the numbers of all pots which contain a plant?" – visualisation based on print(), and add 499999999000 to every grown plant position on iteration #1000.

Day 13: Mine Cart Madness

"To help prevent crashes, you'd like to know the location of the first crash." – parsed the text into a defaultdict (again) with a complex number for the coordinate as key, and the grid (without carts) as the value. Also parse the carts into a dictionary with a complex number as the key, and a tuple of (direction vector, next turn), both as complex numbers. This made it really ease to code the main loop.

"What is the location of the last cart at the end of the first tick where it is the only cart left?"– I think it's a bug to clear the crash site at the beginning of each iteration, but the bug would only manifest if three carts crash in the same tick.

Day 14: Chocolate Charts

"What are the scores of the ten recipes immediately after the number of recipes in your puzzle input?"

"How many recipes appear on the scoreboard to the left of the score sequence in your puzzle input?"

About

Solutions to Advent of Code 2018

https://adventofcode.com/2018


Languages

Language:Python 55.4%Language:Rust 44.2%Language:Shell 0.4%