├── doc ├── img │ ├── robot-tour-00.png │ ├── robot-tour-01.png │ └── robot-tour-02.png └── robot-tour.md ├── src └── manual │ ├── core.clj │ ├── robot_tour.clj │ └── plot.clj ├── .gitignore ├── test └── manual │ └── core_test.clj ├── project.clj └── README.md /doc/img/robot-tour-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marsmining/manual/master/doc/img/robot-tour-00.png -------------------------------------------------------------------------------- /doc/img/robot-tour-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marsmining/manual/master/doc/img/robot-tour-01.png -------------------------------------------------------------------------------- /doc/img/robot-tour-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marsmining/manual/master/doc/img/robot-tour-02.png -------------------------------------------------------------------------------- /src/manual/core.clj: -------------------------------------------------------------------------------- 1 | (ns manual.core 2 | "Scratch pad" 3 | (:require [clojure.pprint :refer [pprint]])) 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /lib 3 | /classes 4 | /checkouts 5 | pom.xml 6 | pom.xml.asc 7 | *.jar 8 | *.class 9 | .lein-deps-sum 10 | .lein-failures 11 | .lein-plugins 12 | .lein-repl-history 13 | -------------------------------------------------------------------------------- /test/manual/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns manual.core-test 2 | (:require [clojure.test :refer :all] 3 | [manual.core :refer :all])) 4 | 5 | (deftest a-test 6 | (testing "FIXME, I fail." 7 | (is (= 0 1)))) 8 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject manual "0.1.0-SNAPSHOT" 2 | :description "follow algo design manual" 3 | :url "http://ockhamsolutions.de" 4 | :dependencies [[org.clojure/clojure "1.5.1"] 5 | [quil "1.6.0"]]) 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Manual 2 | 3 | ### Summary 4 | 5 | Just a place to stash my answers, in Clojure, while going through problems in [The Algorithm Design Manual](http://www.amazon.com/Algorithm-Design-Manual-Steven-Skiena/dp/1848000693/ref=dp_ob_title_bk). To make it more fun, gonna try out [Processing](http://processing.org) for the first time via the Clojure lib, [Quil](https://github.com/quil/quil), to visualize some problems and solutions. 6 | 7 | ### Problems 8 | 9 | _Chapter 1_ 10 | 11 | [Robot Tour](https://github.com/marsmining/manual/blob/master/doc/robot-tour.md) -------------------------------------------------------------------------------- /doc/robot-tour.md: -------------------------------------------------------------------------------- 1 | ## Manual 2 | 3 | ### Robot Tour 4 | 5 | First we want to plot the points of the problem on a graph. The `manual/plot` namespace does this using Quil, like the examples below: 6 | 7 | 9 | 10 | Then we can plot some sample problem data: 11 | 12 | ```clojure 13 | (def s0 [[ 0 9] [ 2 8] [ 5 6] [ 5 2] 14 | [ 4 0] [ 3 -2] [ 0 -5] [-3 -4] 15 | [-5 -1] [-7 2] [-5 5] [-4 7]]) 16 | ``` 17 | 18 | 20 | 21 | And after using the simple "nearest neighbor" heuristic, starting with the first point in the list: 22 | 23 | 25 | 26 | Tagged repo at this point with [nearest-neighbor](https://github.com/marsmining/manual/blob/nearest-neighbor/src/manual/robot_tour.clj) tag. -------------------------------------------------------------------------------- /src/manual/robot_tour.clj: -------------------------------------------------------------------------------- 1 | (ns manual.robot-tour 2 | "Find shortest tour visiting each point in plane" 3 | (:require [manual.plot :as plot])) 4 | 5 | (defn distance 6 | "Distance between two points" 7 | [a b] 8 | (let [[xa ya] a 9 | [xb yb] b 10 | xd (- xa xb) 11 | yd (- ya yb)] 12 | (Math/sqrt (+ (* xd xd) (* yd yd))))) 13 | 14 | (defn nearest-neighbors 15 | "Given a point, and list of points, find nearest neighbors" 16 | [p ps] 17 | (sort 18 | (map #(vector (distance p %) %2) 19 | ps (range 0 (count ps))))) 20 | 21 | (defn robot-tour 22 | "Create list of points, representing best path" 23 | [[p & ps]] 24 | (when (seq ps) 25 | (let [[_ idx] (first (nearest-neighbors p ps)) 26 | point (nth ps idx)] 27 | (conj (robot-tour ps) point)))) 28 | 29 | ;; sample data 30 | (def s0 [[ 0 9] [ 2 8] [ 5 6] [ 5 2] 31 | [ 4 0] [ 3 -2] [ 0 -5] [-3 -4] 32 | [-5 -1] [-7 2] [-5 5] [-4 7]]) 33 | 34 | (comment 35 | 36 | (plot/start) 37 | 38 | (plot/stop) 39 | 40 | (plot/set-points []) 41 | 42 | (plot/set-points s0) 43 | 44 | (plot/set-lines []) 45 | 46 | (plot/set-lines (conj (robot-tour s0) (first s0))) 47 | 48 | (robot-tour s0) 49 | 50 | ) 51 | 52 | -------------------------------------------------------------------------------- /src/manual/plot.clj: -------------------------------------------------------------------------------- 1 | (ns manual.plot 2 | "Draw a cartesian grid for basic plotting" 3 | (:require [quil.core :as q])) 4 | 5 | (def scr-w 750) 6 | (def scr-h 750) 7 | 8 | ;; we want our plot to always be -10 to +10 9 | (def tick (quot scr-w 20)) 10 | (def tick-len (quot scr-w 50)) 11 | 12 | (def points (atom [])) 13 | (def lines (atom [])) 14 | 15 | (defn set-points [xs] (reset! points xs)) 16 | (defn set-lines [xs] (reset! lines xs)) 17 | 18 | (defn setup [] 19 | (q/smooth) 20 | (q/frame-rate 1) 21 | (q/background 200) 22 | (q/text-font (q/create-font "Helvetica" 20 true))) 23 | 24 | (defn ticks 25 | [type [w h w2 h2] step z] 26 | (if (= type :h) 27 | (do 28 | (doseq [x (range (+ w2 step) w step)] 29 | (q/line [x (- h2 z)] [x (+ h2 z)])) 30 | (doseq [x (range (- w2 step) 0 (* step -1))] 31 | (q/line [x (- h2 z)] [x (+ h2 z)]))) 32 | (do 33 | (doseq [y (range (+ h2 step) h step)] 34 | (q/line [(- w2 z) y] [(+ w2 z) y])) 35 | (doseq [y (range (- h2 step) 0 (* step -1))] 36 | (q/line [(- w2 z) y] [(+ w2 z) y]))))) 37 | 38 | (defn from-cartesian 39 | "Convert cartesian to our custom screen coords" 40 | [x y] 41 | [(* (+ x 10) tick) (* (- 10 y) tick)]) 42 | 43 | (defn plot-point 44 | "Accepts cartesian" 45 | ([x y] 46 | (plot-point x y 10)) 47 | ([x y w] 48 | (let [[x' y'] (from-cartesian x y) 49 | label (str x "," y)] 50 | (q/ellipse x' y' w w) 51 | (q/text label (+ x' w) (+ y' w))))) 52 | 53 | (defn plot-line 54 | "Accepts cartesian" 55 | [a b] 56 | (let [[xa ya] (apply from-cartesian a) 57 | [xb yb] (apply from-cartesian b)] 58 | (q/debug "drawing line..") 59 | (q/line xa ya xb yb))) 60 | 61 | (defn draw-plot [] 62 | (let [w (q/width) 63 | h (q/height) 64 | w2 (quot w 2) 65 | h2 (quot h 2)] 66 | 67 | ;; x/y 68 | (q/line [w2 0] [w2 h]) 69 | (q/line [0 h2] [w h2]) 70 | 71 | (q/stroke-weight 1) 72 | 73 | ;; tick marks 74 | (ticks :h [w h w2 h2] tick tick-len) 75 | (ticks :v [w h w2 h2] tick tick-len))) 76 | 77 | (defn draw [] 78 | 79 | (q/background 200) 80 | (q/stroke 0) 81 | (q/stroke-weight 3) 82 | (q/fill 100) 83 | 84 | (draw-plot) 85 | 86 | (doseq [[x y] @points] 87 | (plot-point x y)) 88 | 89 | (doseq [[a b] (map vector @lines (rest @lines))] 90 | (plot-line a b)) 91 | 92 | ;; (q/save-frame "doc/img/robot-tour-02.png") 93 | ) 94 | 95 | (defn start [] 96 | (q/defsketch graph 97 | :title "simple graph" 98 | :setup setup 99 | :draw draw 100 | :size [scr-w scr-h])) 101 | 102 | (defn stop [] 103 | (q/sketch-close graph)) 104 | --------------------------------------------------------------------------------