Files
pylisp/examples/knight.clj
T

80 lines
2.6 KiB
Clojure

(def n 5)
(def m 4)
(def start-position '(1 1))
;; path - '((1 1) (4 2) (0 0))
(def knight-moves '((2 1) (2 -1) (-2 1) (-2 -1) (1 2) (1 -2) (-1 2) (-1 -2)))
(defn check-pos? (p) (and (<= 1 (car p) n) (<= 1 (car (cdr p)) m)))
(def all-cells
(concat (map (lambda (r)
(map (lambda (c)
(list r c))
(range 1 (+ 1 m))))
(range 1 (+ 1 n)))))
(def all-moves (concat (map (lambda (cell)
(filter (lambda (step) (check-pos? (car step)))
(map (lambda (delta-move) (list (zip-with + cell delta-move) cell))
knight-moves)))
all-cells)))
(defn steps-set-gen ()
(eval (cons do (map (lambda (step) (list def (symbol (++ step)) false)) all-moves)))
(defn add (x) (eval (list set! (symbol (++ x)) true)))
(defn has? (x) (eval (symbol (++ x))))
(defn remove (x) (eval (list set! (symbol (++ x)) false)))
(lambda (cmd) (eval cmd))
)
(def steps-set (steps-set-gen))
(defn check-step? (step path) (not ((steps-set 'has?) step)))
(defmacro -= (x v) (set! x (- x v)))
(defmacro += (x v) (set! x (+ x v)))
(defn cells-multiset-gen ()
(eval (cons do (map (lambda (cell) (list def (symbol (++ cell)) 0)) all-cells)))
(def distinct 0)
(defn add (x) (do
(def name (symbol (++ x)))
(when (= (eval name) 0) (+= distinct 1))
(eval (list += name 1))))
(defn remove (x) (do
(def name (symbol (++ x)))
(when (= (eval name) 1) (-= distinct 1))
(eval (list -= name 1))))
;; (defn distinct () xxx)
(lambda (cmd) (eval cmd))
)
(def cells-multiset (cells-multiset-gen))
(defn dfs (path)
;; (def current-position (car path))
;; (print path)
(if (and (= (car path) start-position) (= (cells-multiset 'distinct) (* n m)))
path
(reduce (lambda (acc, x)
(if (!= acc false) acc
(do
(def new-pos (zip-with + x (car path)))
(def step (list new-pos (car path)))
(if (and (check-pos? new-pos) (check-step? step path))
(do ((steps-set 'add) step)
((cells-multiset 'add) new-pos)
(def res (dfs (cons new-pos path)))
((steps-set 'remove) step)
((cells-multiset 'remove) new-pos)
res
)
false))))
false knight-moves))
)