Fork me on GitHub
#adventofcode
<
2023-12-14
>
bhauman05:12:02

The day 12 thread is borked for me. Anyone else?

pez07:12:23

Borked how? It seems to work for me…

bhauman14:12:12

I can’t reply to the thread… tried restarting app. Maybe there is a cache thats fouling things up

pez14:12:48

I could reply.

bhauman17:12:04

well I got some debuggin to do

rjray06:12:08

Day 14 Part 2 is bonkers 😳.

🧵 2
erdos08:12:42

Solution: https://github.com/erdos/advent-of-code/blob/master/2023/day14.clj My approach is quite slow due to transposing the data back an forth all the time, so there is a lot to improve. The trick with part 2 is that the spin cycle becomes periodical after a while, so we just have to find that point as well as the length of periodicity.

👍 1
alekszelark08:12:26

I remember Tetris (Day 17: Pyroclastic Flow) last year — the same trick https://adventofcode.com/2022/day/17

Arno Jacobs10:12:34

Think of analog clocks. 😉

genmeblog11:12:08

@UEF091BP0 could you mark this thread as a solution thread?

Piotr Kaznowski14:12:46

For the p.2 I assumed there will be some frequency finding in the cycles, so I didn't bother with the code and found it pretty quickly with some printing and pencil. Both solutions go in ~0.8 sec together 😛 https://github.com/caseneuve/aoc2023/blob/master/day14/solution.clj

👏 2
gabor.veres17:12:19

A fast one, 3-5 ms for part 2 on the real input (Edited: sorry, flawed measurement) https://github.com/gveres/advent-of-code-2023-clojure/blob/main/src/day14.clj I'm pretty proud of the "line-tilt" ;

(defn tilt-left [line]
  (->> line
       (partition-by #(= % \#))
       (mapcat (comp reverse sort))
       (apply str)))

👏 3
1
bhauman17:12:55

@U4XJNL67P very very similar!

bhauman17:12:21

except yours is fast

gabor.veres18:12:36

@U064J0EFR, yes it is very similar, cool, except your tilt is even more elegant 👍

Piotr Kaznowski19:12:52

I really like tilt with partition-by, but, interestingly, it makes my code run twice as long in comparison to my not so elegant loop (cc @U064J0EFR, @U4XJNL67P) Also @U4XJNL67P, I tried your solution on my machine, but can't go under 3 sec with it.

rjray19:12:24

https://github.com/rjray/advent-2023-clojure/blob/master/src/advent_of_code/day14.clj When I first wrote part 1, I tried to anticipate what part 2 would be. I was wrong, and to add insult to injury my part 1 took 20s to run. So I slept on it, and this morning I rewrote part 1, getting it to run in about 43ms. Part 2, once I had time to think about it, is a familiar pattern (there's usually one of these every year).

gabor.veres19:12:53

@UUAKPEMJ9, sounds weird, but thanks for reporting, I'll check again

gabor.veres20:12:32

@UUAKPEMJ9, my mistake - I accidentally measured with a pre-warmed memoized function in the REPL. I stand corrected - mea culpa.

Piotr Kaznowski20:12:06

Cool, just started to worry there's something wrong with my machine!

1
Ivana03:12:41

Nice task! 830 ms for whole part 2 (150 rotation cycles in my case), after replacing immutable strings processing by mutable char-array with aget & aset by indexes

(let [ca (char-array input)
      cols (str/index-of input \newline)
      rows (quot (count input) cols)
      lis (mapv (fn [r] (mapv #(+ % (* (inc cols) r)) (range cols))) (range rows))
      ris (mapv (comp vec reverse) lis)
      tis (mapv (fn [c] (mapv #(+ (* % (inc cols)) c) (range rows))) (range cols))
      bis (mapv (comp vec reverse) tis)
      swaps (fn [i j] (let [t (aget ca i)] (aset ca i (aget ca j)) (aset ca j t)))
      process-line (fn [xs] (reduce (fn [iis i]
                                      (let [c (aget ca i)]
                                        (case c
                                          \O (if (empty? iis)
                                               iis
                                               (do (swaps (first iis) i)
                                                   (conj (subvec iis 1) i)))
                                          \# []
                                          (conj iis i))))
                                    [] xs))
      move (fn [dir] (doseq [d dir] (process-line d)))
      rotate (fn [] (move tis) (move lis) (move bis) (move ris))]
  (doseq [_ (range 150)] (rotate))
  (north-support (String. ca)))

wevrem04:12:02

My https://github.com/wevre/advent-of-code/blob/master/src/advent_of_code/2023/day_14_v2.clj. I loaded the \O and \# into a locmap (keyed by [r c]) and then for the cycles I did a rotation transformation on the keys of the locmap. I had a few spare moments in between meetings and rewrote my split-grouped-lines and locmap<- utility functions https://github.com/wevre/advent-of-code/blob/master/src/advent_of_code/common2.clj. I’m quite pleased with those.

Bastian09:12:34

To practice I wrote a stateful transducer to tilt one line. cut my time in half for part 2, but did not optimize the rest, so still 10sec total...

(def tilt-transducer
  "transforms a line into sequences of the form OOO....#  by remembering round rocks and dots until # is read (or end of line)"
  (fn [rf]
    (let [dots (volatile! 0)
          rounds (volatile! 0)]
      (fn ([] (rf))
        ([result] (let [tmp (concat (repeat @rounds \O) (repeat @dots \.))
                        result (if (empty? tmp)
                                 result
                                 (unreduced (rf result tmp)))]
                    (vreset! dots 0)
                    (vreset! rounds 0)
                    (rf result)))
        ([result input]
         (condp = input
           \. (do (vswap! dots inc) result)
           \O (do (vswap! rounds inc) result)
           \# (let [out (concat (repeat @rounds \O) (repeat @dots \.) '(\#))]
                (vreset! dots 0)
                (vreset! rounds 0)
                (rf result out))
           result))))))

(transduce tilt-transducer concat '(\# \. \O \O \. \O \# \. \O)) 
;=> (\# \O \O \O \. \. \# \O \.)

1
alpox12:12:56

~1.8s without trying to optimize. Not the best.

alekszelark23:12:55

Updated my solution with some optimizations. It is still Clojure without fancy things and mutations, now it takes 730 msecs. https://github.com/zelark/AoC/blob/master/src/zelark/aoc_2023/day_14.clj For tilt came up with this code

(defn tilt-part [^String part dir]
  (if (str/blank? part)
    part
    (let [rocks (.repeat "O" (aoc/cnt part \O))
          space (.repeat "." (aoc/cnt part \.))]
      (case dir
        :left  (str rocks space)
        :right (str space rocks)))))

(defn tilt-row [^String row dir]
  (->> (str/split row #"#" -1)
       (map #(tilt-part % dir))
       (str/join "#")))

(defn tilt [platform dir]
  (mapv #(tilt-row % dir) platform))
TIL about string.repeat . It’s there since JDK 11. One more interesting thing — str/split can accept 3rd argument — limit. If the limit is negative then the pattern will be applied as many times as possible and the array can have any length