adventofcode 2024-12-22

thankfully the difference happens right at the beginning. let's see

maybe "you can't use blank space" thing

I was thinking it didn't matter and was just to throw you off, but it does matter if you have to operate a dirpad that operates a dirpad, huh

that's definitely it because my paths yield the same code if you simulate it

Day 22: Advent of reading comprehension

Day of off-by-one errors. From previous day to this.

Gonna be honest : I have no idea of how to solve part2 except bruteforce, and even that is not easy to implement. The fact that the sequence might be missing from some prices but not others is messing me up.

https://github.com/erdos/advent-of-code/blob/master/2024/day22.clj runs in 0.1s + 9.5s For part 2, I am building a map of four-consecutive-changes to value for each line. Then I am merging the maps and selecting the key with the largest value.

When writing the secret function I mistyped 54 instead of 65 and of course I multiplied by 2024 instead of 2048 lol.

1

same here with 2024.

He always goes for the year and this tripped me up

Btw @erdos your solution doesn’t work for my input

You take 2000 items from secrets sequence. But the instruction says to look at 2000 price differences, so you should be taking 2001 items

I got totally tripped up by this because I have an input where the correct solution is a 4 number sequence that appears as 2000th diff somewhere 😞

Oh good catch, thank you very much, fixed now. Looks like I got lucky. The (update ... #(or ...)) trick is nice, copied that now.

So my code "kinda" works... But I find a better sequence on the example input FML

[(1 -3 5 1) 24]
[(0 6 -3 -1) 23]
[(-2 1 -1 3) 23]
Let's go for 6 hours of debugging something that is probably an off-by-one error -_-

I did the f*cking 2001 vs 2000 error too 😞

Here's mine. Part2 is slow as all hell (like ~8s). Can't be bothered to do better, though. Really didn't enjoy this one.

Isnt (update ... #(or ...)) just fnil with extra steps?

no, it’s the opposite

Oh, my bad, yeah, makes sense.

I multiplied by 2024 instead of 2048 lol.
@roklenarcic me too, and I spent about 15 minutes to spot the bug 🙈

I checked @erdos's solution on my machine (MacBook Pro 2019) it takes about 15s for part 2. Btw, the same solution in Python takes just about 3-4s. Clojure performance sucks in such days.

I didn’t specifically optimize for speed

but yes, clojure is quite slow in most cases

and if you go for optimized code, it gets really ugly

Optimized mine a bit, I go down to 3.5s with reducers, and the code is still very readable : https://github.com/Maravedis/advent_code/blob/master/src/advent_of_code/2024/22.clj .

👏 2
👏🏻 1

If you have a lot of map operations you can gain a lot of speed by collapsing them

Reducers map do not produce in-between colelctions, they already collapse them. That's one of the good thing.

Unfortunately that’s a big drain on clojure performance, much larger than doing equivalent Stream processing in java

@malaingreclement 4,5s on my machine, seems yours is faster ^_^

btw, [a b c d price] is a nice trick

similar map merge approach, also ~15s here

Hm, reducers? How about transducers?

Never got the hang of them. I find transducers really hard to read. Reducers play more nicely with my mental models. Aren't transducers mono threaded though? They should be slower.

I did this and it still takes 3 sec:

(defn secrets-diff2 [n cnt]
  (loop [[price & more] (rest (iterate next-secret n))
         i cnt
         d1 nil 
         d2 nil 
         d3 nil
         prev-price (first (iterate next-secret n))
         acc (transient {})]
    (if (zero? i)
      (persistent! acc)
      (let [d-price (mod price 10)
            d0 (- d-price prev-price)
            k [d3 d2 d1 d0]
            new-acc (if (contains? acc k) acc (assoc! acc k d-price))]
        (recur more (dec i) d0 d1 d2 d-price new-acc)))))

👍 2

Hm, I tried it and it takes 7s. The reducers approach wins.

@roklenarcic btw, without contains? it is a bit faster.

TIL about iterate 🤩

3

slow but it gets the job done. glad.

👍 1

skipped day 21, but today was surprisingly easy. think Clojure has all the right helpers for this one

can’t mix up 2048 and 2024 if you notice all divisions are shift rights :)

reverse and overwrite. neat

I had 2028 in there for a bit. Here’s todays: https://github.com/bhauman/adv2024/blob/main/src/adv2024/day22/sol.clj The basic strategy was make maps of price-diff-sequence->price and then get all the price-diff-sequence keys and sort them by frequency and then grab the first few keys and total the prices for them and getting the max one. I’m gonna add a transducer to make it a little speedier.

well, transducers gave me nothing

As @malaingreclement showed reducers play well here

What’s the benefit of reducers here compared to transducers?

Multithreading.

I’m getting some love out of pmap so reducers should work great

doh, 16777216 is a power of 2, for bit-and instead of mod.

👍 2

I tried pmap on map that runs for each buyer, but it didn’t have any noticeable effect

For me pmap reduces from 21s to 12s, but with reducers it takes just 4.5s

1

this trick (map (fn [[a b c d price]] [[(- b a) (- c b) (- d c) (- price d)] price])) also matters

yeah thats a big improvement

https://gitlab.com/maximoburrito/advent2024/-/blob/main/src/day22/main.clj I'm still playing catch up. This is dumb and slow but it's good enough for the star. Getting closer.