So thanks to two great comments (Jake McCrary on let/loop and Zac on the & symbol), I’ve been refactoring my solutions a little. I’m only going to update my previous posts with my first revelation on the loop, as I figure the bad example of what I was doing before probably outweighs being able to see how I’m learning clojure.
So anyway, once I grokked the (loop [] expr) syntax, things became worlds easier. I don’t know if it’s because I’m getting used to clojure, or just the idea of functional programming.
; P11 (*) Modified run-length encoding.
(comment "Modify the result of problem P10 in such a way that if an element has no duplicates it is simply copied into the result list. Only elements with duplicates are transferred as (N, E) terms.")
(defn encodeModified [l]
(map
(fn [a] (if (= (first a) 1) (last a) a))
(encode l)))
; P12 (**) Decode a run-length encoded list.
(comment "Given a run-length code list generated as specified in problem P10, construct its uncompressed version.")
(defn decode [l]
(mapcat (fn [a]
(let [n (first a)
value (last a)]
(loop [curr 0
output '()]
(if
(= curr n)
output
(recur (inc curr) (cons value output)))))) l))
; P13 (**) Run-length encoding of a list (direct solution).
(comment "Implement the so-called run-length encoding data compression method directly."
(comment "I.e. don't use other methods you've written (like P09's pack); do all the work directly.")
(defn encodeDirect [l]
(loop [output '()
[head & tail] l
last-seen nil
n 0]
(if (nil? head)
(reverse output)
(if (= last-seen head)
(recur output tail last-seen (inc n))
(recur (if (nil? last-seen) output (cons (list n last-seen) output)) tail head 1)))))
; P14 (*) Duplicate the elements of a list.
(defn duplicate [l] (mapcat (fn [a] (list a a)) l))
Now that I think things are relatively under control, I’m steaming along nicely into what I think is the end of my “beginner” stage in clojure.
