11
votes
Day 14: Extended Polymerization
Today's problem description: https://adventofcode.com/2021/day/14
Please post your solutions in your own top-level comment. Here's a template you can copy-paste into your comment to format it nicely, with the code collapsed by default inside an expandable section with syntax highlighting (you can replace python
with any of the "short names" listed in this page of supported languages):
<details>
<summary>Part 1</summary>
```python
Your code here.
```
</details>
Like day 6, this can be done in O(log(n)) via exponentiation by squaring:
Part 2, Python(-ish)
Python (which the above is transpiled to)
In practice though, with n = 40 this is slower than the O(n) algorithm.
If Sheets didn't have a 50k limit I could simply drag for part two... but I guess that is the design of the challenge. I have no idea.
Part 1
``` =ARRAYFORMULA( CONCATENATE( RIGHT( REGEXREPLACE( MID(A2,SEQUENCE(LEN(A2)-1),2), "(.)(.)", "$1"& IFERROR( VLOOKUP( MID(A2,SEQUENCE(LEN(A2)-1),2), IF(ISBLANK($A$4:$A),, IFERROR( SPLIT($A$4:$A," -> "))), 2,FALSE))), 2))&RIGHT(A2,1)) ```Then for the output
From there, change the reference to the one above and drag that shit down. I hate formulas like this, but I think its the only way.
I'll give it another hour before I give up. I skipped the last three days due to a mix of stubbornness and limitations (both knowledge and Sheets itself.)
I'm at 19 stars so far. I did 25 last year, so if I get that, I'll be happy. Worst case I can go through and suffer through these crappy drag-fill formulas for the last few days.
Oh no
Part 1
Part 2
This was fun! It was pretty clear that we'd need to do more than just let the string grow forever, so I started out with the optimized version. I figured out how I wanted to optimize pretty quickly, but spent quite a while debugging my pair counting logic.
Possible spoiler
I also really liked how the style of optimization closely recalls the lanternfish puzzle from before, in that instead of tracking each element separately in memory, we just keep a count of each type/pair.Part 1 Ruby
Part 2 Ruby
With the optimization already done, we just run the loop a few more times.
I KNEW there was another trap coming. I don't know how I knew, but I just felt it.
Day 14 Part A - Python
I took a bit of a gamble and assumed order wasn't going to matter for this, so I just looked at how one pair turns into 2 pairs and kept a count of how many of each pair I had. I added the elements after the fact because that seemed like the easiest way to figure out the individual elements. It basically rides on the back of the pairs calculation which is doing the real work
Day 14 Part B - Python
It's the same except for changing the run duration
Tips
This is another efficiency problem, your number of elements almost, but not quite doubles every pass
If you approach the problem certain ways, order doesn't end up being super important
Data Structure
I'm using 3 hashes stored together in a list.
Part 1
To update the polymer template, I iterate through the element pairs, generating a new count of pairs along the way. For each pair:
Part 2
lol
Python
Day 14 (Rust)
Intuition
This is the Lanternfish problem again, in different clothes.
Instead of counting single fish, we're counting pairs of characters. Each insertion AxB reduces the count of AB polymers to zero, and correspondingly increases the count of Ax and xB polymers.
The added twist is that you have to cache the updates, because the addition only takes effect after a round of substitutions is complete.
Frustration
I wrote the preceeding paragraph before I started programming, and I guess I stand by it still: the solution is very simple, you just have to execute it right.This was a Day 8 all over again for me. Simple problem, simple solution, but I botched it at some point and spent the better part of 1.5h chasing the bug. Unfortunately the test-cases were of no help, because my code passed them with flying colors -- it would just not produce an answer that the site would accept.
In desperation, I finally caved on my "only Rust" rule and hacked together a small Ruby script that did it by brute-force and then compared its output, step by painful step. Turns out that I was overwriting my character counts at one place instead of adding them; this only manifests if the same character pair appears twice, which is why the test input worked, but the real one didn't.
Since it took me so long, today's code is even less clean than usually.
Imports and data structures
Parsing
Helper functions
Solving
Relatable :P
Rust
For part 1 I took the naieve approach of building the polymer. I figured I'd try to brute force part 2 but alas. I had to think about it for a long time but eventually figured it out.
Rust
Looking through this code is a bit like archaeology, in that you can see the time before I saw part two, looked for hints, and came up with a dumb joke, and the time after. My solution for part two is sometimes off by 1, but I was lazy and rather than figure out exactly how to make it not be off by one, I just threw it in, saw whether I was high or low, and resubmitted after the timer ran out. Not my finest work, but I got the stars and only looked a little bit at hints from @PapaNachos and @Crespyl, and now that I see their solutions I even see how I should have done the counts for part 2. Thanks for being helpful people!
Parts 1 and 2
Rust
Did part 1 with brute force because I wanted to get the first star in (even though I guess what part 2 would be and assumed brute force wouldn't work for it). Eventually figured out how to refactor for part 2.
Part 1 (before refactor)
Both Parts (after refactor)
Discussion(?)
I could probably make it run a bit faster (not that it's particularly slow right) if I passed the number of steps to my
do_steps
function and iterated there so that I didn't have to pass the map to the function so much.I guess I could also just keep track of the very last letter and add a count of 1 for that letter instead of keeping track of the last pair.
Elixir
Does it work for both parts? Yes.
Does it run quickly? Yes—3.5ms for part 2.
Will I explain my nightmare code? ...No.
Both parts