🦌 - 2024 DAY 2 SOLUTIONS -🦌
Day 2: Red-Nosed Reports
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://blocks.programming.dev 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/22323136
- 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
48 replies
Haskell
This was quite fun! I got a bit distracted trying to rewrite
safein point-free style, but I think this version is the most readable. There's probably a more monadic way of writinglessOneas well, but I can't immediately see it.Love to see your haskell solutions!
I am so far very amazed with the compactness of your solutions, your
lessOneis very much mind-Bending. I have never used or seen<$>before, is it a monadic$?Also I can't seem to find your logic for this safety condition:
The levels are either all increasing or all decreasing, did you figure that it wasn't necessary?For the last point, it isn't needed since the differences between elements should be all positive or all negative for the report to be safe. This is tested with the combination of
negateandgradual.I am also enjoying these Haskell solutions. I'm still learning the language, so it's been cool to compare my solution with these and grow my understanding of Haskell.
<$>is justfmapas an infix operator.Thanks! The other two posters already answered your questions, I think :)
Haskell makes it really easy to build complex operations out of simple functional building blocks, skipping a lot of boilerplate needed in some other languages. I find the compactness easier to read, but I realize that not everyone would agree.
BTW, I'm a relative Haskell newbie. I'm sure more experienced folks could come up with even more interesting solutions!
Rust
The function is_sorted_by on Iterators turned out helpful for compactly finding if a report is safe. In part 2 I simply tried the same with each element removed, since all reports are very short.
is_sorted_byis new to me, could be very useful.The
is_sorted_byis a really nice approach. I originally tried using that function thinking that|a, b| a > bor|a, b| a < bwould cut it but it didn't end up working. I never thought to handle the check for the step being between 1 and 3 in the callback closure for that though.C
First went through the input in one pass, number by number, but unfortunately that wouldn't fly for part 2.
::: spoiler Code
:::
https://github.com/sjmulder/aoc/blob/master/2024/c/day02.c
What is this coding style? The function type, name and open brace placement made me think GNU at first, but the code in the body doesn't look like GCS at all.
BSD more or less. Mostly K&R except for function declarations.
Haskell
Took me way too long to figure out that I didn't have to drop one of them differences but the initial Number
Uiua
Uiua is still developing very quickly, and this code uses the experimental
tuplesfunction, hence the initial directive.Try it Live!
How do you write this, not conceptually but physically. Do you have a char picker open at all times?
Haha, you can do it that way, in fact the online Uiua Pad editor has all the operators listed along the top.
But all the operators have ascii names, so you can type e.g.
IsSmall = reduce mul mul fork(>0|<4) abs drop neg 1 - rot 1 dupand the formatter will reduce that toIsSmall ← /××⊃(>0|<4)⌵↘¯1-↻1.whenever you save or execute code.That works in the Pad, and you can enable similar functionality in other editors.
I like to assume people using array programming languages just have a crystal ball that they use to call upon magic runes on the screen
This looks so alien! Does it work with the full set? The comment says 5, choose 4, but I guess it’s written as n, choose n-1?
Yes, it should do. I do run the solutions against the live data, but sometimes tweak the solutions afterwards, so can't always guarantee them :-). I left the comment as 5 choose 4 as it felt clearer in the context of the test data.
It does still feel very alien at times, but I do love being able to think about how to adopt a more arrays-based approach to solving these problems.
#Rust
initially, for part two I was trying to ignore a bad pair not a bad value - read the question!
Only installed Rust on Sunday, day 1 was a mess, today was more controlled. Need to look at some of the rust solutions for std library methods I don't know about.
very focussed on getting it to actually compile/work over making it short or nice!
::: spoiler long! `
pub mod task_2 {
}
` :::
Of course I ended up with a off-by-one error for the second part, so things took a bit longer than they really should've.
But either way, behold, messy C#: ::: spoiler C#
:::
Nim
Got correct answer for part 1 on first try, but website rejected it. Wasted some time debugging and trying different methods. Only to have the same answer accepted minutes later. =(
Codeberg repo
Factor
Quite the interesting language choice. It's so clean. I love it!
It really depends on what your parameter n is. If the only relevant size is the number of records (let's say that is n), then this solution takes time in O(n), because it loops over records only once at a time. This ignores the length of records by considering it constant.
If we also consider the maximum length of records (let's call it m), then your solution, and most others I've seen in this thread, has a time complexity in O(n * m^2) for part 2.
This is my very naive rust solution, part 2 is mostly just an extra function, so they’re bother covered in this one.
AoC day 2
I forgot that this started yesterday, so I'm already behind. I quite like my solution for part one,
but part two will have to waitedit: part 2 was a lot simpler than I thought after a night's sleep.Rust
::: spoiler Tests
:::
Lisp
::: spoiler Part 1
::: ::: spoiler Part 2
:::
Rust
Definitely trickier than yesterday's. I feel like the
windowssolution isn't the best, but it was what came to mind and ended up working for me.Haskell
Had some fun with arrows.
I like the branched pipelines in
isSafe! Very cute.JavaScript
Also wrote a solution in JavaScript to play around with list comprehension. Wrote some utility functions for expressiveness (and lazy evaluation).
::: spoiler Code
:::
https://github.com/sjmulder/aoc/blob/master/2024/js/day02.js
Nim
I got stuck on part 2 trying to check everything inside a single loop, which kept getting more ugly. So then I switched to just deleting one item at a time and re-checking the record.
Reworked it after first finding the solution to compress the code a bit, though the range iterators don't really help with readability.
I did learn about the
sugarimport, which I used to make the sequence duplication more compact:record.dup(delete(it).Cool to see another solution in Nim here =)
That's smart. I haven't thought of using iterators to loop over indexes (except in a
for loop).Yeah I've thought of simple ways to do this and found none. And looking at the input - it's too easy to bruteforce, especially in compiled lang like Nim.
Elixir
Kotlin
A bit late to the party, but here you go.
Uiua
Took me a bit longer to get this one but still quite simple overall.
Spent quite some time on getting to know the
tryandassertoperators better.Run with example input here
G'MIC solution ::: spoiler spoiler
:::
python
::: spoiler solution
:::
R (R-Wasm)
Elixir
this took me so fucking long and in the end i just went for brute force anyway. there are still remnants of some of previous, overly complicated, failed attempts, like the hideous
global removed. In the end, I realized I was fucking up by using remove() instead of pop(), it was causing cases with duplicates where the removal of one would yield a safe result to count as unsafe.Kotlin:
The Report#isSafe method essentially solves both parts.
I've had a bit of a trip up in part 2:
I initially only checked, if the report was safe, if either elements in the pair were to be removed. But in the edge case, that the first pair has different monotonic behaviour than the rest, the issue would only be detected by the second pair with indices (2, 3), whilst removing the first element in the list would yield a safe report.
Rust
Turned out alright, I am looking forward to seeing what 2d coordinate grid code I can cannibalize from last year's solutions 😄
Github link
I think that repo is private
I realized after I posted 😅 thanks for pointing it out! I will go make it public
#Zig
Smalltalk
Discovered a number of frustrations with this supposedly small and elegant language
(nums at: i) - (nums at: i+1)which would benums[i] - nums[i+1]in most languagesPart 1
Part 2