├── 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 |
--------------------------------------------------------------------------------