Advertisement
luorduz

advent-22-12

Dec 14th, 2022
471
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Clojure 2.30 KB | Source Code | 0 0
  1. (require 'clojure.set)
  2.  
  3. (defn get-node [grid coords & [data]]
  4.   (let [node (get-in grid coords)] (get node data node)))
  5.  
  6. (defn get-neighbors [[x y :as current] unvisited grid]
  7.   (->> [[x (inc y)] [x (dec y)] [(dec x) y] [(inc x) y]]
  8.     (filter #(get-in grid %))
  9.     (filter #(<= (- (get-node grid % "val") (get-node grid current "val")) 1))
  10.     (filter unvisited)
  11. ))
  12.  
  13. (defn update-neighbors [grid distance neighbors]
  14.   (reduce
  15.     #(if (<= (get-node grid %2 "dis") distance) %1 (assoc-in %1 (conj %2 "dis") (+ 1 distance)))
  16.     grid neighbors))
  17.  
  18. (defn get-next [neighbors grid end]
  19.   (->> neighbors
  20.     (sort-by #(get-node grid % "dis"))
  21.     first
  22. ))
  23.  
  24. (defn ohai-Dijkstra [current unvisited queue grid end & [start]]
  25.   (let [grid (if (nil? start) grid (assoc-in grid (conj current "dis") 0))]
  26.   (if
  27.     (= current end) (get-node grid current "dis")
  28.     (let [neighbors (get-neighbors current unvisited grid)
  29.           queue (clojure.set/union queue (set neighbors))
  30.           grid (update-neighbors grid (get-node grid current "dis") neighbors)]
  31.       (if
  32.         (empty? queue) nil
  33.         (let [node (get-next queue grid end)]
  34.           (recur node (disj unvisited current) (disj queue node) grid end nil)))))))
  35.  
  36. (defn prepare-input [grid] (let [width (count (first grid))]
  37.   (->> grid
  38.     flatten
  39.     (map-indexed vector)
  40.     (reduce
  41.       (fn [[nodes start end unvisited] [pos altitude]]
  42.         (let
  43.           [
  44.            s (= altitude \S)
  45.            e (= altitude \E)
  46.            alt (cond s (int \a) e (int \z) :else (int altitude))
  47.            pos [(quot pos width) (mod pos width)]
  48.            item {"val" alt "pos" pos "dis" (+ 1 (* width (count nodes)))}
  49.           ] [
  50.              (assoc-in nodes pos item)
  51.              (or start (when s pos))
  52.              (or end (when e pos))
  53.              (conj unvisited pos)
  54.           ]))
  55.       [grid nil nil #{} []])
  56. )))
  57.  
  58. (with-open [rdr (clojure.java.io/reader "heights.in")]
  59.   (let [
  60.     grid (->> rdr line-seq (map vec) vec)
  61.     [grid start end unvisited lowest] (prepare-input grid)
  62.     lowest (->> grid flatten (filter #(= (% "val") 97)) (map #(% "pos")))
  63.   ]
  64.     (println (ohai-Dijkstra start unvisited #{} grid end true))
  65.     (println (->> lowest (map #(ohai-Dijkstra % unvisited #{} grid end true)) (filter some?) (apply min)))
  66. ))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement