Hi all, I'm experimenting with clojure.core: very nice! This is a simple planner for the Farmer Crosses River puzzle:
(def characters [:farmer :goat :wolf :cabbage]) ;;; they all start on the left side of the river (def _starting-state {:farmer :l, :goat :l :wolf :l :cabbage :l}) ;;; they all must cross the river (def _final-state {:farmer :r, :goat :r :wolf :r :cabbage :r}) (defn validstateo "constraints for state s" [s] (fresh [farm goat wolf cabb] (== s {:farmer farm, :goat goat, :wolf wolf, :cabbage cabb}) (conde [(== farm goat)] ; farmer is with goat or... [(!= wolf goat) (!= cabb goat)]))) ; goat/wolf (or goat/ cabbage) not alone (defn initialstateo [s] (== s _starting-state)) (defn finalstateo [s] (== s _final-state)) (defn doactiono [s a ns] ; state action nextstate "action a change state s to state ns" (fresh [farm goat wolf cabb] (== s {:farmer farm, :goat goat, :wolf wolf, :cabbage cabb}) (validstateo ns) ; target state must be valid (conde ;; farmer travels with goat [(== a :bringgoat) (== farm goat) ; they must be on the same side (conde ;; flip side for them [(== farm :l) (== ns {:farmer :r, :goat :r, :wolf wolf, :cabbage cabb})] [(== farm :r) (== ns {:farmer :l, :goat :l, :wolf wolf, :cabbage cabb})])] ;; farmer travels with wolf [(== a :bringwolf) (== farm wolf) (conde [(== farm :l) (== ns {:farmer :r, :goat goat, :wolf :r, :cabbage cabb})] [(== farm :r) (== ns {:farmer :l, :goat goat, :wolf :l, :cabbage cabb})])] ;; farmer travels with cabbage [(== a :bringcabb) (== farm cabb) (conde [(== farm :l) (== ns {:farmer :r, :goat goat, :wolf wolf, :cabbage :r})] [(== farm :r) (== ns {:farmer :l, :goat goat, :wolf wolf, :cabbage :l})])] ;; farmer travels alone [(== a :travalone) (conde [(== farm :l) (== ns {:farmer :r, :goat goat, :wolf wolf, :cabbage cabb})] [(== farm :r) (== ns {:farmer :l, :goat goat, :wolf wolf, :cabbage cabb})])] ))) (defne plano "a plan is a sequence of (action, state) towards the final state" [plan] ([[[?a ?s]]] (finalstateo ?s)) ; last state must be final ([[[?a ?s] . ?r]] (fresh [a2 s2 r2] (conso [a2 s2] r2 ?r) (doactiono ?s a2 s2) (plano ?r)))) (defn print-solution [sol] (let [formatstring (clojure.string/join "" (repeat (inc (count characters)) "%10s"))] (print (format "%10s" "__ACTION__")) (doseq [c characters] (print (format "%10s" c))) (println) (doseq [[a s] sol] (let [row (cons a (map (fn [f] (f s)) characters))] (println (apply (partial format formatstring) row)))))) This can be executed with: (doseq [sol (set (run 1 [q] (fresh [a s] (firsto q [a s]) (initialstateo s) (plano q))))] (print-solution sol)) This is the output: __ACTION__ :farmer :goat :wolf :cabbage _.0 :l :l :l :l :bringgoat :r :r :l :l :travalone :l :r :l :l :bringwolf :r :r :r :l :bringgoat :l :l :r :l :bringcabb :r :l :r :r :travalone :l :l :r :r :bringgoat :r :r :r :r Due to lvar handling, I have problems in writing a more concise version of doactiono: any idea? Moreover, core.logic should be more informative, e.g. if I try to execute: user> (run* [q] (== q (firsto [1 2]))) ; wrong use of firsto and wrong number of args passed to it the only message printed is: ; Evaluation aborted. In any case, thanks to core.logic authors! Ciao -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en