Awesome
Advent of Code
year | day | summary |
---|---|---|
2015 | 1 | reduuuuuuuce |
2015 | 2 | simple regex, yummy destructuring, map/reduce... fun! |
2015 | 3 | reduce is very versatile! |
2015 | 4 | clojure is plenty fast, eh? |
2015 | 5 | maybe helper functions would be more readable? otherwise, simple enough :) |
2015 | 6 | had some (but not tooooo much) fun optimising, ha |
2015 | 7 | WIP |
2020 | 1 | (just warming up for 2024!) |
2021 | 1 | off to a nice, neat start |
2021 | 2 | sooo much nicer than my first attempt! |
2021 | 3 | not terrible |
2022 | 1 | let's goooooo! |
2022 | 2 | alright: I was a bit distracted :P |
2022 | 3 | neat... but feels like the calm before the storm |
2022 | 4 | ditto |
2022 | 5 | parsing is a little inelegant, but the rest was fine :) |
2022 | 6 | piece of piss |
2022 | 7 | SO IT BEGINS |
2022 | 8 | eh... quite ugly :/ |
2022 | 9 | not too bad! |
2022 | 10 | neat enough! |
2022 | 11 | part 1? fine. part 2? uhhhhh... |
2022 | 12 | a little ugly. but more importantly: slowwwww... |
2022 | 13 | little hard to understand the spec, but got there in the end |
2022 | 14 | easy enough; wordy solution though |
2023 | 1 | overlapping regex, grrrrr... |
2023 | 2 | zero snags; enjoyed making it nice :) |
2023 | 3 | easy peeeeez... once I figured how best to parse things |
2023 | 4 | neat! |
2024 | 1 | I think I'll break from, uh, tradition this year and write marginally more serious summaries! :D</br></br>That said, not much to say about this one. Nice warmup. Hopefully I can keep up the readability, among other things, as we go on — because if I had a goal for AoC 2024 it'd be to produce elegant, readily understandable (especially to Clojure beginners), performant solutions. In roughly that order.</br></br>I know I'm going to miss some days. But at the very least I hope to keep up, then swing back later to fill in any gaps. There's only so much time in December for 'toy problems' anyhow... which as it happens is a happy constraint. I'm very grateful that Clojure isn't just a toy language for me, but a living. Perhaps my rushed solutions here can help others into the same predicament? (repeat "ONE OF US") </br></br>P.S. Do also check out the #adventofcode channel in Clojurians Slack! There will be daily solution threads. I always learn a lot from them. |
2024 | 2 | This one was fun! My initial approach to Part One — based on partitioning each 'report' into pairs, then checking the first pair to determine whether the rest of the report should increase, decrease, or had already failed — didn't seamlessly scale to Part Two, so I had to go back to the drawing board a bit. What I ended up with was one big reduce that first scores each report based on number of increasing pairs, number of decreasing pairs, and number of 'bounded' pairs; checks whether a score is 'safe' (i.e. the bounded total, plus either the increasing or decreasing total, equals the number of pairs); then if it isn't (and a retry? arg is true), runs (lazily) over the possible alternate reports missing one element until either a safe alternate is found, or there are no more alternates to test.</br></br>I had worried about this resulting in needlessly, repeatedly scoring the same pairs, so I memoize d the score-pair function. But this didn't seem to make any measurable difference to performance — plenty fast in either case. Perhaps with much larger 'reports', or a 'tolerance' higher than one bad element, things would get more interesting. :) |
2024 | 3 | Cute! A nice short one this morning. It will be interesting to see if subsequent days expand on it... :D |
2024 | 4 | Enjoyed this one! I was glad to be reminded that clojure.core.matrix exists, after first spending a few minutes fiddling with a rather imperative loop to generate the diagonals for Part One. m/diagonal did just what I wanted.</br></br>As for Part Two, I didn't immediately see a way to re-use my initial (regex over string lines) approach... so I didn't bother. Instead I generated a list of all the three-by-three sub-matrices and simply matched characters. |
2024 | 5 | Proud of myself today. Started down the road towards brute forcing... but stopped before I got too far, and found a neat trick instead! :)</br></br>In short, consider: (1) each 'update' implies its own set of rules; and (2) if one or more of these rules is backwards with regards to the actual rule set, the 'update' is out-of-order.</br></br>That's it!</br></br>As for Part 2, the rule set trivially entails a comparator that can be passed to sort-by . Fun! |
2024 | 7 | Fun problem! Solved it rather quickly, including Part Two as the only difference between them was an extra 'op'... at least, that's quicky in terms of development time! My first Part Two solution took nearly a minute to churn through all the combinations of + , * , and || . So I had to do something about that.</br></br>Naturally, I reached right for clj-async-profiler. Which immediately put the spotlight on (what came to be called) apply-ops-v1 . Swapping a recusive solution for one based on reduce improved performance by ~2x. Then, solve-v2 swapped a keep for a pmap for another ~2x speedup.</br></br>In retrospect—and after seeing how folks in Clojurians Slack approached Day 7!—I was maybe a bit too attached to, well, my brute-forcey solution. And rather than try to eke out little incremental gains... at least one really neat trick was waiting there to be found that would have sped things up by orders of magnitude instead. Oh well. Flame graphs are pretty. :D |
Feedback welcome!