src/huffman-trees.lisp @ 5d5018e0b82b
Start the SICP Huffman trees
author |
Steve Losh <steve@stevelosh.com> |
date |
Tue, 23 Aug 2016 00:22:20 +0000 |
parents |
(none) |
children |
301c22f28112 |
(in-package #:sand.huffman-trees)
(defstruct huffman-tree)
(defstruct (leaf (:include huffman-tree)
(:constructor make-leaf (symbol weight)))
(symbol (required-argument))
(weight (required-argument) :type real))
(defstruct (node (:include huffman-tree)
(:constructor %make-node))
(left (required-argument) :type huffman-tree)
(right (required-argument) :type huffman-tree)
(symbols (required-argument) :type list)
(weight (required-argument) :type real))
(defun huffman-tree-symbols (tree)
(etypecase tree
(leaf (list (leaf-symbol tree)))
(node (node-symbols tree))))
(defun huffman-tree-weight (tree)
(etypecase tree
(leaf (leaf-weight tree))
(node (node-weight tree))))
(defun make-node (left right)
(%make-node :left left
:right right
:weight (+ (huffman-tree-weight left)
(huffman-tree-weight right))
:symbols (append (huffman-tree-symbols left)
(huffman-tree-symbols right))))
(defun decode (bits tree)
(flet ((choose-branch (bit tree)
(ecase bit
(0 (node-left tree))
(1 (node-right tree)))))
(recursively ((bits bits)
(current tree))
(when bits
(let ((next-branch (choose-branch (first bits) current)))
(etypecase next-branch
(leaf (cons (leaf-symbol next-branch)
(recur (rest bits) tree)))
(node (recur (rest bits) next-branch))))))))
(defun adjoin-set (tree set)
(cond
((null set)
(list tree))
((< (huffman-tree-weight tree) (huffman-tree-weight (first set)))
(cons tree set))
(t
(cons (first set)
(adjoin-set tree (rest set))))))
(defun make-leaf-set (pairs)
(if (null pairs)
'()
(destructuring-bind (symbol weight)
(first pairs)
(adjoin-set (make-leaf symbol weight)
(make-leaf-set (rest pairs))))))
(defparameter *sample-tree*
(make-node (make-leaf 'a 4)
(make-node (make-leaf 'b 2)
(make-node (make-leaf 'D 1)
(make-leaf 'C 1)))))
; (decode '(0 1 1 0 0 1 0 1 0 1 1 1 0) *sample-tree*)