Skip to content

Instantly share code, notes, and snippets.

@fogus
Created March 8, 2011 19:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fogus/860878 to your computer and use it in GitHub Desktop.
Save fogus/860878 to your computer and use it in GitHub Desktop.
Run-length encoding a seq
(defn mundane-pack
"Mundane recursive way to pack a sequence"
[[f & r :as S]]
(if (seq S)
(let [[packed tail] (split-with {f true} S)]
(if (seq tail)
(cons packed (mundane-pack tail))
[packed]))
[nil]))
(defn pack
"Tail-recursive way to pack a sequence"
[coll]
(letfn [(pack* [[f & r :as S] acc]
(when (seq S)
(let [[packed tail] (split-with {f true} S)]
(if (seq tail)
(recur tail (conj acc packed))
(conj acc packed)))))]
(pack* coll [])))
(defn rle
"Run-length encode a sequence"
[coll]
(map #(vector (count %) (first %))
(pack coll)))
(def S '[a a a a b c c a a d e e e e])
(pack S)
;=> [(a a a a) (b) (c c) (a a) (d) (e e e e)]
(rle S)
;=> ([4 a] [1 b] [2 c] [2 a] [1 d] [4 e])
@cgrand
Copy link

cgrand commented Mar 9, 2011

Beware of the #{f}, {f true} is more robust. And you are not an if-let and when-let lover isn't it?

@fogus
Copy link
Author

fogus commented Mar 9, 2011

Thanks for the tips. I added the {f true} but am holding off on the *-let for now as the above reads a little clearer to me.

@cgrand
Copy link

cgrand commented Mar 9, 2011

de gustibus non est disputandum
I'm too enamoured with *-let...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment