Skip to content

Instantly share code, notes, and snippets.

@loganlinn
Last active March 21, 2022 15:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save loganlinn/5437067 to your computer and use it in GitHub Desktop.
Save loganlinn/5437067 to your computer and use it in GitHub Desktop.
Dijkstra's Algorithm in Clojure
(def ^:private inf (Long/MAX_VALUE))
(defn neighbors
"Returns n's neighbors, optionally filtered if unvisited"
([g n] (get g n {}))
([g n uv] (select-keys (neighbors g n) uv)))
(defn update-costs
"Returns costs updated with any shorter paths found to curr's unvisisted
neighbors by using curr's shortest path"
[g costs curr unvisited]
(let [curr-cost (costs curr)]
(reduce
(fn [c [nbr nbr-cost]] (update-in c [nbr] (partial min (+ curr-cost nbr-cost))))
costs
(neighbors g curr unvisited))))
(defn dijkstra
"Returns a mapping of nodes to minimum cost from src using Dijkstra algorithm.
Graph is a mapping of nodes to map of neighboring nodes and associated cost.
Optionally, specify :target node to return only the min price for target"
[g src & {:keys [target]}]
(loop [costs (assoc (zipmap (keys g) (repeat inf)) src 0)
curr src
unvisited (disj (apply hash-set (keys g)) src)]
(if (or (empty? unvisited) (= inf (costs curr)))
costs
(let [costs' (update-costs g costs curr unvisited)
curr' (first (sort-by costs' unvisited))]
(if (= target curr)
(costs' target)
(recur costs'
curr'
(disj unvisited curr')))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment