Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (require '[clojure.set :as set])
- (def dirs {:back (fn [cube [_ _ lowz] _]
- (if (some (partial > lowz) (mapcat #(map (fn [[_ _ z]] z) %) cube))
- [nil nil]
- [(set (map #(set (map (fn [[x y z]] [x y (dec z)]) %)) cube)) :back]))
- :front (fn [cube _ [_ _ highz]]
- (if (some (partial = highz) (mapcat #(map (fn [[_ _ z]] z) %) cube))
- [nil nil]
- [(set (map #(set (map (fn [[x y z]] [x y (inc z)]) %)) cube)) :front]))
- :left (fn [cube [lowx _ _] _]
- (if (some (partial > lowx) (mapcat #(map first %) cube))
- [nil nil]
- [(set (map #(set (map (fn [[x y z]] [(dec x) y z]) %)) cube)) :left]))
- :right (fn [cube _ [highx _ _]]
- (if (some (partial = highx) (mapcat #(map first %) cube))
- [nil nil]
- [(set (map #(set (map (fn [[x y z]] [(inc x) y z]) %)) cube)) :right]))
- :down (fn [cube [_ lowy _] _]
- (if (some (partial > lowy) (mapcat #(map second %) cube))
- [nil nil]
- [(set (map #(set (map (fn [[x y z]] [x (dec y) z]) %)) cube)) :down]))
- :up (fn [cube _ [_ highy _]]
- (if (some (partial = highy) (mapcat #(map second %) cube))
- [nil nil]
- [(set (map #(set (map (fn [[x y z]] [x (inc y) z]) %)) cube)) :up]))})
- (def transforms {:back (vals (dissoc dirs :front))
- :front (vals (dissoc dirs :back))
- :left (vals (dissoc dirs :right))
- :right (vals (dissoc dirs :left))
- :up (vals (dissoc dirs :down))
- :down (vals (dissoc dirs :up))})
- (defn side-gen [[a b]]
- (for [x (range (dec a) (inc a)) y (range (dec b) (inc b))]
- [x y]))
- (defn face-spreader [[x y z]]
- (reduce
- (fn [faces [canon coords transform]]
- (into faces (map #(set (map (partial transform %) (side-gen coords))) [(dec canon) canon])))
- [] [[x [y z] (comp vec cons)] [y [x z] (comp vec interpose)] [z [x y] #(conj %2 %)]]))
- (defn graphic-builder [faces]
- (reduce #(if (contains? %1 %2) (disj %1 %2) (conj %1 %2)) #{} faces))
- (defn get-neighbors [current anticubes visited dir lowest highest]
- (if (nil? current) nil
- (remove (fn [[node _]] (or (nil? node) (visited node) (nil? (anticubes node)))) (map #(% current lowest highest) (transforms dir)))))
- (defn bfs [anticubes lowest highest queue visited]
- (let [[current dir :as curr] (first queue)
- queue (disj queue curr)
- neighbors (get-neighbors current anticubes visited dir lowest highest)]
- (cond
- (nil? current) visited
- (visited current) (recur anticubes lowest highest (into queue neighbors) visited)
- (anticubes current) (recur anticubes lowest highest (into queue neighbors) (conj visited current))
- :else (recur anticubes lowest highest queue visited))))
- (defn create-surface [[lx ly lz :as lowest] [hx hy hz :as highest] anticubes prism]
- (reduce
- (fn [visited [starter dir]]
- (set/union visited (bfs anticubes lowest highest #{[starter dir]} visited)))
- #{}
- (concat
- (for [x (range lx (inc hx)) y (range ly (inc hy)) [z dir] [[lz :front] [hz :back]]] [(set (face-spreader [x y z])) dir])
- (for [x (range lx (inc hx)) z (range lz (inc hz)) [y dir] [[ly :up] [hy :down]]] [(set (face-spreader [x y z])) dir])
- (for [z (range lz (inc hz)) y (range ly (inc hy)) [x dir] [[lx :right] [hx :left]]] [(set (face-spreader [x y z])) dir]))))
- (defn build-prism [[lx ly lz] [hx hy hz]]
- (map face-spreader (for [x (range lx (inc hx)) y (range ly (inc hy)) z (range lz (inc hz))] [x y z])))
- (defn add-floating [lowest highest cubes]
- (let [prism (set (map set (build-prism lowest highest)))
- anticubes (set/difference prism cubes)
- visited (create-surface lowest highest anticubes prism)]
- (set/union cubes (set/difference anticubes visited))))
- (defn get-highest [data]
- [(apply max (map first data)) (apply max (map second data)) (apply max (map #(nth % 2) data))])
- (defn get-lowest [data]
- [(apply min (map first data)) (apply min (map second data)) (apply min (map #(nth % 2) data))])
- (def data
- (->> (slurp "cubes.in")
- clojure.string/split-lines
- flatten
- (map #(clojure.string/split % #","))
- flatten
- (map parse-long)
- (partition 3)))
- (->> data (mapcat face-spreader) graphic-builder count println)
- (->> data
- (map face-spreader)
- (map set)
- set
- (add-floating (get-lowest data) (get-highest data))
- (mapcat seq)
- graphic-builder
- count
- println)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement