+(defn a-star
+ "succ :: state -> [state]
+ cost :: cost -> state -> cost
+ heur :: state -> cost
+ init :: state
+ des? :: state -> bool"
+ [succ cost heur init des?]
+ (let [update-openl (fn [ol sn pt cs]
+ (reduce (fn [o p]
+ (assoc o p [(cost cs p) (heur p)]))
+ ol (remove sn (succ pt))))
+ openl (priority-map-by (fn [[ag ah] [bg bh]]
+ (let [cmp (compare (+ ag ah) (+ bg bh))
+ cmp-g (compare ag bg)
+ cmp-h (compare ah bh)]
+ (if-not (zero? cmp)
+ cmp
+ (if-not (zero? cmp-g)
+ cmp-g
+ cmp-h)))))]
+ (loop [openl (assoc openl init [0 (heur init)])
+ seen #{init}]
+ (let [[point [dist _]] (peek openl)]
+ (cond
+ (empty? openl) [nil ##Inf]
+ (des? point) [point dist]
+ :else (let [openl (update-openl (pop openl) seen point dist)
+ seen (apply conj seen (keys openl))]
+ (recur openl seen)))))))
+