Here’s a my implementation that I thought was decent enough to share :)
Normally, the algorithm finds the shortest path to all other nodes in graph, but
you can optionally pass a specific destination node. The algorithm will exit early
once destination has been visited.
(def ^:privateinfDouble/POSITIVE_INFINITY)(defn update-costs"Returns costs updated with any shorter paths found to curr's unvisisted neighbors by using curr's shortest path"[gcostsunvisitedcurr](let [curr-cost(get costscurr)](reduce-kv(fn [cnbrnbr-cost](if (unvisitednbr)(update-inc[nbr]min (+ curr-costnbr-cost))c))costs(get gcurr))))(defn dijkstra"Returns a map of nodes to minimum cost from src using Dijkstra algorithm. Graph is a map of nodes to map of neighboring nodes and associated cost. Optionally, specify destination node to return once cost is known"([gsrc](dijkstragsrcnil))([gsrcdst](loop [costs(assoc (zipmap (keys g)(repeat inf))src0)currsrcunvisited(disj (apply hash-set (keys g))src)](cond(= currdst)(select-keys costs[dst])(or (empty?unvisited)(= inf(get costscurr)))costs:else(let [next-costs(update-costsgcostsunvisitedcurr)next-node(apply min-key next-costsunvisited)](recurnext-costsnext-node(disj unvisitednext-node)))))))