🍷 - 2024 DAY 3 SOLUTIONS -🍷
Day 3: Mull It Over
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
Sorry for the delay posting this one, Ategon seemed to have it covered, so I forgot :D I will do better.
C
Yay parsers! I've gotten quite comfortable writing these with C. Using out pointers arguments for the cursor that are only updated if the match is successful makes for easy bookkeeping.
::: spoiler Code
:::
https://github.com/sjmulder/aoc/blob/master/2024/c/day03.c
Got the code a little shorter:
::: spoiler Code
:::
I started poking at doing a proper lexer/parser, but then I thought about how early in AoC it is and how low the chance is that the second part will require proper parsing.
So therefore; hello regex my old friend, I've come to talk with you again.
::: spoiler C#
:::
I couldn't figure it out in haskell, so I went with bash for the first part
Shell
but this wouldn't rock anymore in the second part, so I had to resort to python for it
Python
Really cool trick. I did a bunch of regex matching that I'm sure I won't remember how it works few weeks from now, this is so much readable
Nice, sometimes a few extra linebreaks can do the trick...
My first insinct was similar, add line breaks to the do and dont modifiers. But I got toa caught up thinking id have to keep track of the added characters, I wound up just abusing split()-
Nim
From a first glance it was obviously a regex problem.
I'm using tinyre here instead of stdlib
relibrary just because I'm more familiar with it.Codeberg repo
I shy away from regexes for these parsing problems because part 2 likes to mess those up but here it worked beautifully. Nice and compact solution!
Haskell
Of course it's point-free
Uiua
Uses experimental feature of
foldto track the running state of do/don't.[edit] Slightly re-written to make it less painful :-) Try it online!
Python
Part1:
Part2:
Haskell
Oof, a parsing problem :/ This is some nasty-ass code.
stepis almost the State monad written out explicitly.::: spoiler Solution
:::
Love to see you chewing through this parsing problem in Haskell, I didn't dare use Parsec because I wasn't confident enough.
Why did you decide to have a strict definition of
Mul !Int !Int?My guess is because a linter and/or HLS was suggesting it. I know HLS used to suggest making your fields strict in almost all cases. In this case I have a hunch that it slightly cuts down on memory usage because we use almost all
Muls either way. So it does not need to keep the string it is parsed from in memory as part of the thunk.But it probably makes a small/negligible difference here.
Yep, HLS suggested it, and I figured since I'm definitely going to be using all of the values (in part one, at least), why not?
Normally I ignore that kind of nitpicky suggestion though.
Go
Part 1, just find the regex groups, parse to int, and done.
::: spoiler Part 1
:::
Part 2, not so simple. Ended up doing some weird hack with a map to check if the multiplication was enabled or not. Also instead of finding regex groups I had to find the indices, and then interpret what those mean... Not very readable code I'm afraid
::: spoiler Part2
:::
I also used Go - my solution for part 1 was essentially identical to yours. I went a different route for part 2 that I think ended up being simpler though.
I just prepended
do()anddon't()to the original regex with a|, that way it captured all 3 in order and I just looped through all the matches once and toggled theisEnabledflag accordingly.Always interesting to see how other people tackle the same problem!
::: spoiler Part 2 Code
:::
Honestly this is soo much better, I'm not proud of my code at all haha. Thanks for sharing, definitely adding that | to my bag of tricks
Kotlin
You can avoid having to escape the backslashes in regexps by using multiline strings:
Rust with nom parser
Decided to give it a go with the nom parser (first time using this crate). Turned out quite nicely. Had some issues with the alt combinator: All alternatives have to return the same type, using a enum to wrap all options did the trick.
I had to check if
dowas reserved since I couldn't remember seeing it in the language, and it's in the reserved for future use section.Uiua
Part 1:
Part 2:
Rust
Didn't do anything crazy here -- ended up using regex like a bunch of other folks.
::: spoiler solution
:::
Solution on my github (Made it public now)
Factor
Raku
github
Python
Given the structure of the input file, we just have to ignore everything between don't() and do(), so remove those from the instructions before processing.
Sub was my first instinct too, but I got a bad answer and saw that my input had unbalanced do/don't.
I did wonder if that might be the case, I must have been lucky with my input.
Rust
Regex made this one pretty straightforward. The second part additionally looks for
do()anddon't()in the same regex, then we do a case distinction on the match.Our part1's are basically identical, but for part 2 I just regex deleted everything between
dont()anddo() `, after sanitizing out the newlines.I guess it would have failed if my test data had a mul after the last dont, but it worked out, so good enough :)
Python
After a bunch of fiddling yesterday and today I finally managed to arrive at a regex-only solution for part 2. That
re.DOTALLis crucial here.Nim
I had a nicer solution in mind for part 2, but for some reason
nredidn't want to work for me, andrecouldn't give me the start/end or all results, so I ended up doing this skip/toggle approach.Also initially I was doing it line by line out of habit from other puzzles, but then ofc the
don't()s didn't propagate to the next line.Kotlin
Just the standard Regex stuff. I found this website to be very helpful to write the patterns. (Very useful in general)
Elixir
First time writing Elixir. It's probably janky af.
I've had some help from AI to get some pointers along the way. I'm not competing in any way, just trying to learn and have fun.
~~Part 2 is currently not working, and I can't figure out why. I'm trying to just remove everything from "don't()" to "do()" and just pass the rest through the working solution for part 1. Should work, right?
Any pointers?~~
edit; working solution:
I think I had the same issue. Consider what happens if there isn't a do() after a don't().
Ah, yes, that's it. The lazy solution would be to add a "do()" to the end of the input, right? Haha
It was actually a line break that broke the regex. Changing from a "." to "[\s\S]" fixed it.
Gleam
Struggled with the second part as I am still very new to this very cool language, but got there after scrolling for some inspiration.
python
::: spoiler solution
:::
Rust
Definitely not my prettiest code ever. It would probably look nicer if I used regex or some parsing library, but I took on the self-imposed challenge of not using third party libraries. Also, this is already further than I made it last year!
Elixir
Julia
I did not try to make my solution concise and kept separate code for part 1 and part 2 with test cases for both to check if I broke anything. But after struggling with Day 2 I am quite pleased to have solved Day 3 with only a little bugfixing.
Lisp
Just did some basic regex stuff.
::: spoiler Part 1 and 2
:::
Rust feat. pest
No Zalgo here! I wasted a huge amount of time by not noticing that the second part's example input was different - my code worked fine but my test failed 🤦♂️
pest.rs is lovely, although part two made my PEG a bit ugly.
Uiua
Regex my beloved <3
Run with example input here
I did part 2 live with the python interactive shell. I deleted all the stuff where I was just exploring ideas.
part 1:
part 2:
Smalltalk
I wrote
matchesActualcause all of smalltalk'sstupidmatchesDo:or whatever don't give you the actual match with captures, only substrings (that wasted a good 40 minutes).Also smalltalk really needs an index operator