clojure如何在递归循环中停止和输出

时间:2013-09-24 21:16:29

标签: loops recursion clojure

所以我正在进行A *搜索8拼图,它似乎有效,但问题是一旦找到解决方案,它就会继续通过优先级映射并输出所有可能性。一旦遇到病情,有没有办法停止输出?

注意:我觉得使用for循环使doseqs懒惰并使它们不是eval整个事情是最好的。有没有办法做到这一点?

这是我的代码:

(defn a-star

   ([board history]

     (if (at-end? board) (print-board board)


           (let [options (filter #(possible-move? % board) *moves*)
                move (into (pm/priority-map) (for [move options] [move (global-man-dis (move-tile board move))]))]


              (doseq [pair move :let [next-move (key pair)]] 


                  (print-board (move-tile board next-move))
                  (println)
                  (a-star (move-tile board next-move) next-move (conj history board))

              )
          )
    ))



  ([board prev-move history]

     (if (or (at-end? board) (history-check history board)) (print-board board)


      (let [options (get-queue board (dont-go-back prev-move))
            move (into (pm/priority-map) (for [move options] [move (global-man-dis (move-tile board move))]))]

        (doseq [pair move :let [next-move (key pair)]] 


             (print-board (move-tile board next-move))
             (println)
             (a-star (move-tile board next-move) next-move (conj history board))

         )
       )
     )))



(defn -main [& args]
  (println "insert a list all numbers no spaces or letters")
  (def board (mapv (fn [^Character c] (Character/digit c 10)) (read-line)))
  ;(def testt [0 8 4 7 2 1 3 5 6])
  ;(def testt [1 2 3 5 4 6 8 0 7])
  (a-star board [])
  )

2 个答案:

答案 0 :(得分:2)

为了扩展我昨天的评论,这里是Clojure中完整的通用A *实现。由于你没有在你的a-star函数中包含各种辅助函数,我不知道你是如何将8拼图问题转化为图搜索问题,但你应该能够自己调整以下代码。

(ns a-star.core
  (:require [clojure.data.priority-map :refer [priority-map]]))

(defn pred->path
  "Determine the path to GOAL from the map of predecessors PRED."
  [pred goal]
  (loop [node goal, path ()]
    (if (contains? pred node)
      (recur (pred node) (cons node path))
      (cons node path))))

(defn expand
  [node h [open g pred] succ cost]
  (let [g-succ (+ (g node) cost)]
    (if (and (contains? open succ)
             (>= g-succ (g succ)))
      [open g pred]
      [(assoc open succ (+ g-succ (h succ)))
       (assoc g succ g-succ)
       (assoc pred succ node)])))

(defn a*
  "Determine the shortest path from START to GOAL in graph GRAPH
with heuristic cost function H. GRAPH format is {from {to cost}}."
  [start goal graph h]
  (loop [open (priority-map start 0)
         closed ()
         g {start 0}
         pred {}]
    (if (empty? open)
      :no-path-found
      (let [node (key (peek open))]
        (if (= node goal)
          [:path-found (pred->path pred goal) (g goal)]
          (let [successors (apply dissoc (graph node) closed)
                [open* g* pred*] (reduce-kv (partial expand node h)
                                            [(pop open) g pred]
                                            successors)]
            (recur open* (conj closed node) g* pred*)))))))

测试代码应阐明如何使用a*函数:

(ns a-star.core-test
  (:require [clojure.test :refer :all]
            [a-star.core :refer :all]))

(deftest test-a*
  (is (= (a* :sb :wb
             {:sb {:kl 70, :kr 145}
              :kl {:ff 103, :lh 53}
              :ff {:wb 116}
              :lh {:wb 183}
              :kr {:hb 84}
              :hb {:wb 102}}
             {:sb 222, :kl 158, :ff 96, :wb 0, :lh 108, :kr 140, :hb 87})
         [:path-found '(:sb :kl :ff :wb) 289])
      "Find path in a directed graph.")
  (is (= (a* :sb :wb
             {:sb {:kl 70, :kr 145}
              :kl {:sb 70, :ff 103, :lh 53}
              :ff {:kl 103, :wb 116}
              :lh {:kl 53, :wb 183}
              :kr {:sb 145, :hb 84}
              :hb {:kr 84, :wb 102}
              :wb {:ff 116, :lh 183, :hb 102}}
             {:sb 222, :kl 158, :ff 96, :wb 0, :lh 108, :kr 140, :hb 87})
         [:path-found '(:sb :kl :ff :wb) 289])
      "Find path in an undirected graph.")
  (is (= (a* :sb :wb
             {:kl {:sb 70}
              :ff {:kl 103}
              :lh {:kl 53}
              :kr {:sb 145}
              :hb {:kr 84}
              :wb {:ff 116, :lh 183, :hb 102}}
             {:sb 222, :kl 158, :ff 96, :wb 0, :lh 108, :kr 140, :hb 87})
         :no-path-found)
      "Find no path in reversed directed graph."))

答案 1 :(得分:1)

一种常见的方法是在最后的递归调用周围添加if语句。类似的东西:

(if-not (finished? move)
   (a-star ... ))

ps:一个无关紧要的格式化点,如果所有连续的结束)都在同一条线上,一些clojure程序员会发现它更容易阅读,尽管这纯粹是个人品味。