-
-
Save nxtk/c4ea2267c3e865bcbe3d1e32371a38c1 to your computer and use it in GitHub Desktop.
This file contains 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
(defn- legal-move? | |
[from to] | |
(or (empty? to) | |
(and (not (empty? from)) | |
(< (peek from) (peek to))))) | |
(comment (defn- move | |
[{:keys [src dst aux odd-n? idx] :as state}] | |
(let [mod-n (condp = (mod (inc idx) 3) ;; move cw/ccw? | |
1 (if odd-n? 1 2) | |
2 (if odd-n? 2 1) | |
0) | |
new-state (condp = mod-n | |
1 (if (legal-move? src dst) | |
(-> state | |
(update :dst conj (peek src)) | |
(update :src pop)) | |
(-> state | |
(update :src conj (peek dst)) | |
(update :dst pop))) | |
2 (if (legal-move? src aux) | |
(-> state | |
(update :aux conj (peek src)) | |
(update :src pop)) | |
(-> state | |
(update :src conj (peek aux)) | |
(update :aux pop))) | |
0 (if (legal-move? aux dst) | |
(-> state | |
(update :dst conj (peek aux)) | |
(update :aux pop)) | |
(-> state | |
(update :aux conj (peek dst)) | |
(update :dst pop))))] | |
(update new-state :idx inc)))) | |
(defn- move | |
[{:keys [odd-n? idx] :as state}] | |
(let [reverse-illegal (fn [direction] | |
(if (apply legal-move? | |
(map state direction)) | |
direction | |
(reverse direction))) | |
[from to] (condp = (mod (inc idx) 3) ;; move cw/ccw? | |
1 (reverse-illegal (if odd-n? [:src :dst] [:src :aux])) | |
2 (reverse-illegal (if odd-n? [:src :aux] [:src :dst])) | |
0 (reverse-illegal [:aux :dst]))] | |
(-> state | |
(update to conj (peek (get state from))) | |
(update from pop) | |
(update :idx inc)))) | |
(defn hanoi-tower | |
[n] | |
(let [src (vec (reverse (range 1 (inc n)))) | |
init-state {:src src :dst [] :aux [] :odd-n? (odd? n) :idx 0} | |
total-steps (int (Math/pow 2 n))] | |
(take total-steps (iterate move init-state)))) | |
(defn hanoi-tower-print | |
[s] | |
(let [column-length (+ 2 (* 2 (count (:src (first s))))) | |
pattern (format "%1$s %1$s %1$s" (str "%-" column-length "s"))] | |
(doseq [{:keys [src dst aux]} s] | |
(println (format pattern src dst aux))))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment