Skip to content

Instantly share code, notes, and snippets.

@nxtk
Last active January 9, 2020 07:45
Show Gist options
  • Save nxtk/c4ea2267c3e865bcbe3d1e32371a38c1 to your computer and use it in GitHub Desktop.
Save nxtk/c4ea2267c3e865bcbe3d1e32371a38c1 to your computer and use it in GitHub Desktop.
(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