15
votes
Day 5: Supply Stacks
Today's problem description: https://adventofcode.com/2022/day/5
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>
Here's my Python solution -- my first this year that uses a defaultdict
and uses regex for the input parsing.
Part 1
Part 2
Update: added Speedrun.
Part 1
Parsing is relatively easy with the wonderful in-slice and a few helper procedures,
groups
andlines
from day 1 andintegers
(converting the result of regex\d+
to numbers).BUT... I lost so much time because I kept testing my parser with a pre-formatted, hard-coded list, rather than the 2 strings that
groups
returns. smhTo see how dumb I am, can anyone spot the difference between
and
good for you, because apparently I can't.
My take-away from this is simply not to bother testing your code before you run it.
Initially of course there was no
arrange-crates
ormove-with
- it was all hard-coded into part 1 and copy-pasted into part 2, but I feel icky with so much duplication, so I extracted them to post here.Part 2
Part 2 was so easy, just replace the
reverse
foridentity
(which in Racket isvalues
)Speedrun
Before each part took ~2.1 ms (after reading the file into a string) because each part built up the same data structure, total time ~4.3ms
Attempt 1: ~80% elapsed time
Removing the duplicated work building data structures, and re-use them for both parts.
Attempt 2: ~30% elapsed time
As always, one trick is to build your data structure/s as you read the file, instead of slurping the whole thing in and then running over it several times parsing values.
Two parsing phases, the drawing and the instructions.
These are pretty much the same with two significant changes.
Use a
hasheq
instead ofhash
and push each new crate to the front of the stack and reverse all stacks as a final step.Racket's
hasheq
is faster than a regularhash
because it useseq?
to test keys. For objectseq?
is identity (aka memory location), so super fast. Luckily integers areeq?
if their values are =, sohasheq
speeds up all hash operations.Instead of
adjoin
appending to the current stack, push the crate onto the existing stack. This means the parsed stacks are reversed so there's a final step to reverse them.Change part-01 and part-02 to accept the parsed stacks and instructions.
The rest is the same as before.
Part 1, in Python-ish
Python code generated from the above
Part 2, in Python-ish
Python code generated from the above
i have also been challenging myself to solve each puzzle in a single expression. here are my single-expression solutions for today:
Part 1, in Python-ish
Python code generated from the above
Part 2, in Python-ish
Python code generated from the above
Python
Update
FromTo
Yeah, the parsing took more time than both solutions…
Is this the first advent of code challenge where the answer is a string instead of an integer? I had to update the Deno helper library I wrote to deal with this change.
I'm considering rewriting my parse function to use some parser library in order to practice with them, or doing that for future challenges if the input gets more complicated.
Multiple parts of my answer were written using Github Copilot. The main reason for some of the comments in my code was to help Copilot figure out what I wanted to do and write what I needed. It's amazing how well it works. It wrote the code to split each line into groups of four characters, the code to create
Procedure
objects out of a regex match, and both// execute procedure,
blocks.Typescript (Deno)
day 13 last year had a string answer
There have been previous years where the answer was not only text, but text based on ASCII renders of text, e.g.
Nice warmup to some familiar AoC patterns.
Part 1
Part 2
Still doesn't feel idiomatic, because I use a bunch of mutation, but it's getting easier to write down what I want to do, so that's a win. Now I just have to not do the unidiomatic thing. xD
Racket:
Part 1
And Part 2:
Part 2
Here's my TypeScript solution
Part 1
Part 2
Rust
Rust
Going to be honest, I saw a chance to whip out
deque
and I just went for it even though nothing in part 1 indicated that it couldn't be handled with a regular Python list. It was probably actually a hinderance overall, but I still enjoyed getting to play with it. You may also notice that I didn't use regex, which is because I have not really used it in Python and continue to get away with that.On the feedback front, if anyone here is familiar with
mypy
and it's enforcement of static typing, is there any good way to fill or construct a tuple using a loop while enforcing its length? I kept trying to do that with the translated instructions in my input parsing function but eventually gave up and hand wrote the bit since it was only 3 elements anyway.Parts 1 and 2
Is mypy smart enough to take
assert
statements into account? You could stick anassert len(breakdown) == 3
in there and see how mypy responds.Edit: Oops, I misread your code.
breakdown
isn't the 3-tuple. But maybeassert
could help nonetheless.An interesting idea, but I don't think assertions are accounted for when mypy parses the code. Something like this:
...yields this complaint:
I also tried hinting
test
asTuple[int, int, int]
but that got a type mismatch on assignment complaint. I think mypy will always assume that a tuple constructed from a loop or comprehension is indeterminate in size :/I think as I learn more nim I'll be able to come back to this one and clean it up a bit, but anyways, it works for now :P
nim (both parts)
Elixir
Most of the work for this one was parsing the input, IMO!
Both parts
Took me a while to get the arrays transposed in bash, but I did it all in native bash which is a big step up in the last few days! Both solutions run at or less than 0.1s, which I will happily take. It was my first time working with associative arrays in bash.
Part 1+2
Ruby
Part 1
Part 2
90% of the work today was just parsing the input. Once I had that, implementing the moves was pretty straightforward.
Driver
Utilities
Part 1
Part 2
I'm using Rust this year, and trying to keep it
std
-only throughout the month.Part 1
Part 2