Skip to content

Instantly share code, notes, and snippets.

@dela3499
Last active August 29, 2015 14:17
Show Gist options
  • Save dela3499/a519ff15a90abc2c5ee1 to your computer and use it in GitHub Desktop.
Save dela3499/a519ff15a90abc2c5ee1 to your computer and use it in GitHub Desktop.
Symmetrizing hobbit body parts (refactored)
(def asym-hobbit-body-parts [{:name "head" :size 3}
{:name "left-eye" :size 1}
{:name "left-ear" :size 1}
{:name "mouth" :size 1}
{:name "nose" :size 1}
{:name "neck" :size 2}
{:name "left-shoulder" :size 3}
{:name "left-upper-arm" :size 3}
{:name "chest" :size 10}
{:name "back" :size 10}
{:name "left-forearm" :size 3}
{:name "abdomen" :size 6}
{:name "left-kidney" :size 1}
{:name "left-hand" :size 2}
{:name "left-knee" :size 2}
{:name "left-thigh" :size 4}
{:name "left-lower-leg" :size 3}
{:name "left-achilles" :size 1}
{:name "left-foot" :size 2}])
(defn needs-matching-part?
[part]
(re-find #"^left-" (:name part)))
(defn make-matching-part
[part]
{:name (clojure.string/replace (:name part) #"^left-" "right-")
:size (:size part)})
(defn symmetrize-body-parts
"Expects a seq of maps which have a :name and :size"
[asym-body-parts]
(loop [remaining-asym-parts asym-body-parts
final-body-parts []]
(if (empty? remaining-asym-parts)
final-body-parts
(let [[part & remaining] remaining-asym-parts
final-body-parts (conj final-body-parts part)]
(if (needs-matching-part? part)
(recur remaining (conj final-body-parts (make-matching-part part)))
(recur remaining final-body-parts))))))
(defn better-symmetrize-body-parts
"Expects a seq of maps which have a :name and :size"
[asym-body-parts]
(reduce (fn [final-body-parts part]
(let [final-body-parts (conj final-body-parts part)]
(if (needs-matching-part? part)
(conj final-body-parts (make-matching-part part))
final-body-parts)))
[]
asym-body-parts))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This is my version of the symmetrize function.
; It uses mapcat and the thread-last macro rather than loop, recur, or reduce.
(defn my-symmetrize-body-parts
"Expects a seq of maps which have a :name and :size"
[asym-body-parts]
(->> asym-body-parts
(mapcat (fn [part] (if (needs-matching-part? part)
[(make-matching-part part) part]
[part])))))
; Each function's results are equivalent, though mine is differently-ordered (hence the 'set' operation).
(println
(apply =
(->> asym-hobbit-body-parts
((juxt symmetrize-body-parts
better-symmetrize-body-parts
my-symmetrize-body-parts))
(map set))))
;;; true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment