Advertisement
luorduz

advent-22-17

Dec 26th, 2022
512
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Clojure 3.10 KB | Source Code | 0 0
  1. (def rocks (cycle
  2.   [[[1 1] [1 2] [1 3] [1 4]]
  3.    [[2 1] [1 2] [2 2] [3 2] [2 3]]
  4.    [[1 1] [1 2] [1 3] [2 3] [3 3]]
  5.    [[1 1] [2 1] [3 1] [4 1]]
  6.    [[1 1] [1 2] [2 2] [2 1]]]))
  7.  
  8.  
  9. (defn build-state [grid]
  10.   (for [potential (range 1 8)]
  11.     (as-> (iterate dec (:h grid)) y
  12.       (filter #(or (some? (get-in grid [% potential] nil)) (zero? %)) y)
  13.       (first y)
  14.       [(- y (:h grid)) potential])))
  15.  
  16. (defn place-rock [grid coords]
  17.   (as-> grid g
  18.     (reduce (fn [res [y x :as coord]] (-> res (assoc-in coord true) (update-in [:h] max y))) g coords)))
  19.  
  20. (defn move [grid rock dir]
  21.   (let [transforms (repeat (count rock) (case dir "d" [dec identity] "<" [identity dec] ">" [identity inc]))
  22.         coords (vec (map (fn [[y x] [yt xt]] [(yt y) (xt x)]) rock transforms))]
  23.     (cond
  24.      (and
  25.        (every? pos? (flatten coords))
  26.        (every? #(< % 8) (map second coords))
  27.        (not-any? true? (map #(get-in grid %) coords)))
  28.       [grid coords]
  29.      (not= "d" dir)
  30.       [grid rock]
  31.      :else
  32.       [(place-rock grid rock) nil])))
  33.  
  34. (defn gen-rock [highest rock]
  35.   (vec (map (fn [[y x]] [(+ highest 3 y) (+ 2 x)]) rock)))
  36.  
  37. (defn simulate [blasts stop & [rock blast state]]
  38.   (loop
  39.     [grid (merge {:h (apply max 0 (keys state)) :state {}} state)
  40.      rocks (nthrest rocks (or rock 0))
  41.      rock (gen-rock (:h grid) (first rocks))
  42.      fallen 0
  43.      dirs (nthrest (interpose "d" (cycle blasts)) (or blast 0))
  44.      iterations (or blast 0)]
  45.     (let [[grid rock] (move grid rock (first dirs))]
  46.       (cond
  47.         (= fallen stop) [(:h grid) nil]
  48.         (some? rock) (recur grid rocks rock fallen (rest dirs) (inc iterations))
  49.         :else (let [state (build-state grid)]
  50.           (if (zero? (mod (- iterations (get-in grid [:state state 2] (- iterations 1))) (count blasts)))
  51.             [state iterations [(:h grid) (inc fallen)] ((:state grid) state)]
  52.             (recur
  53.               (update-in grid [:state] assoc state [(:h grid) (inc fallen) iterations])
  54.               (rest rocks)
  55.               (gen-rock (:h grid) (second rocks))
  56.               (inc fallen)
  57.               (rest dirs)
  58.               (inc iterations))))))))
  59.  
  60. (defn build-wall [blasts stop]
  61.   (as-> (simulate blasts stop) data
  62.     (if (nil? (second data)) data
  63.       (let [[state blast [last-highest last-fallen] [old-highest old-fallen _]] data]
  64.         (def iterable-stop (- stop last-fallen))
  65.         (def iterations (quot iterable-stop (- last-fallen old-fallen)))
  66.         (def new-highest (+ last-highest (* iterations (- last-highest old-highest))))
  67.         (def new-fallen (+ last-fallen (* iterations (- last-fallen old-fallen))))
  68.         (def lowest (apply min (map first state)))
  69.         (def new-grid (reduce (fn [res [y x]] (assoc-in res [(- y lowest) x] true)) {} state))
  70.         (def remaining (simulate blasts (- stop new-fallen) (mod new-fallen 5) (inc blast) new-grid))
  71.         (+ new-highest (first remaining) lowest)))))
  72.  
  73. (def data
  74.   (-> (slurp "rocks.test")
  75.       (clojure.string/replace "\n" "")
  76.       (clojure.string/split #"")))
  77.  
  78. (println (build-wall data 2022))
  79.  
  80. (println (build-wall data 1000000000000))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement