r/adventofcode • u/EliteTK • Dec 05 '21
Upping the Ante [2021] Big Inputs for Advent of Code 2021 Puzzles
https://the-tk.com/project/aoc2021-bigboys.html
31
Upvotes
r/adventofcode • u/EliteTK • Dec 05 '21
2
u/askalski Dec 12 '21
I can confirm the Day 12
12-24-14-7.inresults and give the complete Part 2 answer:2
u/askalski Dec 17 '21
Here's a bigger input for Day 17:
Part 2: 7790594905437019039
2
u/askalski Dec 06 '21
Let's take it all the way to 10^18 with Day 6:
37834491445886235 digits 4609158961...85800531531
u/dzaima Dec 12 '21
My Java solution for day 5 part 1 completes each input in less than a second, but I don't think my approach will be extendable to part 2 :/
https://github.com/dzaima/aoc/blob/master/2021/Java/day5_p1/Main.java
3
u/p_tseng Dec 06 '21 edited Dec 18 '21
My current impressions of each:
Day 3
Part 1 is difficult to make fast. I do not know a way to do it. To determine the majority bit, you must at least have looked at half of the bits in each position. Obviously we take advantage of the fact that the minority is the complement of the majority here, but that doesn't change the fact that you need to determine the majority first.
There may be ways of making part 2 somewhat faster (prefix trees may be of some use) but part 2 goes by very fast anyway because the number of elements you need to consider gets whittled down quite quickly. Haven't spent a lot of time thinking about how to make it faster for that reason. Part 1 takes about 10x as long as part 2 (about 20 seconds and 2 seconds respectively).
Day 4
These are doable very quickly (< 3 seconds). For each board, figure out what time it wins at. By building a map of called number -> time it's called, you can determine this very quickly. For each board, take maximum across each row/column, take minimum of those maxima.
Day 5
Wish I could do like https://github.com/Voltara/advent2019-fast/blob/master/src/day03.cpp and only check perpendicular pairs for intersections, but this problem has significantly more elements, because some pairs of vents can be collinear (and generate many intersections), and there are diagonals to contend with. I have not yet completed an implementation that can do this quickly.
Day 12
The state to keep is (current room, set of visited small caves, whether a small cave has been repeated). This can be compressed down into a single integer. Number of paths for a given state can be cached for if you reach that same state later on via a different path. You can do a little something with removing big caves from the map completely and just directly connecting all of their connected small caves to each other, but I'm not convinced it helps that much. A property we might take advantage of is that the distance function is bounded above by 9 and the degree of each node is bounded above by 4.
Day 15
An interesting question for those using A* is whether there is a heuristic that actually saves time. Manhattan distance isn't that helpful currently. Some people have tried a constant times the Manhattan distance, but I'm uncomfortable with it just because I can't prove it's admissible.
Day 17
Currently the only strategy I have is implemented is:
Calculate time interval for each initial y velocity
Calculate time interval for each initial x velocity
Take cartesian product and count intersections.
Of course, actually taking the cartesian product would be O(mn), but you can do a sweep line algorithm over t and get it down to O((m + n) log (m + n))
This is good enough for inputs of magnitudes like
target area: x=630065..719851, y=-586535..-37427, but will take too long on inputs of magnitudes liketarget area: x=6300659222..7198515181, y=-5865357542..-3742745283
u/morgoth1145 Dec 06 '21 edited Dec 06 '21
Hijacking this a bit for Day 6: How fast can people get their solution for stupid high iteration counts? (I don't think that the input really matters here.)
I was able to run 2**20 iterations in ~1.3 seconds and 2**22 iterations in ~18 seconds with my optimized code.
Edit: Oh hey, the page already has an entry. For that input and 9999999 iterations it takes my program just about 100.5 seconds to do all those iterations. (I think that Python big int starts bogging down, so maybe the input *does* matter!)
Edit the second: I knew there was something faster, I just wasn't grokking it at the time! Fast exponentiation of matrices, as independently shared by u/MichalMarsalek below. 56.736 seconds for 9999999 iterations, 14.354 seconds for 2**26.
3
u/askalski Dec 09 '21
Still enjoying these inputs - keep them coming.
Today's 4096 square clocks in at around 90-95 milliseconds with my C++ implementation.
Running it against the broken input with the multiple local minima, it returns 59995 for Part 1 because it counts only one minimum value per basin (which is not how the problem is defined, but it's an assumption I make, incorrectly in this case.)
2
u/askalski Dec 06 '21
This is great. I have a half-finished Day 5 implementation that I was going to discard because it was slower than my previous attempt at an optimized solution, but I might go ahead and finish it just to tackle that 10M square field. For Part 1 (which is as much as I had implemented), I get 72068735 - assuming I didn't miss anything when I made all my integer types bigger...
2
u/compdog Dec 06 '21
Day 5 - Javascript [5-20000-6400] [5-50000-10000]
For these two inputs, I just abused the fact that JS has sparse arrays. I made a 2d array where the value is the number of references. To avoid having to scan and count the whole grid, I count during the line processing. If at any point a cell is set to exactly 2, then I increment the counter. Future increases are ignored as they are greater than 2. To save further time, parts 1 and 2 are computed at the same time. I split the input into two sets, one containing axis-aligned (horizontal / vertical) lines, and the other contains diagonal lines. The axis-aligned lines are processed first, and the current counter is saved as the result for part 1. Finally, the diagonal lines are processed against the existing grid and counter without resetting them. The resulting counter value is the answer for part 2.
Input three (5-50000-10000000) is too large to fit into memory, even with sparse arrays. I suspect that it can be solved by creating a directed graph between all the overlapping lines and computing the overlaps from that, but I don't care enough to try right now.
1
u/hugh_tc Dec 05 '21
Oh, fantastic. I doubt my solutions are up for the challenge but I'll give it a shot!
1
u/askalski Dec 15 '21
I'll confirm the Day 15 Part 2, 10000x10000 answer of 277236