Last active
October 12, 2015 10:38
-
-
Save ssboisen/4014313 to your computer and use it in GitHub Desktop.
Hoffman encoding in Clojure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn branch? [node] | |
(= (:type node) :branch)) | |
(defn get-chars [node] | |
(if (branch? node) | |
(:chars node) | |
[(:char node)])) | |
(defn leaf [char weight] | |
{:char char :weight weight :type :leaf}) | |
(defn branch [left right] | |
{:left left :right right | |
:chars (sort (into (get-chars left) (get-chars right))) | |
:weight (+ (:weight left) (:weight right)) | |
:type :branch}) | |
(defn create-code-tree [text] | |
(letfn [(combine-trees [trees] | |
(let [[fst snd & r] trees] | |
(if (nil? snd) | |
trees | |
(recur (sort-by :weight (cons (branch fst snd) r))))))] | |
(first (combine-trees | |
(->> (frequencies text) | |
(sort-by second) | |
(map #(leaf (first %) (second %)))))))) | |
(defn decode [tree bits] | |
(loop [_tree tree | |
bits bits | |
chars []] | |
(if (branch? _tree) | |
(let [bit (first bits) | |
v (if (= bit 0) :left :right)] | |
(recur (v _tree) (rest bits) chars)) | |
(let [chars (into chars (get-chars _tree) )] | |
(if (empty? bits) | |
chars | |
(recur tree bits chars)))))) | |
(defn encode [tree text] | |
(letfn [(has-char? [tree c] | |
(some #(= c %) (get-chars tree)))] | |
(loop [_tree tree | |
chars text | |
bits []] | |
(if (empty? chars) | |
bits | |
(if (branch? _tree) | |
(let [v (if (has-char? (:left _tree) (first chars)) :left :right) | |
bits (conj bits (if (= v :left) 0 1))] | |
(recur (v _tree) chars bits)) | |
(recur tree (rest chars) bits)))))) | |
(defn fast-encode [tree] | |
(let [code-map (into {} (map #(hash-map % (encode tree (str %))) (get-chars tree)))] | |
(fn [text] (reduce (fn [s c] (into s (get code-map c))) [] text)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
wtf?!
teach me!