Advent of Code 2019

The story of my slow descent into madness

View on GitHub
16 December 2019

Day 16: Flawed Frequency Transmission

by Simon Berger


Links:

We’re blessed with a very short puzzle today. But don’t let that concise description fool you because oh is it ever painful. It’s another one of those puzzles that lure you in with a relatively easy first part and then go “yeah now let’s scale it up”. Your cute little algorithm now has to do 7 orders of magnitude more work and even though you pray to the gods it just won’t be able to tackle it. At least not in under an hour.

What this usually means is that you have to find a way to cheat the system and calculate the result without actually putting in the work. I don’t really like this type of puzzle. In terms of challenge they’re great, but they force you to ignore parts of - if not the entire - story to solve them.

This may sound like I’m annoyed but I’m really not. Even though I wasn’t convinced by the puzzle in the context of advent of code’s story, it was still a good challenge and I’m quite fascinated by today’s puzzle.

As stated before, the first part can be solved by applying “bare” algorithm 100 times. This does take a bit of time, but it works. You could use partial sums to get it down to . I didn’t feel comfortable about this when I solved it though, so I just used the inefficient quadratic approach.

I solved the second part by abusing the fact that the offset points to the second half of the signal. This is really helpful because of the way the pattern is generated. For the item, each element in the base pattern is repeated times. If is the length of the signal and the pattern repeats times followed by repeated times. The result of an element in the signal only depends on the elements following it.

Using this we can calculate the value in the signal using the formula:

This can be performed in and thus the second part becomes easily solvable. All we need to do is run this algorithm over the elements starting from the offset to the end, repeat it another 99 times, and then read the result from offset to offset + 8 (exclusive).

This isn’t a general solution though, it only works when the output is found in the second half of the signal. A general solution using partial sums would probably take about a minute to complete.

Edit:

I came back to this puzzle on the same day because I really couldn’t let the inefficiency of the first part go. I played around with the idea of partial sums and got it working.

To give a brief overview of how it works: First, a list where each element contains the running sum of the signal values up to that point is constructed.

Then the code finds the relevant ranges where the pattern doesn’t return 0. The sum of a pattern range is easily determined using the running sums by taking the running sum at the end of the range r and subtracting the one at the start of the range l (). This sum is then multiplied by the pattern’s value at that position and added to the total.

The first part now runs ~70 times faster for the standard input length of 650. I didn’t touch the second part though.

tags: advent-of-code - rust
Overview
Previous day Next day