π¨οΈ - 2024 DAY 5 SOLUTIONS - π¨οΈ
Day 5: Print Queue
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Nim
Solution: sort numbers using custom rules and compare if sorted == original. Part 2 is trivial.
Runtime for both parts: 1.05 ms
Codeberg repo
Nice, compact and easy to follow. The implicit
resultobject reminds me of Visual Basic.Oh! Sort first and then check for equality. Clever!
Kotlin
Took me a while to figure out how to sort according to the rules. π€―
I like how clean this is
I guess adding type aliases and removing the regex from parser makes it a bit more readable.
I wasn't being sarcastic, but yeah even better
Factor
on GitHub
Uiua
Well it's still today here, and this is how I spent my evening. It's not pretty or maybe even good, but it works on the test data... ::: spoiler spoiler Uses Kahn's algorithm with simplifying assumptions based on the helpful nature of the data. :::
Try it here
Does this language ever look pretty? Great for signaling UFOs though :D
Ah, but the terseness of the code allows the beauty of the underlying algorithm to shine through :-)
Oh my. I just watched yernab's video, and this becomes so much easier:
Dart
A bit easier than I first thought it was going to be.
I had a look at the Uiua discussion, and this one looks to be beyond my pay grade, so this will be it for today.
Haskell
Part two was actually much easier than I thought it was!
Rust
While part 1 was pretty quick, part 2 took me a while to figure something out. I figured that the relation would probably be a total ordering, and obtained the actual order using topological sorting. But it turns out the relation has cycles, so the topological sort must be limited to the elements that actually occur in the lists.
::: spoiler Solution
:::
also on github
Rust
Real thinker. Messed around with a couple solutions before this one. The gist is to take all the pairwise comparisons given and record them for easy access in a ranking matrix.
For the sample input, this grid would look like this (I left out all the non-present integers, but it would be a 98 x 98 grid where all the empty spaces are filled with
Ordering::Equal):I discovered this can't be used for a total order on the actual puzzle input because there were cycles in the pairs given (see how rust changed sort implementations as of 1.81). I used
usizefor convenience (I did it withu8for all the pair values originally, but kept having to cast over and overas usize). Didn't notice a performance difference, but I'm sure uses a bit more memory.Also I Liked the
simple_gridcrate a little better than thegridone. Will have to refactor that out at some point.::: spoiler solution
:::
On github
*Edit: I did try switching to just using
std::collections::HashMap, but it was 0.1 ms slower on average than using thesimple_grid::Grid...Vec[idx]access is faster maybe?I think you may have over thought it, I just applied the rules by swapping unordered pairs until it was ordered :D cool solution though
Good old bubble sort
Its called AdventOfCode, not AdventOfEfficientCode :D
Very cool approach. I didn't think that far. I just wrote a compare function and hoped for the best.
Python
Also took advantage of
cmp_to_key.Haskell
I should probably have used
sortByinstead of this ad-hoc selection sort.I was very much unhappy because my previous implementation took 1 second to execute and trashed through 2GB RAM in the process of doing so, I sat down again with some inspiration about the sorting approach.
I am very much happy now, the profiler tells me that most of time is spend in the parsing functions now.
I am also grateful for everyone else doing haskell, this way I learned about Arrays, Bifunctors and Arrows which (I think) improved my code a lot.
Haskell
Haskell
It's more complicated than it needs to be, could've done the first part just like the second.
Also it takes one second (!) to run it .-.
Well, this one ended up with a surprisingly easy part 2 with how I wrote it.
Not the most computationally optimal code, but since they're still cheap enough to run in milliseconds I'm not overly bothered.
::: spoiler C#
:::
Nim
I thought of doing a sort at first, but dismissed it for some reason, so I came up with this slow and bulky recursive backtracking thing which traverses the rules as a graph until it reaches a depth equal to the given sequence. Not my finest work, but it does solve the puzzle :)
Python
sort using a compare function
No need for
floor, you can just uselen(pages) // 2.nice one thanks
C
I got the question so wrong - I thought a|b and b|c would imply a|c so I went and used dynamic programming to propagate indirect relations through a table.
It worked beautifully but not for the input, which doesn't describe an absolute global ordering at all. It may well give a|c and b|c AND c|a. Nothing can be deduced then, and nothing needs to, because all required relations are directly specified.
The table works great though, the sort comparator is a simple 2D array index, so O(1).
::: spoiler Code
:::
https://github.com/sjmulder/aoc/blob/master/2024/c/day05.c
Same, I initially also thought a|b and a|c implies a|c. However when I drew the graph of the example on paper, I suspected that all relations will be given, and coded it with that assumption, that turned out to be correct
R
https://adventofcode.guslipkin.me/2024/05/2024-05
Rust
Used a sorted/unsorted comparison to solve the first part, the second part was just filling out the else branch.
Go
Using a map to store u|v relations. Part 2 sorting with a custom compare function worked very nicely
::: spoiler spoiler
:::
Because you're just sorting integers and in a single pass, the a == b and a > b distinction doesn't actually matter here, so the cmp can very simply be
is a|b in rules, no map needed.Edit: I realise it would be a sidegrade for your case because of how you did P1, just thought it was an interesting insight, especially for those that did P1 by checking if the input was sorted using the same custom compare.
Rust
I don't love this code, but I didn't initially use a hashmap and it runs so fast it wasn't worth the time to refactor.
Java
Part 2 was an interesting one and my solution kinda feels like cheating. What I did I only changed the validation method from part 1 to return the indexes of incorrectly placed pages and then randomly swapped those around in a loop until the validation passed. I was expecting this to not work at all or take forever to run but surprisingly it only takes three to five seconds to complete.
That's insane, you just bruteforced it. It definitely would not work for larger arrays
You're absolutely right. Good for me then that the inputs weren't any larger
Still in rust, and still inexperienced.
Forgot to make a separate solve for part two, for part one, imagine this without the make_valid function and some slightly different structure changes around the accumulator in babbage().
Used a hash map to track what should be in order, and a few indexed loops to keep track of where Iβm at and where to look forward.
Day 5
TypeScript
This one ended up being easier than I thought it was going to be. My algorithm for correcting the incorrect orders needed to be ran multiple times, for some reason
https://github.com/spencersolberg/advent-of-code-2024/tree/main/05
python
::: spoiler solution
:::
Julia
No really proud of todays solution. Probably because I started too late today.
I used a dictionary with the numbers that should be in front of any given number. Then I checked if they appear after that number. Part1 check. For part 2 I just hoped for the best that ordering it would work by switching each two problematic entries and it worked.
::: spoiler
:::
Kotlin
That was an easy one, once you define a comparator function. (At least when you have a sorting function in your standard-library.) The biggest part was the parsing. lol
Elixir
Zig
Lisp
::: spoiler Part 1 and 2
:::
Uiua
This is the first one that caused me some headache because I didn't read the instructions carefully enough.
I kept trying to create a sorted list for when all available pages were used, which got me stuck in an endless loop.
Another fun part was figuring out to use
memberof (β)instead offind (β)in the last line ofFindNext. So much time spent on debugging other areas of the codeRun with example input here
Smalltalk
parsing logic is duplicated between the two, and I probably could use part2's logic for part 1, but yeah
part 1
part 2
I've got a "smart" solution and a really dumb one. I'll start with the smart one (incomplete but you can infer). I did four different ways to try to get it faster, less memory, etc.
The dumb solution. These comparisons aren't fully transitive. I can't believe it works.
Python
(Part 1) omg I can't believe this actually worked first try!
Rust
Kinda sorta got day 5 done on time.
Reusing my
bytes_to_numfunction from day 3 feels nice. Pretty fun challenge.