Advertisement
luorduz

advent-22-18

Dec 27th, 2022
461
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Clojure 4.72 KB | Source Code | 0 0
  1. (require '[clojure.set :as set])
  2.  
  3. (def dirs {:back (fn [cube [_ _ lowz] _]
  4.                    (if (some (partial > lowz) (mapcat #(map (fn [[_ _ z]] z) %) cube))
  5.                      [nil nil]
  6.                      [(set (map #(set (map (fn [[x y z]] [x y (dec z)]) %)) cube)) :back]))
  7.            :front (fn [cube _ [_ _ highz]]
  8.                    (if (some (partial = highz) (mapcat #(map (fn [[_ _ z]] z) %) cube))
  9.                      [nil nil]
  10.                      [(set (map #(set (map (fn [[x y z]] [x y (inc z)]) %)) cube)) :front]))
  11.            :left (fn [cube [lowx _ _] _]
  12.                    (if (some (partial > lowx) (mapcat #(map first %) cube))
  13.                      [nil nil]
  14.                      [(set (map #(set (map (fn [[x y z]] [(dec x) y z]) %)) cube)) :left]))
  15.            :right (fn [cube _ [highx _ _]]
  16.                    (if (some (partial = highx) (mapcat #(map first %) cube))
  17.                      [nil nil]
  18.                      [(set (map #(set (map (fn [[x y z]] [(inc x) y z]) %)) cube)) :right]))
  19.            :down (fn [cube [_ lowy _] _]
  20.                    (if (some (partial > lowy) (mapcat #(map second %) cube))
  21.                      [nil nil]
  22.                      [(set (map #(set (map (fn [[x y z]] [x (dec y) z]) %)) cube)) :down]))
  23.            :up (fn [cube _ [_ highy _]]
  24.                    (if (some (partial = highy) (mapcat #(map second %) cube))
  25.                      [nil nil]
  26.                      [(set (map #(set (map (fn [[x y z]] [x (inc y) z]) %)) cube)) :up]))})
  27.  
  28. (def transforms {:back (vals (dissoc dirs :front))
  29.                  :front (vals (dissoc dirs :back))
  30.                  :left (vals (dissoc dirs :right))
  31.                  :right (vals (dissoc dirs :left))
  32.                  :up (vals (dissoc dirs :down))
  33.                  :down (vals (dissoc dirs :up))})
  34.  
  35. (defn side-gen [[a b]]
  36.   (for [x (range (dec a) (inc a)) y (range (dec b) (inc b))]
  37.     [x y]))
  38.  
  39. (defn face-spreader [[x y z]]
  40.   (reduce
  41.     (fn [faces [canon coords transform]]
  42.       (into faces (map #(set (map (partial transform %) (side-gen coords))) [(dec canon) canon])))
  43.       [] [[x [y z] (comp vec cons)] [y [x z] (comp vec interpose)] [z [x y] #(conj %2 %)]]))
  44.  
  45. (defn graphic-builder [faces]
  46.   (reduce #(if (contains? %1 %2) (disj %1 %2) (conj %1 %2)) #{} faces))
  47.  
  48. (defn get-neighbors [current anticubes visited dir lowest highest]
  49.   (if (nil? current) nil
  50.   (remove  (fn [[node _]] (or (nil? node) (visited node) (nil? (anticubes node)))) (map #(% current lowest highest) (transforms dir)))))
  51.  
  52. (defn bfs [anticubes lowest highest queue visited]
  53.   (let [[current dir :as curr] (first queue)
  54.         queue (disj queue curr)
  55.         neighbors (get-neighbors current anticubes visited dir lowest highest)]
  56.     (cond
  57.       (nil? current) visited
  58.       (visited current) (recur anticubes lowest highest (into queue neighbors) visited)
  59.       (anticubes current) (recur anticubes lowest highest (into queue neighbors) (conj visited current))
  60.       :else (recur anticubes lowest highest queue visited))))
  61.  
  62. (defn create-surface [[lx ly lz :as lowest] [hx hy hz :as highest] anticubes prism]
  63.   (reduce
  64.     (fn [visited [starter dir]]
  65.       (set/union visited (bfs anticubes lowest highest #{[starter dir]} visited)))
  66.     #{}
  67.     (concat
  68.       (for [x (range lx (inc hx)) y (range ly (inc hy)) [z dir] [[lz :front] [hz :back]]] [(set (face-spreader [x y z])) dir])
  69.       (for [x (range lx (inc hx)) z (range lz (inc hz)) [y dir] [[ly :up] [hy :down]]] [(set (face-spreader [x y z])) dir])
  70.       (for [z (range lz (inc hz)) y (range ly (inc hy)) [x dir] [[lx :right] [hx :left]]] [(set (face-spreader [x y z])) dir]))))
  71.  
  72. (defn build-prism [[lx ly lz] [hx hy hz]]
  73.   (map face-spreader (for [x (range lx (inc hx)) y (range ly (inc hy)) z (range lz (inc hz))] [x y z])))
  74.  
  75. (defn add-floating [lowest highest cubes]
  76.   (let [prism (set (map set (build-prism lowest highest)))
  77.         anticubes (set/difference prism cubes)
  78.         visited (create-surface lowest highest anticubes prism)]
  79.     (set/union cubes (set/difference anticubes visited))))
  80.  
  81. (defn get-highest [data]
  82.   [(apply max (map first data)) (apply max (map second data)) (apply max (map #(nth % 2) data))])
  83.  
  84. (defn get-lowest [data]
  85.   [(apply min (map first data)) (apply min (map second data)) (apply min (map #(nth % 2) data))])
  86.  
  87. (def data
  88.   (->> (slurp "cubes.in")
  89.       clojure.string/split-lines
  90.       flatten
  91.       (map #(clojure.string/split % #","))
  92.       flatten
  93.       (map parse-long)
  94.       (partition 3)))
  95.  
  96. (->> data (mapcat face-spreader) graphic-builder count println)
  97. (->> data
  98.      (map face-spreader)
  99.      (map set)
  100.      set
  101.      (add-floating (get-lowest data) (get-highest data))
  102.      (mapcat seq)
  103.      graphic-builder
  104.      count
  105.      println)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement