Forked from piotr-yuxuan/math-and-simple-call-in-core-logic.clj
Created
January 16, 2016 18:21
-
-
Save vdt/fc2fe3213034d548832c to your computer and use it in GitHub Desktop.
Learning try-and-diy: how can I simplify this example?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns firstshot.chessknightmove | |
| (:refer-clojure :exclude [== >= <= > < =]) | |
| (:use clojure.core.logic | |
| clojure.core.logic.arithmetic)) | |
| (defn knight-moves | |
| "Returns the available moves for a knight (on a 8x8 grid) given its current position." | |
| [x y] | |
| (let [xmax 8 ymax 8] | |
| (run* [q] | |
| (fresh [a b] | |
| (conde | |
| [(< (+ x 1) xmax) (< (+ y 2) ymax) (== a (+ x 1)) (== b (+ y 2))] | |
| [(< (+ x 2) xmax) (< (+ y 1) ymax) (== a (+ x 2)) (== b (+ y 1))] | |
| [(< (+ x 2) xmax) (>= (- y 1) 0) (== a (+ x 2)) (== b (- y 1))] | |
| [(< (+ x 1) xmax) (>= (- y 2) 0) (== a (+ x 1)) (== b (- y 2))] | |
| [(>= (- x 1) 0) (>= (- y 2) 0) (== a (- x 1)) (== b (- y 2))] | |
| [(>= (- x 2) 0) (>= (- y 1) 0) (== a (- x 2)) (== b (- y 1))] | |
| [(>= (- x 2) 0) (< (+ y 1) ymax) (== a (- x 2)) (== b (+ y 1))] | |
| [(>= (- x 1) 0) (< (+ y 2) ymax) (== a (- x 1)) (== b (+ y 2))]) | |
| (== q [a b]))))) | |
| ;; This instruction | |
| (knight-moves 4 4) | |
| ;; will give the following result | |
| ([5 6] [6 5] [6 3] [5 2] [3 2] [2 3] [2 5] [3 6]) | |
| ;; Now let's try to go beyond that verbose way. | |
| ;; First, let's define an helper function | |
| (defn distance | |
| [a b] | |
| "Returns the distance between two numbers" | |
| (let [diff (- a b)] | |
| (max diff (- diff)))) | |
| (defn knight-moves-smaller | |
| "Returns the available moves for a knight and aims at cleaning the code." | |
| [x y] | |
| (let [xmax 8 ymax 8] | |
| (run* [q] | |
| (fresh [a b] | |
| (== 3 (+ (distance a x) (distance b y))) | |
| (>= a 0) (< a xmax) | |
| (>= b 0) (< b ymax) | |
| (== q [a b]))))) | |
| ;; But we've got a problem with the arithmetic part then this doesn't work: | |
| (knight-moves-smaller 4 4) | |
| ;; => Unhandled java.lang.ClassCastException, clojure.core.logic.LVar cannot be cast to java.lang.Number | |
| ;; I'm new to core.logic (and Clojure in general) so I'll like to understand how we can do to factorise the previous into something similar to the latter. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment