改进这个clojure代码:深度优先搜索算法

时间:2012-09-26 19:16:06

标签: clojure artificial-intelligence depth-first-search

上下文

作为我自己的运动(我正在学习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)

问题

我真的对如何改进此代码感兴趣。可读性,效率和性能都有。

1 个答案:

答案 0 :(得分:4)

不要使用懒猫,如果你drop-last就行,你的seq就会实现。

Clojure中的递归应该使用loop / recur来完成,以避免堆栈溢出。

不要将多个let放在一行:

(let [first* (pop* stack)
      l      (last first*)]

使用(if-not代替(if (not(not=

也是如此

使用小写var名​​称(graph,而不是Graph)。保持对类,记录和协议的大写。