作为我自己的运动(我正在学习clojure)。我想实现Depth-first search
算法。
使用递归
(def graph
{:s {:a 3 :d 4}
:a {:s 3 :d 5 :b 4}
:b {:a 4 :e 5 :c 4}
:c {:b 4}
:d {:s 4 :a 5 :e 2}
:e {:d 2 :b 5 :f 4}
:f {:e 4 :g 1}})
(def stack [[:s]])
(def goal :g)
(defn cost [Graph start goal]
(goal (start Graph)))
(defn hasloop? [path]
(not (= (count path) (count (set path)))))
(defn atgoal? [path]
(= goal (last path)))
(defn solved? [stack]
(some true? (map atgoal? stack)))
(defn addtopath [path node]
(conj path node))
(defn pop* [stack]
(last stack))
(defn findpath [stack]
(if (not (solved? stack))
(let [first* (pop* stack) l (last first*) ]
(findpath (drop-last
(remove hasloop? (lazy-cat
(map #(addtopath first* %)
(keys (l graph))) stack)))))
[(first stack)]))
如何使用
(findpath stack)
我真的对如何改进此代码感兴趣。可读性,效率和性能都有。
答案 0 :(得分:4)
不要使用懒猫,如果你drop-last
就行,你的seq就会实现。
Clojure中的递归应该使用loop
/ recur
来完成,以避免堆栈溢出。
不要将多个let
放在一行:
(let [first* (pop* stack)
l (last first*)]
使用(if-not
代替(if (not
。 (not=
使用小写var名称(graph
,而不是Graph
)。保持对类,记录和协议的大写。