From d9d802337271897a8a0ee7298a4c76c3b5f7903d Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sun, 23 Feb 2020 22:26:48 +0100 Subject: [PATCH] Add codes table generation, add tests --- README.md | 5 +++ go.mod | 8 +++++ go.sum | 12 +++++++ huffman.go | 40 ++++++++++++++++++++++ huffman_test.go | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 153 insertions(+) create mode 100644 README.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 huffman_test.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..3aef37d --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# huffman-coding + +https://en.wikipedia.org/wiki/Huffman_coding + + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7510772 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module huffman-coding + +go 1.13 + +require ( + github.com/stretchr/testify v1.5.1 + gopkg.in/go-playground/assert.v1 v1.2.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..83b096b --- /dev/null +++ b/go.sum @@ -0,0 +1,12 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/huffman.go b/huffman.go index eba462d..d734046 100644 --- a/huffman.go +++ b/huffman.go @@ -90,3 +90,43 @@ func buildTree(nodes []*Node) *Node { } return nodes[0] } + +func descendTable(n *Node, path string, table map[byte]string) map[byte]string { + if n.typ == MID { + table = descendTable(n.l, path+"0", table) + table = descendTable(n.r, path+"1", table) + } else if n.typ == LEAF { + table[n.leaf] = path + } + return table +} + +func generateTable(n *Node) map[byte]string { + table := make(map[byte]string) + table = descendTable(n, "", table) + return table +} + +func Huffman(b []byte) error { + // compute frequencies + values := make(map[byte]int64) + for _, v := range b { + values[v]++ + } + leafs := leafsFromValues(values) + + // sort frequencies + sortedLeafs := sortNodes(leafs) + + // build binary tree + n := buildTree(sortedLeafs) + fmt.Println(n) + + // get the table (binary code for each value) + table := generateTable(n) + fmt.Println(table) + + // WIP + + return nil +} diff --git a/huffman_test.go b/huffman_test.go new file mode 100644 index 0000000..a5ca063 --- /dev/null +++ b/huffman_test.go @@ -0,0 +1,88 @@ +package huffman + +import ( + "fmt" + "testing" + + "gopkg.in/go-playground/assert.v1" +) + +var debug = true + +func TestBuildTree0(t *testing.T) { + values := make(map[byte]int64) + values[65] = 3 + values[66] = 5 + values[67] = 6 + values[68] = 4 + values[69] = 2 + + leafs := leafsFromValues(values) + sortedLeafs := sortNodes(leafs) + n := buildTree(sortedLeafs) + + /* + Expected result (both valid): + 20 + / \ + 9 \ + / \ \ + / 5 11 + / / \ / \ + 4 2 3 5 6 + + 20 + / \ + / 11 + / / \ + 9 5 \ + / \ / \ \ + 4 5 2 3 6 + The second tree is what is genereated in this test + */ + assert.Equal(t, int64(20), n.key) + assert.Equal(t, int64(9), n.l.key) + assert.Equal(t, int64(4), n.l.l.key) + assert.Equal(t, int64(5), n.l.r.key) + assert.Equal(t, int64(11), n.r.key) + assert.Equal(t, int64(5), n.r.l.key) + assert.Equal(t, int64(2), n.r.l.l.key) + assert.Equal(t, int64(3), n.r.l.r.key) + assert.Equal(t, int64(6), n.r.r.key) +} + +func TestBuildTree1(t *testing.T) { + values := make(map[byte]int64) + values[97] = 10 + values[101] = 15 + values[105] = 12 + values[115] = 3 + values[116] = 4 + values[112] = 13 + values[10] = 1 + + leafs := leafsFromValues(values) + sortedLeafs := sortNodes(leafs) + n := buildTree(sortedLeafs) + + assert.Equal(t, int64(58), n.key) + assert.Equal(t, int64(25), n.l.key) + assert.Equal(t, int64(33), n.r.key) +} + +func TestGenerateTable(t *testing.T) { + values := make(map[byte]int64) + values[65] = 3 + values[66] = 5 + values[67] = 6 + values[68] = 4 + values[69] = 2 + + leafs := leafsFromValues(values) + sortedLeafs := sortNodes(leafs) + n := buildTree(sortedLeafs) + + table := generateTable(n) + + fmt.Println(table) +}