🎄 - 2025 DAY 4 SOLUTIONS - 🎄
Day 4: Printing Department
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
26 replies
Uiua
Suspiciously easy. I even included a free animation generator for your entertainment.
Now you're just showing off!
Edit: ooh, this makes it obvious that my puzzle input takes more cycles to reach the done state.
Love a good visualisation <3
I was gonna do the same later when some free time, was wondering if it generated some kind of image.
If you click the link on that post, you'll see that the test data does resolve to a (very low res) elf!
That's a great addition :D
Running my own input I also noticed that your solution is a lot faster than mine (processing each roll individually). I'll keep that 2D-rotation in mind for the future.
Yeah, that's one thing the gurus keep hammering home: anything you can move out of loop constructs (inc rows, partition, etc as well as the obvious do, repeat) and handle pervasively is a big win.
Haskell
I tried rewriting part 2 to use a MutableArray, but it only made everything slower. So I left it at this. I saw somebody do a 1-second-challenge last year and I feel like that will be very hard unless I up my performance game.
::: spoiler Solution, Both Parts
:::
Python
Simple brute-force is enough.
Nim
Today was so easy, that I decided to solve it twice, just for fun. First is a 2D traversal (see above). And then I did a node graph solution in a few minutes (in repo below). Both run in ~27 ms.
It's a bit concerning, because a simple puzzle can only mean that tomorrow will be a nightmare. Good Luck everyone, we will need it.
Full solution is at Codeberg: solution.nim
C
For loops!
::: spoiler Code
:::
Repo
For my x86-16 version, the 20K input is pushing it over the 64K .COM limit, so I'll need to implement some better compression first.
Rust
I pulled out some code from last year to make representing 2D grids as a vector easier, so this was quite straightforward. 2.5ms runtime (including reading/parsing the input twice cos of TDD).
::: spoiler Full code
Javascript
After smashing out a functional version in 20 minutes, I converted it into a OOP approach for a more appealing solution.
::: spoiler Solution
:::
Kotlin
Pretty simple solution, just plain count / remove the rolls until none can be removed anymore. I would've liked to try using imaginary numbers this year (due to this article), but sadly Kotlin doesn't natively support them and I was too lazy to use a library.
::: spoiler Solution
:::
full code on Codeberg
Ha, I've got that article half-read in a tab somewhere. Same problem here though - they're not in the standard library for anything I plan to use for AoC.
Edit: looking at your code, I had forgotten about
.indices. That would have made this a little easier to write.I completely forgot to do the puzzle yesterday somehow. I struggled a bit on this one for a while because I'd used a
<= 4where I should have used a< 4. Just a complete brainfart of thinking, "It needs to be 4 or less". I wasted more time on that than I'd like to admit.My first stab at this set all of the adjacency counts to 0, and that lead to a few rolls that had no rolls adjacent to them staying on the map by accident.
Turns out on part 2 you can remove on access rather than after a full sweep of the grid, which cuts down the number of iterations you need to do about 1/2 sometimes 1/3 (depending on input).
Haskell
Very simple, this one.
Uiua
Quite simple this one. Part 2 still takes a few seconds because I'm essentially checking off each roll individually.
Run with example input
:::spoiler Code
:::
:::spoiler Old Part 2 Before seeing mykl's solution this was my solution for part 2
It's basically the same, just that I used a while-do-loop, making the check for the ending condition myself (which took me a bit to get right because I still find loops in Uiua a bit confusing).
Using the repeat-loop as above also gets rid of the
dip's (⊙). I could've removed them here as well but I was already deep in the trouble of getting the loop to work correctly and I liked the little face at the beginning 0⊙0 :::Rust
View on github
Go
Rust
Nothing really exciting here, was pretty straightforward
Kotlin
I'm catching up on this year's AOC.
This one was rather easy. I already have a pretty versatile grid class that I have just iterated as often as needed.
Doing this one also lead me into the rabbit hole that is source code generation in Gradle. I used this to generate all the implementations for the primitive types of the grid class as primitive arrays are not generic in the JVM.
An
Array<Int>is an array of integer references, but anIntArrayis an array of primitive integers.Code on GitHub ::: spoiler Code
:::
Haskell
Futhark
Only part 1 so far, I want to do part 2 later too.
This is my first ever futhark program. I have not yet figured out whether string parsing is possible or intended with this language. I used a combination of
sedandvimto bring the input into a formfutharkcan read.The highlighting is a bit off because I used
ocamlas the language. There is no futhark highlighter (at least in Web UI) yet.Edit: Part2
Also, it runs blazingly fast 🚀 :O, even in sequential C mode
Python
Send in the object orientation!
Honestly though, it was just a convenient way to keep things contained.
(Browser-based) Javascript
This was a good opportunity to refresh my grasp on the math involved in losslessly stuffing a tuple into a single number. JS-in-the-browser has Sets and Maps but no Tuples, and Arrays are indexed on their id / memory handle instead of their value contents, so if you want to put coordinates into a set or map and have the collection behave as expected you need to serialize the coordinates into a primitive type. Stuff it into a string if you don't want to think too hard. For this specific problem we don't even need to be able to compute the original coordinates (just count the unique removed points) but implementing that computation was a handy way to verify the "serializer" was working correctly.
Seeing as the record tuple proposal was withdrawn in February of this year this is still a technique worth knowing when working with coords in JS.
::: spoiler Code
:::