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.