2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -17,6 +17,12 @@ A Huffman encoding can be computed by first creating a tree of nodes:
## Add the new node to the queue.
# The remaining node is the root node and the tree is complete.
<br>
Traverse the constructed binary tree from root to leaves assigning and accumulating a '0' for one branch and a '1' for the other at each node. The accumulated zeros and ones at each leaf constitute a Huffman encoding for those symbols and weights:
'''Using the characters and their frequency from the string ''"this is an example for huffman encoding"'', create a program to generate a Huffman encoding for each character as a table.'''
;Task:
Using the characters and their frequency from the string:
::::: &nbsp; ''' '' this is an example for huffman encoding '' '''
create a program to generate a Huffman encoding for each character as a table.
<br><br>

View file

@ -106,7 +106,8 @@ void decode(const char *s, node t)
int main(void)
{
int i;
const char *str = "this is an example for huffman encoding", buf[1024];
const char *str = "this is an example for huffman encoding";
char buf[1024];
init(str);
for (i = 0; i < 128; i++)

View file

@ -0,0 +1,52 @@
abstract class HuffmanTree(var freq: Int) : Comparable<HuffmanTree> {
override fun compareTo(other: HuffmanTree) = freq - other.freq
}
class HuffmanLeaf(freq: Int, var value: Char) : HuffmanTree(freq)
class HuffmanNode(var left: HuffmanTree, var right: HuffmanTree) : HuffmanTree(left.freq + right.freq)
fun buildTree(charFreqs: IntArray) : HuffmanTree {
val trees = PriorityQueue<HuffmanTree>()
charFreqs.forEachIndexed { index, freq ->
if(freq > 0) trees.offer(HuffmanLeaf(freq, index.toChar()))
}
assert(trees.size > 0)
while (trees.size > 1) {
val a = trees.poll()
val b = trees.poll()
trees.offer(HuffmanNode(a, b))
}
return trees.poll()
}
fun printCodes(tree: HuffmanTree, prefix: StringBuffer) {
when(tree) {
is HuffmanLeaf -> println("${tree.value}\t${tree.freq}\t$prefix")
is HuffmanNode -> {
//traverse left
prefix.append('0')
printCodes(tree.left, prefix)
prefix.deleteCharAt(prefix.lastIndex)
//traverse right
prefix.append('1')
printCodes(tree.right, prefix)
prefix.deleteCharAt(prefix.lastIndex)
}
}
}
fun main(args: Array<String>) {
val test = "this is an example for huffman encoding"
val maxIndex = test.max()!!.toInt() + 1
val freqs = IntArray(maxIndex) //256 enough for latin ASCII table, but dynamic size is more fun
test.forEach { freqs[it.toInt()] += 1 }
val tree = buildTree(freqs)
println("SYMBOL\tWEIGHT\tHUFFMAN CODE")
printCodes(tree, StringBuffer())
}

View file

@ -0,0 +1,91 @@
MODULE HuffmanEncoding;
IMPORT
Object,
PriorityQueue,
Strings,
Out;
TYPE
Leaf = POINTER TO LeafDesc;
LeafDesc = RECORD
(Object.ObjectDesc)
c: CHAR;
END;
Inner = POINTER TO InnerDesc;
InnerDesc = RECORD
(Object.ObjectDesc)
left,right: Object.Object;
END;
VAR
str: ARRAY 128 OF CHAR;
i: INTEGER;
f: ARRAY 96 OF INTEGER;
q: PriorityQueue.Queue;
a: PriorityQueue.Node;
b: PriorityQueue.Node;
c: PriorityQueue.Node;
h: ARRAY 64 OF CHAR;
PROCEDURE NewLeaf(c: CHAR): Leaf;
VAR
x: Leaf;
BEGIN
NEW(x);x.c := c; RETURN x
END NewLeaf;
PROCEDURE NewInner(l,r: Object.Object): Inner;
VAR
x: Inner;
BEGIN
NEW(x); x.left := l; x.right := r; RETURN x
END NewInner;
PROCEDURE Preorder(n: Object.Object; VAR x: ARRAY OF CHAR);
BEGIN
IF n IS Leaf THEN
Out.Char(n(Leaf).c);Out.String(": ");Out.String(h);Out.Ln
ELSE
IF n(Inner).left # NIL THEN
Strings.Append("0",x);
Preorder(n(Inner).left,x);
Strings.Delete(x,(Strings.Length(x) - 1),1)
END;
IF n(Inner).right # NIL THEN
Strings.Append("1",x);
Preorder(n(Inner).right,x);
Strings.Delete(x,(Strings.Length(x) - 1),1)
END
END
END Preorder;
BEGIN
str := "this is an example for huffman encoding";
(* Collect letter frecuencies *)
i := 0;
WHILE str[i] # 0X DO INC(f[ORD(CAP(str[i])) - ORD(' ')]);INC(i) END;
(* Create Priority Queue *)
NEW(q);q.Clear();
(* Insert into the queue *)
i := 0;
WHILE (i < LEN(f)) DO
IF f[i] # 0 THEN
q.Insert(f[i]/Strings.Length(str),NewLeaf(CHR(i + ORD(' '))))
END;
INC(i)
END;
(* create tree *)
WHILE q.Length() > 1 DO
q.Remove(a);q.Remove(b);
q.Insert(a.w + b.w,NewInner(a.d,b.d));
END;
(* tree traversal *)
h[0] := 0X;q.Remove(c);Preorder(c.d,h);
END HuffmanEncoding.

View file

@ -1,17 +1,13 @@
sub huffman ($s) {
my $de = $s.chars;
my @q = $s.comb.classify({$_}).map({[+.value / $de, .key]}).sort;
while @q > 1 {
my ($a,$b) = @q.splice(0,2);
@q = sort flat $[$a[0] + $b[0], [$a[1], $b[1]]], @q;
sub huffman (%frequencies) {
my @queue = %frequencies.map({ [.value, .key] }).sort;
while @queue > 1 {
given @queue.splice(0, 2) -> ([$freq1, $node1], [$freq2, $node2]) {
@queue = (|@queue, [$freq1 + $freq2, [$node1, $node2]]).sort;
}
}
sort *.value, gather walk @q[0][1], '';
hash gather walk @queue[0][1], '';
}
multi walk (@node, $prefix) {
walk @node[0], $prefix ~ 1;
walk @node[1], $prefix ~ 0;
}
multi walk ($node, $prefix) { take $node => $prefix }
say .perl for huffman('this is an example for huffman encoding');
multi walk ($node, $prefix) { take $node => $prefix; }
multi walk ([$node1, $node2], $prefix) { walk $node1, $prefix ~ '0';
walk $node2, $prefix ~ '1'; }

View file

@ -1,9 +1,11 @@
my $str = 'this is an example for huffman encoding';
my %enc = huffman $str;
my %dec = %enc.invert;
say $str;
my $huf = %enc{$str.comb}.join;
say $huf;
my $rx = join('|', map { "'" ~ .key ~ "'" }, %dec);
$rx = EVAL '/' ~ $rx ~ '/';
say $huf.subst(/<$rx>/, -> $/ {%dec{~$/}}, :g);
sub huffman (%frequencies) {
my @queue = %frequencies.map: { .value => (hash .key => '') };
while @queue > 1 {
@queue.=sort;
my $x = @queue.shift;
my $y = @queue.shift;
@queue.push: ($x.key + $y.key) => hash $x.value.deepmap('0' ~ *),
$y.value.deepmap('1' ~ *);
}
@queue[0].value;
}

View file

@ -0,0 +1,3 @@
for huffman 'this is an example for huffman encoding'.comb.Bag {
say "'{.key}' : {.value}";
}

View file

@ -0,0 +1,10 @@
my $original = 'this is an example for huffman encoding';
my %encode-key = huffman $original.comb.Bag;
my %decode-key = %encode-key.invert;
my @codes = %decode-key.keys;
my $encoded = $original.subst: /./, { %encode-key{$_} }, :g;
my $decoded = $encoded .subst: /@codes/, { %decode-key{$_} }, :g;
.say for $original, $encoded, $decoded;

View file

@ -0,0 +1,61 @@
function Get-HuffmanEncodingTable ( $String )
{
# Create leaf nodes
$ID = 0
$Nodes = [char[]]$String |
Group-Object |
ForEach { $ID++; $_ } |
Select @{ Label = 'Symbol' ; Expression = { $_.Name } },
@{ Label = 'Count' ; Expression = { $_.Count } },
@{ Label = 'ID' ; Expression = { $ID } },
@{ Label = 'Parent' ; Expression = { 0 } },
@{ Label = 'Code' ; Expression = { '' } }
# Grow stems under leafs
ForEach ( $Branch in 2..($Nodes.Count) )
{
# Get the two nodes with the lowest count
$LowNodes = $Nodes | Where Parent -eq 0 | Sort Count | Select -First 2
# Create a new stem node
$ID++
$Nodes += '' |
Select @{ Label = 'Symbol' ; Expression = { '' } },
@{ Label = 'Count' ; Expression = { $LowNodes[0].Count + $LowNodes[1].Count } },
@{ Label = 'ID' ; Expression = { $ID } },
@{ Label = 'Parent' ; Expression = { 0 } },
@{ Label = 'Code' ; Expression = { '' } }
# Put the two nodes in the new stem node
$LowNodes[0].Parent = $ID
$LowNodes[1].Parent = $ID
# Assign 0 and 1 to the left and right nodes
$LowNodes[0].Code = '0'
$LowNodes[1].Code = '1'
}
# Assign coding to nodes
ForEach ( $Node in $Nodes[($Nodes.Count-2)..0] )
{
$Node.Code = ( $Nodes | Where ID -eq $Node.Parent ).Code + $Node.Code
}
$EncodingTable = $Nodes | Where { $_.Symbol } | Select Symbol, Code | Sort Symbol
return $EncodingTable
}
# Get table for given string
$String = "this is an example for huffman encoding"
$HuffmanEncodingTable = Get-HuffmanEncodingTable $String
# Display table
$HuffmanEncodingTable | Format-Table -AutoSize
# Encode string
$EncodedString = $String
ForEach ( $Node in $HuffmanEncodingTable )
{
$EncodedString = $EncodedString.Replace( $Node.Symbol, $Node.Code )
}
$EncodedString

View file

@ -12,8 +12,8 @@ Structure ztree
right.l
EndStructure
Dim memc.c(0)
memc()=@SampleString
Dim memc.c(datalen)
CopyMemory(@SampleString, @memc(0), datalen * SizeOf(Character))
Dim tree.ztree(255)
@ -23,7 +23,7 @@ For i=0 To datalen-1
tree(memc(i))\ischar=1
Next
SortStructuredArray(tree(),#PB_Sort_Descending,OffsetOf(ztree\number),#PB_Sort_Character)
SortStructuredArray(tree(),#PB_Sort_Descending,OffsetOf(ztree\number),#PB_Integer)
For i=0 To 255
If tree(i)\number=0

View file

@ -0,0 +1,43 @@
// this version uses immutable data only, recursive functions and pattern matching
object Huffman {
sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
// recursively build the binary tree needed to Huffman encode the text
def merge(xs: List[(Tree[Char], Int)]): List[(Tree[Char], Int)] = {
if (xs.length == 1) xs else {
val l = xs.head
val r = xs.tail.head
val merged = (Branch(l._1, r._1), l._2 + r._2)
merge((merged :: xs.drop(2)).sortBy(_._2))
}
}
// recursively search the branches of the tree for the required character
def contains(tree: Tree[Char], char: Char): Boolean = tree match {
case Leaf(c) => if (c == char) true else false
case Branch(l, r) => contains(l, char) || contains(r, char)
}
// recursively build the path string required to traverse the tree to the required character
def encodeChar(tree: Tree[Char], char: Char): String = {
def go(tree: Tree[Char], char: Char, code: String): String = tree match {
case Leaf(_) => code
case Branch(l, r) => if (contains(l, char)) go(l, char, code + '0') else go(r, char, code + '1')
}
go(tree, char, "")
}
def main(args: Array[String]) {
val text = "this is an example for huffman encoding"
// transform the text into a list of tuples.
// each tuple contains a Leaf node containing a unique character and an Int representing that character's weight
val frequencies = text.groupBy(chars => chars).mapValues(group => group.length).toList.map(x => (Leaf(x._1), x._2)).sortBy(_._2)
// build the Huffman Tree for this text
val huffmanTree = merge(frequencies).head._1
// output the resulting character codes
println("Char\tWeight\tCode")
frequencies.foreach(x => println(x._1.value + "\t" + x._2 + s"/${text.length}" + s"\t${encodeChar(huffmanTree, x._1.value)}"))
}
}