19
votes
Day 3: Rucksack Reorganization
Today's problem description: https://adventofcode.com/2022/day/3
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>
As you can tell, I love Python generators!
Part 1
Part 2
ooh,
string.ascii_letters
is nice here, i'm going to steal that :)My first instinct was to use
ord()
and subtract ascii values, but this worked out cleaner I think.Part 1
Really straightforward with sets
in-slice
make this trivial.Part 2:
Part 2
Speedrun
First attempt part 1: ~50% elapsed time:Instead of using converting both halves of the rucksack to sets, just convert the first half of the rucksack to a set and find the first member of that set in the second half of the rucksack
For part 2 ~66% elapsed time:
Ah, sets make a lot of sense, didn't think of them.
I went about it in a rather... procedural way, which felt dirty, but worked. xD
Part 1
And part 2 also makes use of hash-maps a lot.
Part 2
Part 1, in Python-ish
Python code generated from the above
Part 2, in Python-ish
Python code generated from the above
edit: replaced
λ c: ord(c) - (ord("a") if c.islower() else ord("A") - 26) + 1
withstring.ascii_letters.index | X + 1
.Elixir
Both parts
Pretty straightforward. I converted the appropriate strings or substrings to sets of characters, and then used set intersection to find the common character.
More swift!
Parts 1 and 2
Wow, Swift seems a lot like Rust
I really wish rusts HashSet implentation allowed finding the intersection of more than one other hashset at a time...
Driver
utilites
Part 1
Part 2
I remember an exercise to extend mergesort to multiple arrays. Many people used a priority queue, but my approach was much like mergesort itself, recursively break down the arrays into 2 halves. When one half was a single array or 2 arrays, use mergesort and return the result back up the stack.
I think it would work for set intersection too.
I thought this would be nicely doable using reduce, but it turns out that that solution is far from elegant.
Reduce multiple HashSets
It's actually not that bad; no type wrasslin', no weird methods or anything like that. (One thing I'd change is using
copied()
instead ofmap(|x| *x)
, but it's practically the same thing.)thats actually pretty clever...
Python
Sets!
Clojure (both parts)
Here's my TypeScript solution
Part 1
Part 2
These are both very similar. Another nice one for the sheetheads out there. Minor details in each. 7117/9122
Part 1
Basically, this is splitting the cell in half and adding L or R to each side along with the row number. From there I split by the diamond and flatten it. Once I have stuff like
2|L|p
I run UNIQUE on it so each group is cleansed of its dupes. Then I split again by the pipe and run the first QUERY. The second QUERY is a quick and dirty cleanup.Lastly, the VLOOKUP uses CODE for the letters, since VLOOKUP is case agnostic. CODE, as you guessed it, gives me the unicode map value.. and the rest is the VLOOKUP.
The SEQUENCEs at the end are generating code tables to convert the codes to the 1-52 values. I was doing it straight CODE(..)-x but that doesn't work as nicely for this.
Part 2
More of this trash, but this time instead of L and R for sets, I have `ROUNDUP((ROW(A2:A)-1)/3)` to get sets of three (1,2,3 round down to 1.. etc)Nothing crazy, just longer than I want it to be.
Ruby
Part 1
Part 2
Neat one.
Part 1
Part 2
Happy with how this turned out, though I think I learned that I need to find a more elegant way to interact with Python's
Set
, especially given how handy I find it in general.Parts 1 and 2
I enjoyed today!
Nim (both parts)
I think there's a better way for me to get the single item left after the intersections than popping, but I can't figure it out
I found today to be quite difficult with bash. Would love some feedback if anyone has any, particularly on how to make these faster.
Part 1+2
Part 1: we split the line into two even sections, separate each character, with a newline, sort it. We compare the sorted lines. Then, we convert the letter to a number with printf and add it on to our sum.Part 2: the same, except we don't split the line into two sections and we do two comparisons of the sorted lines.
Have you read the Pure Bash Bible? Although external commands may be fast at processing data, it is significantly more efficient to use builtins for small changes because you avoid the fork and startup time. Especially when you would otherwise use command substitution and piping, as those are already costly by themselves.
Some examples of simple substitutions you could make are
printf -v str %s {a..z}
instead ofstr=$(echo {a..z} | tr -d ' '
andupCase=${commonLetter^}
instead ofupCase=$(tr [:lower:] [:upper:]<<<$commonLetter)
.Beyond that, you can get creative with Bash's builtins and solve them in a completely different way. This may be a bit too arcane, but here's how I would solve it:
Part 1
Part 2
Both of these execute in ~0.010s on my machine. But if you want a more straightforward way to find the common letters, you can use Bash's associative arrays to do something like my AWK solution.
EDIT - One easier method for part 1:
Part 1
Thank you very much for taking the time to write these up. They run ~0.05s on my system, so about 100x faster than my solutions! I'd never seen that github page. It helped me find this resource too, so thanks for that!
I've broken out the assignment used in Part 1 to help myself understand them. I'm wondering why the expansion of ["$b"] with brackets works, but leaving the brackets off doesn't?
see this snippet
I'll note that your second solution to Part 1 is 0.009s on my system, so an even better speedup. Thanks again for giving me these tips.
No problem, Bash is always fun to hack on. The brackets denote a regex character class (e.g.,
[0-9]
) that matches any character in$b
.Late to the party, saved them for the workday. Feeling much better than Day 2. I abstracted better, so part 2 was not nearly as painful.
Typescript (both parts)
I'm using Rust this year, and trying to keep it
std
-only throughout the month.I had a lot of fun using a bitset for this one.
Part 1
Part 2