[英]clojure how to stop and output while in a recursive loop
因此,我正在A *搜索一個8難題,它似乎可以工作,但是問題是,一旦找到解決方案,它就會不斷瀏覽優先級圖並輸出所有可能性。 一旦滿足條件,有沒有辦法停止並輸出?
注意 :我感覺像是用一個for循環使dosqqs變得懶惰,並使它們不評估整個過程將是最好的。 有沒有辦法做到這一點?
這是我的代碼:
(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 [])
)
為了進一步說明我昨天的評論,這里是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."))
一種常見的方法是在循環調用的末尾放置一個if
語句。 就像是:
(if-not (finished? move)
(a-star ... ))
PS:一個猥瑣點的格式,一些Clojure的程序員發現它更容易閱讀,如果所有的連續收盤)
的走在同一條線上,雖然這純粹是個人喜好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.