Data update

This commit is contained in:
Ingy döt Net 2026-02-01 16:33:20 -08:00
parent 5150844a7d
commit 4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions

View file

@ -1,83 +0,0 @@
with Ada.Containers.Indefinite_Ordered_Maps;
with Ada.Containers.Ordered_Maps;
with Ada.Finalization;
generic
type Symbol_Type is private;
with function "<" (Left, Right : Symbol_Type) return Boolean is <>;
with procedure Put (Item : Symbol_Type);
type Symbol_Sequence is array (Positive range <>) of Symbol_Type;
type Frequency_Type is private;
with function "+" (Left, Right : Frequency_Type) return Frequency_Type
is <>;
with function "<" (Left, Right : Frequency_Type) return Boolean is <>;
package Huffman is
-- bits = booleans (true/false = 1/0)
type Bit_Sequence is array (Positive range <>) of Boolean;
Zero_Sequence : constant Bit_Sequence (1 .. 0) := (others => False);
-- output the sequence
procedure Put (Code : Bit_Sequence);
-- type for freqency map
package Frequency_Maps is new Ada.Containers.Ordered_Maps
(Element_Type => Frequency_Type,
Key_Type => Symbol_Type);
type Huffman_Tree is private;
-- create a huffman tree from frequency map
procedure Create_Tree
(Tree : out Huffman_Tree;
Frequencies : Frequency_Maps.Map);
-- encode a single symbol
function Encode
(Tree : Huffman_Tree;
Symbol : Symbol_Type)
return Bit_Sequence;
-- encode a symbol sequence
function Encode
(Tree : Huffman_Tree;
Symbols : Symbol_Sequence)
return Bit_Sequence;
-- decode a bit sequence
function Decode
(Tree : Huffman_Tree;
Code : Bit_Sequence)
return Symbol_Sequence;
-- dump the encoding table
procedure Dump_Encoding (Tree : Huffman_Tree);
private
-- type for encoding map
package Encoding_Maps is new Ada.Containers.Indefinite_Ordered_Maps
(Element_Type => Bit_Sequence,
Key_Type => Symbol_Type);
type Huffman_Node;
type Node_Access is access Huffman_Node;
-- a node is either internal (left_child/right_child used)
-- or a leaf (left_child/right_child are null)
type Huffman_Node is record
Frequency : Frequency_Type;
Left_Child : Node_Access := null;
Right_Child : Node_Access := null;
Symbol : Symbol_Type;
end record;
-- create a leaf node
function Create_Node
(Symbol : Symbol_Type;
Frequency : Frequency_Type)
return Node_Access;
-- create an internal node
function Create_Node (Left, Right : Node_Access) return Node_Access;
-- fill the encoding map
procedure Fill
(The_Node : Node_Access;
Map : in out Encoding_Maps.Map;
Prefix : Bit_Sequence);
-- huffman tree has a tree and an encoding map
type Huffman_Tree is new Ada.Finalization.Controlled with record
Tree : Node_Access := null;
Map : Encoding_Maps.Map := Encoding_Maps.Empty_Map;
end record;
-- free memory after finalization
overriding procedure Finalize (Object : in out Huffman_Tree);
end Huffman;

View file

@ -1,244 +0,0 @@
with Ada.Text_IO;
with Ada.Unchecked_Deallocation;
with Ada.Containers.Vectors;
package body Huffman is
package Node_Vectors is new Ada.Containers.Vectors
(Element_Type => Node_Access,
Index_Type => Positive);
function "<" (Left, Right : Node_Access) return Boolean is
begin
-- compare frequency
if Left.Frequency < Right.Frequency then
return True;
elsif Right.Frequency < Left.Frequency then
return False;
end if;
-- same frequency, choose leaf node
if Left.Left_Child = null and then Right.Left_Child /= null then
return True;
elsif Left.Left_Child /= null and then Right.Left_Child = null then
return False;
end if;
-- same frequency, same node type (internal/leaf)
if Left.Left_Child /= null then
-- for internal nodes, compare left children, then right children
if Left.Left_Child < Right.Left_Child then
return True;
elsif Right.Left_Child < Left.Left_Child then
return False;
else
return Left.Right_Child < Right.Right_Child;
end if;
else
-- for leaf nodes, compare symbol
return Left.Symbol < Right.Symbol;
end if;
end "<";
package Node_Vector_Sort is new Node_Vectors.Generic_Sorting;
procedure Create_Tree
(Tree : out Huffman_Tree;
Frequencies : Frequency_Maps.Map) is
Node_Queue : Node_Vectors.Vector := Node_Vectors.Empty_Vector;
begin
-- insert all leafs into the queue
declare
use Frequency_Maps;
Position : Cursor := Frequencies.First;
The_Node : Node_Access := null;
begin
while Position /= No_Element loop
The_Node :=
Create_Node
(Symbol => Key (Position),
Frequency => Element (Position));
Node_Queue.Append (The_Node);
Next (Position);
end loop;
end;
-- sort by frequency (see "<")
Node_Vector_Sort.Sort (Node_Queue);
-- iterate over all elements
while not Node_Queue.Is_Empty loop
declare
First : constant Node_Access := Node_Queue.First_Element;
begin
Node_Queue.Delete_First;
-- if we only have one node left, it is the root node of the tree
if Node_Queue.Is_Empty then
Tree.Tree := First;
else
-- create new internal node with two smallest frequencies
declare
Second : constant Node_Access := Node_Queue.First_Element;
begin
Node_Queue.Delete_First;
Node_Queue.Append (Create_Node (First, Second));
end;
Node_Vector_Sort.Sort (Node_Queue);
end if;
end;
end loop;
-- fill encoding map
Fill (The_Node => Tree.Tree, Map => Tree.Map, Prefix => Zero_Sequence);
end Create_Tree;
-- create leaf node
function Create_Node
(Symbol : Symbol_Type;
Frequency : Frequency_Type)
return Node_Access
is
Result : Node_Access := new Huffman_Node;
begin
Result.Frequency := Frequency;
Result.Symbol := Symbol;
return Result;
end Create_Node;
-- create internal node
function Create_Node (Left, Right : Node_Access) return Node_Access is
Result : Node_Access := new Huffman_Node;
begin
Result.Frequency := Left.Frequency + Right.Frequency;
Result.Left_Child := Left;
Result.Right_Child := Right;
return Result;
end Create_Node;
-- fill encoding map
procedure Fill
(The_Node : Node_Access;
Map : in out Encoding_Maps.Map;
Prefix : Bit_Sequence) is
begin
if The_Node.Left_Child /= null then
-- append false (0) for left child
Fill (The_Node.Left_Child, Map, Prefix & False);
-- append true (1) for right child
Fill (The_Node.Right_Child, Map, Prefix & True);
else
-- leaf node reached, prefix = code for symbol
Map.Insert (The_Node.Symbol, Prefix);
end if;
end Fill;
-- free memory after finalization
overriding procedure Finalize (Object : in out Huffman_Tree) is
procedure Free is new Ada.Unchecked_Deallocation
(Name => Node_Access,
Object => Huffman_Node);
-- recursively free all nodes
procedure Recursive_Free (The_Node : in out Node_Access) is
begin
-- free node if it is a leaf
if The_Node.Left_Child = null then
Free (The_Node);
else
-- free left and right child if node is internal
Recursive_Free (The_Node.Left_Child);
Recursive_Free (The_Node.Right_Child);
-- free node afterwards
Free (The_Node);
end if;
end Recursive_Free;
begin
-- recursively free root node
Recursive_Free (Object.Tree);
end Finalize;
-- encode single symbol
function Encode
(Tree : Huffman_Tree;
Symbol : Symbol_Type)
return Bit_Sequence
is
begin
-- simply lookup in map
return Tree.Map.Element (Symbol);
end Encode;
-- encode symbol sequence
function Encode
(Tree : Huffman_Tree;
Symbols : Symbol_Sequence)
return Bit_Sequence
is
begin
-- only one element
if Symbols'Length = 1 then
-- see above
return Encode (Tree, Symbols (Symbols'First));
else
-- encode first element, append result of recursive call
return Encode (Tree, Symbols (Symbols'First)) &
Encode (Tree, Symbols (Symbols'First + 1 .. Symbols'Last));
end if;
end Encode;
-- decode a bit sequence
function Decode
(Tree : Huffman_Tree;
Code : Bit_Sequence)
return Symbol_Sequence
is
-- maximum length = code length
Result : Symbol_Sequence (1 .. Code'Length);
-- last used index of result
Last : Natural := 0;
The_Node : Node_Access := Tree.Tree;
begin
-- iterate over the code
for I in Code'Range loop
-- if current element is true, descent the right branch
if Code (I) then
The_Node := The_Node.Right_Child;
else
-- false: descend left branch
The_Node := The_Node.Left_Child;
end if;
if The_Node.Left_Child = null then
-- reached leaf node: append symbol to result
Last := Last + 1;
Result (Last) := The_Node.Symbol;
-- reset current node to root
The_Node := Tree.Tree;
end if;
end loop;
-- return subset of result array
return Result (1 .. Last);
end Decode;
-- output a bit sequence
procedure Put (Code : Bit_Sequence) is
package Int_IO is new Ada.Text_IO.Integer_IO (Integer);
begin
for I in Code'Range loop
if Code (I) then
-- true = 1
Int_IO.Put (1, 0);
else
-- false = 0
Int_IO.Put (0, 0);
end if;
end loop;
Ada.Text_IO.New_Line;
end Put;
-- dump encoding map
procedure Dump_Encoding (Tree : Huffman_Tree) is
use type Encoding_Maps.Cursor;
Position : Encoding_Maps.Cursor := Tree.Map.First;
begin
-- iterate map
while Position /= Encoding_Maps.No_Element loop
-- key
Put (Encoding_Maps.Key (Position));
Ada.Text_IO.Put (" = ");
-- code
Put (Encoding_Maps.Element (Position));
Encoding_Maps.Next (Position);
end loop;
end Dump_Encoding;
end Huffman;

View file

@ -1,49 +0,0 @@
with Ada.Text_IO;
with Huffman;
procedure Main is
package Char_Natural_Huffman_Tree is new Huffman
(Symbol_Type => Character,
Put => Ada.Text_IO.Put,
Symbol_Sequence => String,
Frequency_Type => Natural);
Tree : Char_Natural_Huffman_Tree.Huffman_Tree;
Frequencies : Char_Natural_Huffman_Tree.Frequency_Maps.Map;
Input_String : constant String :=
"this is an example for huffman encoding";
begin
-- build frequency map
for I in Input_String'Range loop
declare
use Char_Natural_Huffman_Tree.Frequency_Maps;
Position : constant Cursor := Frequencies.Find (Input_String (I));
begin
if Position = No_Element then
Frequencies.Insert (Key => Input_String (I), New_Item => 1);
else
Frequencies.Replace_Element
(Position => Position,
New_Item => Element (Position) + 1);
end if;
end;
end loop;
-- create huffman tree
Char_Natural_Huffman_Tree.Create_Tree
(Tree => Tree,
Frequencies => Frequencies);
-- dump encodings
Char_Natural_Huffman_Tree.Dump_Encoding (Tree => Tree);
-- encode example string
declare
Code : constant Char_Natural_Huffman_Tree.Bit_Sequence :=
Char_Natural_Huffman_Tree.Encode
(Tree => Tree,
Symbols => Input_String);
begin
Char_Natural_Huffman_Tree.Put (Code);
Ada.Text_IO.Put_Line
(Char_Natural_Huffman_Tree.Decode (Tree => Tree, Code => Code));
end;
end Main;

View file

@ -35,7 +35,7 @@ static void _heap_destroy(heap_t *heap)
free(heap);
}
#define swap_(I,J) do { int t_; t_ = a[(I)]; \
#define swap_(I,J) do { int t_; t_ = a[(I)]; \
a[(I)] = a[(J)]; a[(J)] = t_; } while(0)
static void _heap_sort(heap_t *heap)
{

View file

@ -2,9 +2,9 @@
#include <string.h>
typedef struct node_t {
struct node_t *left, *right;
int freq;
char c;
struct node_t *left, *right;
int freq;
char c;
} *node;
struct node_t pool[256] = {{0}};
@ -14,110 +14,110 @@ char *code[128] = {0}, buf[1024];
node new_node(int freq, char c, node a, node b)
{
node n = pool + n_nodes++;
if (freq) n->c = c, n->freq = freq;
else {
n->left = a, n->right = b;
n->freq = a->freq + b->freq;
}
return n;
node n = pool + n_nodes++;
if (freq) n->c = c, n->freq = freq;
else {
n->left = a, n->right = b;
n->freq = a->freq + b->freq;
}
return n;
}
/* priority queue */
void qinsert(node n)
{
int j, i = qend++;
while ((j = i / 2)) {
if (q[j]->freq <= n->freq) break;
q[i] = q[j], i = j;
}
q[i] = n;
int j, i = qend++;
while ((j = i / 2)) {
if (q[j]->freq <= n->freq) break;
q[i] = q[j], i = j;
}
q[i] = n;
}
node qremove()
{
int i, l;
node n = q[i = 1];
int i, l;
node n = q[i = 1];
if (qend < 2) return 0;
qend--;
while ((l = i * 2) < qend) {
if (l + 1 < qend && q[l + 1]->freq < q[l]->freq) l++;
q[i] = q[l], i = l;
}
q[i] = q[qend];
return n;
if (qend < 2) return 0;
qend--;
while ((l = i * 2) < qend) {
if (l + 1 < qend && q[l + 1]->freq < q[l]->freq) l++;
q[i] = q[l], i = l;
}
q[i] = q[qend];
return n;
}
/* walk the tree and put 0s and 1s */
void build_code(node n, char *s, int len)
{
static char *out = buf;
if (n->c) {
s[len] = 0;
strcpy(out, s);
code[n->c] = out;
out += len + 1;
return;
}
static char *out = buf;
if (n->c) {
s[len] = 0;
strcpy(out, s);
code[n->c] = out;
out += len + 1;
return;
}
s[len] = '0'; build_code(n->left, s, len + 1);
s[len] = '1'; build_code(n->right, s, len + 1);
s[len] = '0'; build_code(n->left, s, len + 1);
s[len] = '1'; build_code(n->right, s, len + 1);
}
void init(const char *s)
{
int i, freq[128] = {0};
char c[16];
int i, freq[128] = {0};
char c[16];
while (*s) freq[(int)*s++]++;
while (*s) freq[(int)*s++]++;
for (i = 0; i < 128; i++)
if (freq[i]) qinsert(new_node(freq[i], i, 0, 0));
for (i = 0; i < 128; i++)
if (freq[i]) qinsert(new_node(freq[i], i, 0, 0));
while (qend > 2)
qinsert(new_node(0, 0, qremove(), qremove()));
while (qend > 2)
qinsert(new_node(0, 0, qremove(), qremove()));
build_code(q[1], c, 0);
build_code(q[1], c, 0);
}
void encode(const char *s, char *out)
{
while (*s) {
strcpy(out, code[*s]);
out += strlen(code[*s++]);
}
while (*s) {
strcpy(out, code[*s]);
out += strlen(code[*s++]);
}
}
void decode(const char *s, node t)
{
node n = t;
while (*s) {
if (*s++ == '0') n = n->left;
else n = n->right;
node n = t;
while (*s) {
if (*s++ == '0') n = n->left;
else n = n->right;
if (n->c) putchar(n->c), n = t;
}
if (n->c) putchar(n->c), n = t;
}
putchar('\n');
if (t != n) printf("garbage input\n");
putchar('\n');
if (t != n) printf("garbage input\n");
}
int main(void)
{
int i;
const char *str = "this is an example for huffman encoding";
int i;
const char *str = "this is an example for huffman encoding";
char buf[1024];
init(str);
for (i = 0; i < 128; i++)
if (code[i]) printf("'%c': %s\n", i, code[i]);
init(str);
for (i = 0; i < 128; i++)
if (code[i]) printf("'%c': %s\n", i, code[i]);
encode(str, buf);
printf("encoded: %s\n", buf);
encode(str, buf);
printf("encoded: %s\n", buf);
printf("decoded: ");
decode(buf, q[1]);
printf("decoded: ");
decode(buf, q[1]);
return 0;
return 0;
}

View file

@ -14,7 +14,7 @@
(defn huffman-tree [pq]
(while (> (.size pq) 1)
(let [a (.poll pq) b (.poll pq)
new-node {:priority (+ (:priority a) (:priority b)) :left a :right b}]
new-node {:priority (+ (:priority a) (:priority b)) :left a :right b}]
(.add pq new-node)))
(.poll pq))

View file

@ -4,29 +4,29 @@
(defn init-pq [s]
(let [c (count s)]
(->> s frequencies
(map (fn [[k v]] [k {:sym k :weight (/ v c)}]))
(into (priority-map-keyfn-by :weight <)))))
(map (fn [[k v]] [k {:sym k :weight (/ v c)}]))
(into (priority-map-keyfn-by :weight <)))))
(defn huffman-tree [pq]
(letfn [(build-step
[pq]
(let [a (second (peek pq)) b (second (peek (pop pq)))
nn {:sym (str (:sym a) (:sym b))
:weight (+ (:weight a) (:weight b))
:left a :right b}]
(assoc (pop (pop pq)) (:sym nn) nn)))]
[pq]
(let [a (second (peek pq)) b (second (peek (pop pq)))
nn {:sym (str (:sym a) (:sym b))
:weight (+ (:weight a) (:weight b))
:left a :right b}]
(assoc (pop (pop pq)) (:sym nn) nn)))]
(->> (iterate build-step pq)
(drop-while #(> (count %) 1))
first vals first)))
(drop-while #(> (count %) 1))
first vals first)))
(defn symbol-map [m]
(letfn [(sym-step
[{:keys [sym weight left right] :as m} code]
(cond (and left right) #(vector (trampoline sym-step left (str code \0))
(trampoline sym-step right (str code \1)))
left #(sym-step left (str code \0))
right #(sym-step right (str code \1))
:else {:sym sym :weight weight :code code}))]
[{:keys [sym weight left right] :as m} code]
(cond (and left right) #(vector (trampoline sym-step left (str code \0))
(trampoline sym-step right (str code \1)))
left #(sym-step left (str code \0))
right #(sym-step right (str code \1))
:else {:sym sym :weight weight :code code}))]
(trampoline sym-step m "")))
(defn huffman-encode [s]

View file

@ -1,188 +1,188 @@
class HUFFMAN_NODE[T -> COMPARABLE]
inherit
COMPARABLE
redefine
three_way_comparison
end
COMPARABLE
redefine
three_way_comparison
end
create
leaf_node, inner_node
leaf_node, inner_node
feature {NONE}
leaf_node (a_probability: REAL_64; a_value: T)
do
probability := a_probability
value := a_value
is_leaf := true
leaf_node (a_probability: REAL_64; a_value: T)
do
probability := a_probability
value := a_value
is_leaf := true
left := void
right := void
parent := void
end
left := void
right := void
parent := void
end
inner_node (a_left, a_right: HUFFMAN_NODE[T])
do
left := a_left
right := a_right
inner_node (a_left, a_right: HUFFMAN_NODE[T])
do
left := a_left
right := a_right
a_left.parent := Current
a_right.parent := Current
a_left.is_zero := true
a_right.is_zero := false
a_left.parent := Current
a_right.parent := Current
a_left.is_zero := true
a_right.is_zero := false
probability := a_left.probability + a_right.probability
is_leaf := false
end
probability := a_left.probability + a_right.probability
is_leaf := false
end
feature
probability: REAL_64
value: detachable T
probability: REAL_64
value: detachable T
is_leaf: BOOLEAN
is_zero: BOOLEAN assign set_is_zero
is_leaf: BOOLEAN
is_zero: BOOLEAN assign set_is_zero
set_is_zero (a_value: BOOLEAN)
do
is_zero := a_value
end
set_is_zero (a_value: BOOLEAN)
do
is_zero := a_value
end
left: detachable HUFFMAN_NODE[T]
right: detachable HUFFMAN_NODE[T]
parent: detachable HUFFMAN_NODE[T] assign set_parent
left: detachable HUFFMAN_NODE[T]
right: detachable HUFFMAN_NODE[T]
parent: detachable HUFFMAN_NODE[T] assign set_parent
set_parent (a_parent: detachable HUFFMAN_NODE[T])
do
parent := a_parent
end
set_parent (a_parent: detachable HUFFMAN_NODE[T])
do
parent := a_parent
end
is_root: BOOLEAN
do
Result := parent = void
end
is_root: BOOLEAN
do
Result := parent = void
end
bit_value: INTEGER
do
if is_zero then
Result := 0
else
Result := 1
end
end
bit_value: INTEGER
do
if is_zero then
Result := 0
else
Result := 1
end
end
feature -- comparable implementation
is_less alias "<" (other: like Current): BOOLEAN
do
Result := three_way_comparison (other) = -1
end
is_less alias "<" (other: like Current): BOOLEAN
do
Result := three_way_comparison (other) = -1
end
three_way_comparison (other: like Current): INTEGER
do
Result := -probability.three_way_comparison (other.probability)
end
three_way_comparison (other: like Current): INTEGER
do
Result := -probability.three_way_comparison (other.probability)
end
end
class HUFFMAN
create
make
make
feature {NONE}
make(a_string: STRING)
require
non_empty_string: a_string.count > 0
local
l_queue: HEAP_PRIORITY_QUEUE[HUFFMAN_NODE[CHARACTER]]
l_counts: HASH_TABLE[INTEGER, CHARACTER]
l_node: HUFFMAN_NODE[CHARACTER]
l_left, l_right: HUFFMAN_NODE[CHARACTER]
do
create l_queue.make (a_string.count)
create l_counts.make (10)
make(a_string: STRING)
require
non_empty_string: a_string.count > 0
local
l_queue: HEAP_PRIORITY_QUEUE[HUFFMAN_NODE[CHARACTER]]
l_counts: HASH_TABLE[INTEGER, CHARACTER]
l_node: HUFFMAN_NODE[CHARACTER]
l_left, l_right: HUFFMAN_NODE[CHARACTER]
do
create l_queue.make (a_string.count)
create l_counts.make (10)
across a_string as char
loop
if not l_counts.has (char.item) then
l_counts.put (0, char.item)
end
l_counts.replace (l_counts.at (char.item) + 1, char.item)
end
across a_string as char
loop
if not l_counts.has (char.item) then
l_counts.put (0, char.item)
end
l_counts.replace (l_counts.at (char.item) + 1, char.item)
end
create leaf_dictionary.make(l_counts.count)
create leaf_dictionary.make(l_counts.count)
across l_counts as kv
loop
create l_node.leaf_node ((kv.item * 1.0) / a_string.count, kv.key)
l_queue.put (l_node)
leaf_dictionary.put (l_node, kv.key)
end
across l_counts as kv
loop
create l_node.leaf_node ((kv.item * 1.0) / a_string.count, kv.key)
l_queue.put (l_node)
leaf_dictionary.put (l_node, kv.key)
end
from
until
l_queue.count <= 1
loop
l_left := l_queue.item
l_queue.remove
l_right := l_queue.item
l_queue.remove
from
until
l_queue.count <= 1
loop
l_left := l_queue.item
l_queue.remove
l_right := l_queue.item
l_queue.remove
create l_node.inner_node (l_left, l_right)
l_queue.put (l_node)
end
create l_node.inner_node (l_left, l_right)
l_queue.put (l_node)
end
root := l_queue.item
root.is_zero := false
end
root := l_queue.item
root.is_zero := false
end
feature
root: HUFFMAN_NODE[CHARACTER]
leaf_dictionary: HASH_TABLE[HUFFMAN_NODE[CHARACTER], CHARACTER]
root: HUFFMAN_NODE[CHARACTER]
leaf_dictionary: HASH_TABLE[HUFFMAN_NODE[CHARACTER], CHARACTER]
encode(a_value: CHARACTER): STRING
require
encodable: leaf_dictionary.has (a_value)
local
l_node: HUFFMAN_NODE[CHARACTER]
do
Result := ""
if attached leaf_dictionary.item (a_value) as attached_node then
l_node := attached_node
from
encode(a_value: CHARACTER): STRING
require
encodable: leaf_dictionary.has (a_value)
local
l_node: HUFFMAN_NODE[CHARACTER]
do
Result := ""
if attached leaf_dictionary.item (a_value) as attached_node then
l_node := attached_node
from
until
l_node.is_root
loop
Result.append_integer (l_node.bit_value)
if attached l_node.parent as parent then
l_node := parent
end
end
until
l_node.is_root
loop
Result.append_integer (l_node.bit_value)
if attached l_node.parent as parent then
l_node := parent
end
end
Result.mirror
end
end
Result.mirror
end
end
end
class
APPLICATION
APPLICATION
create
make
make
feature {NONE}
make -- entry point
local
l_str: STRING
huff: HUFFMAN
chars: BINARY_SEARCH_TREE_SET[CHARACTER]
do
l_str := "this is an example for huffman encoding"
make -- entry point
local
l_str: STRING
huff: HUFFMAN
chars: BINARY_SEARCH_TREE_SET[CHARACTER]
do
l_str := "this is an example for huffman encoding"
create huff.make (l_str)
create huff.make (l_str)
create chars.make
chars.fill (l_str)
create chars.make
chars.fill (l_str)
from
chars.start
until
chars.off
loop
print (chars.item.out + ": " + huff.encode (chars.item) + "%N")
chars.forth
end
end
from
chars.start
until
chars.off
loop
print (chars.item.out + ": " + huff.encode (chars.item) + "%N")
chars.forth
end
end
end

View file

@ -113,20 +113,20 @@ PRIVATE>
! { 1 2 3 4 } huffman huffman-print
! "this is an example of a huffman tree" huffman huffman-print
! Element Weight Code
! 7 { 0 0 0 }
! a 4 { 1 1 1 }
! e 4 { 1 1 0 }
! f 3 { 0 0 1 0 }
! h 2 { 1 0 1 0 }
! i 2 { 0 1 0 1 }
! m 2 { 0 1 0 0 }
! n 2 { 0 1 1 1 }
! s 2 { 0 1 1 0 }
! t 2 { 0 0 1 1 }
! l 1 { 1 0 1 1 1 }
! o 1 { 1 0 1 1 0 }
! p 1 { 1 0 0 0 1 }
! r 1 { 1 0 0 0 0 }
! u 1 { 1 0 0 1 1 }
! x 1 { 1 0 0 1 0 }
! Element Weight Code
! 7 { 0 0 0 }
! a 4 { 1 1 1 }
! e 4 { 1 1 0 }
! f 3 { 0 0 1 0 }
! h 2 { 1 0 1 0 }
! i 2 { 0 1 0 1 }
! m 2 { 0 1 0 0 }
! n 2 { 0 1 1 1 }
! s 2 { 0 1 1 0 }
! t 2 { 0 0 1 1 }
! l 1 { 1 0 1 1 1 }
! o 1 { 1 0 1 1 0 }
! p 1 { 1 0 0 0 1 }
! r 1 { 1 0 0 0 0 }
! u 1 { 1 0 0 1 1 }
! x 1 { 1 0 0 1 0 }

View file

@ -54,7 +54,7 @@ local c,T
T := table()
every c := !s do {
/T[c] := huffnode(,,0,c)
T[c].n +:= 1
T[c].n +:= 1
}
return T
end

View file

@ -1,99 +1,99 @@
class node{
constructor(freq, char, left, right){
this.left = left;
this.right = right;
this.freq = freq;
this.c = char;
}
constructor(freq, char, left, right){
this.left = left;
this.right = right;
this.freq = freq;
this.c = char;
}
};
nodes = [];
code = {};
function new_node(left, right){
return new node(left.freq + right.freq, -1, left, right);;
return new node(left.freq + right.freq, -1, left, right);;
};
function qinsert(node){
nodes.push(node);
nodes.sort(compareFunction);
nodes.push(node);
nodes.sort(compareFunction);
};
function qremove(){
return nodes.pop();
return nodes.pop();
};
function compareFunction(a, b){
return b.freq - a.freq;
return b.freq - a.freq;
};
function build_code(node, codeString, length){
if (node.c != -1){
code[node.c] = codeString;
return;
};
/* Left Branch */
leftCodeString = codeString + "0";
build_code(node.left, leftCodeString, length + 1);
/* Right Branch */
rightCodeString = codeString + "1";
build_code(node.right, rightCodeString, length + 1);
if (node.c != -1){
code[node.c] = codeString;
return;
};
/* Left Branch */
leftCodeString = codeString + "0";
build_code(node.left, leftCodeString, length + 1);
/* Right Branch */
rightCodeString = codeString + "1";
build_code(node.right, rightCodeString, length + 1);
};
function init(string){
var i;
var freq = [];
var codeString = "";
for (var i = 0; i < string.length; i++){
if (isNaN(freq[string.charCodeAt(i)])){
freq[string.charCodeAt(i)] = 1;
} else {
freq[string.charCodeAt(i)] ++;
};
};
for (var i = 0; i < freq.length; i++){
if (freq[i] > 0){
qinsert(new node(freq[i], i, null, null));
};
};
while (nodes.length > 1){
qinsert(new_node(qremove(), qremove()));
};
build_code(nodes[0], codeString, 0);
var i;
var freq = [];
var codeString = "";
for (var i = 0; i < string.length; i++){
if (isNaN(freq[string.charCodeAt(i)])){
freq[string.charCodeAt(i)] = 1;
} else {
freq[string.charCodeAt(i)] ++;
};
};
for (var i = 0; i < freq.length; i++){
if (freq[i] > 0){
qinsert(new node(freq[i], i, null, null));
};
};
while (nodes.length > 1){
qinsert(new_node(qremove(), qremove()));
};
build_code(nodes[0], codeString, 0);
};
function encode(string){
output = "";
for (var i = 0; i < string.length; i ++){
output += code[string.charCodeAt(i)];
};
return output;
output = "";
for (var i = 0; i < string.length; i ++){
output += code[string.charCodeAt(i)];
};
return output;
};
function decode(input){
output = "";
node = nodes[0];
for (var i = 0; i < input.length; i++){
if (input[i] == "0"){
node = node.left;
} else {
node = node.right;
};
if (node.c != -1){
output += String.fromCharCode(node.c);
node = nodes[0];
};
};
return output
output = "";
node = nodes[0];
for (var i = 0; i < input.length; i++){
if (input[i] == "0"){
node = node.left;
} else {
node = node.right;
};
if (node.c != -1){
output += String.fromCharCode(node.c);
node = nodes[0];
};
};
return output
};
@ -101,10 +101,10 @@ string = "this is an example of huffman encoding";
console.log("initial string: " + string);
init(string);
for (var i = 0; i < Object.keys(code).length; i++){
if (isNaN(code[Object.keys(code)[i]])){
} else {
console.log("'" + String.fromCharCode(Object.keys(code)[i]) + "'" + ": " + code[Object.keys(code)[i]]);
};
if (isNaN(code[Object.keys(code)[i]])){
} else {
console.log("'" + String.fromCharCode(Object.keys(code)[i]) + "'" + ": " + code[Object.keys(code)[i]]);
};
};
huffman = encode(string);

View file

@ -2,7 +2,7 @@
@interface HuffmanTree : NSObject {
int freq;
int freq;
}
-(instancetype)initWithFreq:(int)f;
@property (nonatomic, readonly) int freq;
@ -11,34 +11,34 @@
@implementation HuffmanTree
@synthesize freq; // the frequency of this tree
-(instancetype)initWithFreq:(int)f {
if (self = [super init]) {
freq = f;
}
return self;
if (self = [super init]) {
freq = f;
}
return self;
}
@end
const void *HuffmanRetain(CFAllocatorRef allocator, const void *ptr) {
return (__bridge_retained const void *)(__bridge id)ptr;
return (__bridge_retained const void *)(__bridge id)ptr;
}
void HuffmanRelease(CFAllocatorRef allocator, const void *ptr) {
(void)(__bridge_transfer id)ptr;
(void)(__bridge_transfer id)ptr;
}
CFComparisonResult HuffmanCompare(const void *ptr1, const void *ptr2, void *unused) {
int f1 = ((__bridge HuffmanTree *)ptr1).freq;
int f2 = ((__bridge HuffmanTree *)ptr2).freq;
if (f1 == f2)
return kCFCompareEqualTo;
else if (f1 > f2)
return kCFCompareGreaterThan;
else
return kCFCompareLessThan;
int f1 = ((__bridge HuffmanTree *)ptr1).freq;
int f2 = ((__bridge HuffmanTree *)ptr2).freq;
if (f1 == f2)
return kCFCompareEqualTo;
else if (f1 > f2)
return kCFCompareGreaterThan;
else
return kCFCompareLessThan;
}
@interface HuffmanLeaf : HuffmanTree {
char value; // the character this leaf represents
char value; // the character this leaf represents
}
@property (readonly) char value;
-(instancetype)initWithFreq:(int)f character:(char)c;
@ -47,16 +47,16 @@ CFComparisonResult HuffmanCompare(const void *ptr1, const void *ptr2, void *unus
@implementation HuffmanLeaf
@synthesize value;
-(instancetype)initWithFreq:(int)f character:(char)c {
if (self = [super initWithFreq:f]) {
value = c;
}
return self;
if (self = [super initWithFreq:f]) {
value = c;
}
return self;
}
@end
@interface HuffmanNode : HuffmanTree {
HuffmanTree *left, *right; // subtrees
HuffmanTree *left, *right; // subtrees
}
@property (readonly) HuffmanTree *left, *right;
-(instancetype)initWithLeft:(HuffmanTree *)l right:(HuffmanTree *)r;
@ -65,86 +65,86 @@ CFComparisonResult HuffmanCompare(const void *ptr1, const void *ptr2, void *unus
@implementation HuffmanNode
@synthesize left, right;
-(instancetype)initWithLeft:(HuffmanTree *)l right:(HuffmanTree *)r {
if (self = [super initWithFreq:l.freq+r.freq]) {
left = l;
right = r;
}
return self;
if (self = [super initWithFreq:l.freq+r.freq]) {
left = l;
right = r;
}
return self;
}
@end
HuffmanTree *buildTree(NSCountedSet *chars) {
CFBinaryHeapCallBacks callBacks = {0, HuffmanRetain, HuffmanRelease, NULL, HuffmanCompare};
CFBinaryHeapRef trees = CFBinaryHeapCreate(NULL, 0, &callBacks, NULL);
// initially, we have a forest of leaves
// one for each non-empty character
for (NSNumber *ch in chars) {
int freq = [chars countForObject:ch];
if (freq > 0)
CFBinaryHeapAddValue(trees, (__bridge const void *)[[HuffmanLeaf alloc] initWithFreq:freq character:(char)[ch intValue]]);
}
NSCAssert(CFBinaryHeapGetCount(trees) > 0, @"String must have at least one character");
// loop until there is only one tree left
while (CFBinaryHeapGetCount(trees) > 1) {
// two trees with least frequency
HuffmanTree *a = (__bridge HuffmanTree *)CFBinaryHeapGetMinimum(trees);
CFBinaryHeapRemoveMinimumValue(trees);
HuffmanTree *b = (__bridge HuffmanTree *)CFBinaryHeapGetMinimum(trees);
CFBinaryHeapRemoveMinimumValue(trees);
// put into new node and re-insert into queue
CFBinaryHeapAddValue(trees, (__bridge const void *)[[HuffmanNode alloc] initWithLeft:a right:b]);
}
HuffmanTree *result = (__bridge HuffmanTree *)CFBinaryHeapGetMinimum(trees);
CFRelease(trees);
return result;
CFBinaryHeapCallBacks callBacks = {0, HuffmanRetain, HuffmanRelease, NULL, HuffmanCompare};
CFBinaryHeapRef trees = CFBinaryHeapCreate(NULL, 0, &callBacks, NULL);
// initially, we have a forest of leaves
// one for each non-empty character
for (NSNumber *ch in chars) {
int freq = [chars countForObject:ch];
if (freq > 0)
CFBinaryHeapAddValue(trees, (__bridge const void *)[[HuffmanLeaf alloc] initWithFreq:freq character:(char)[ch intValue]]);
}
NSCAssert(CFBinaryHeapGetCount(trees) > 0, @"String must have at least one character");
// loop until there is only one tree left
while (CFBinaryHeapGetCount(trees) > 1) {
// two trees with least frequency
HuffmanTree *a = (__bridge HuffmanTree *)CFBinaryHeapGetMinimum(trees);
CFBinaryHeapRemoveMinimumValue(trees);
HuffmanTree *b = (__bridge HuffmanTree *)CFBinaryHeapGetMinimum(trees);
CFBinaryHeapRemoveMinimumValue(trees);
// put into new node and re-insert into queue
CFBinaryHeapAddValue(trees, (__bridge const void *)[[HuffmanNode alloc] initWithLeft:a right:b]);
}
HuffmanTree *result = (__bridge HuffmanTree *)CFBinaryHeapGetMinimum(trees);
CFRelease(trees);
return result;
}
void printCodes(HuffmanTree *tree, NSMutableString *prefix) {
NSCAssert(tree != nil, @"tree must not be nil");
if ([tree isKindOfClass:[HuffmanLeaf class]]) {
HuffmanLeaf *leaf = (HuffmanLeaf *)tree;
// print out character, frequency, and code for this leaf (which is just the prefix)
NSLog(@"%c\t%d\t%@", leaf.value, leaf.freq, prefix);
} else if ([tree isKindOfClass:[HuffmanNode class]]) {
HuffmanNode *node = (HuffmanNode *)tree;
// traverse left
[prefix appendString:@"0"];
printCodes(node.left, prefix);
[prefix deleteCharactersInRange:NSMakeRange([prefix length]-1, 1)];
// traverse right
[prefix appendString:@"1"];
printCodes(node.right, prefix);
[prefix deleteCharactersInRange:NSMakeRange([prefix length]-1, 1)];
}
NSCAssert(tree != nil, @"tree must not be nil");
if ([tree isKindOfClass:[HuffmanLeaf class]]) {
HuffmanLeaf *leaf = (HuffmanLeaf *)tree;
// print out character, frequency, and code for this leaf (which is just the prefix)
NSLog(@"%c\t%d\t%@", leaf.value, leaf.freq, prefix);
} else if ([tree isKindOfClass:[HuffmanNode class]]) {
HuffmanNode *node = (HuffmanNode *)tree;
// traverse left
[prefix appendString:@"0"];
printCodes(node.left, prefix);
[prefix deleteCharactersInRange:NSMakeRange([prefix length]-1, 1)];
// traverse right
[prefix appendString:@"1"];
printCodes(node.right, prefix);
[prefix deleteCharactersInRange:NSMakeRange([prefix length]-1, 1)];
}
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *test = @"this is an example for huffman encoding";
// read each character and record the frequencies
NSCountedSet *chars = [[NSCountedSet alloc] init];
int n = [test length];
for (int i = 0; i < n; i++)
[chars addObject:@([test characterAtIndex:i])];
// build tree
HuffmanTree *tree = buildTree(chars);
// print out results
NSLog(@"SYMBOL\tWEIGHT\tHUFFMAN CODE");
printCodes(tree, [NSMutableString string]);
NSString *test = @"this is an example for huffman encoding";
// read each character and record the frequencies
NSCountedSet *chars = [[NSCountedSet alloc] init];
int n = [test length];
for (int i = 0; i < n; i++)
[chars addObject:@([test characterAtIndex:i])];
// build tree
HuffmanTree *tree = buildTree(chars);
// print out results
NSLog(@"SYMBOL\tWEIGHT\tHUFFMAN CODE");
printCodes(tree, [NSMutableString string]);
}
return 0;
}

View file

@ -3,48 +3,48 @@ use strict;
# produce encode and decode dictionary from a tree
sub walk {
my ($node, $code, $h, $rev_h) = @_;
my ($node, $code, $h, $rev_h) = @_;
my $c = $node->[0];
if (ref $c) { walk($c->[$_], $code.$_, $h, $rev_h) for 0,1 }
else { $h->{$c} = $code; $rev_h->{$code} = $c }
my $c = $node->[0];
if (ref $c) { walk($c->[$_], $code.$_, $h, $rev_h) for 0,1 }
else { $h->{$c} = $code; $rev_h->{$code} = $c }
$h, $rev_h
$h, $rev_h
}
# make a tree, and return resulting dictionaries
sub mktree {
my (%freq, @nodes);
$freq{$_}++ for split '', shift;
@nodes = map([$_, $freq{$_}], keys %freq);
my (%freq, @nodes);
$freq{$_}++ for split '', shift;
@nodes = map([$_, $freq{$_}], keys %freq);
do { # poor man's priority queue
@nodes = sort {$a->[1] <=> $b->[1]} @nodes;
my ($x, $y) = splice @nodes, 0, 2;
push @nodes, [[$x, $y], $x->[1] + $y->[1]]
} while (@nodes > 1);
do { # poor man's priority queue
@nodes = sort {$a->[1] <=> $b->[1]} @nodes;
my ($x, $y) = splice @nodes, 0, 2;
push @nodes, [[$x, $y], $x->[1] + $y->[1]]
} while (@nodes > 1);
walk($nodes[0], '', {}, {})
walk($nodes[0], '', {}, {})
}
sub encode {
my ($str, $dict) = @_;
join '', map $dict->{$_}//die("bad char $_"), split '', $str
my ($str, $dict) = @_;
join '', map $dict->{$_}//die("bad char $_"), split '', $str
}
sub decode {
my ($str, $dict) = @_;
my ($seg, @out) = ("");
my ($str, $dict) = @_;
my ($seg, @out) = ("");
# append to current segment until it's in the dictionary
for (split '', $str) {
$seg .= $_;
my $x = $dict->{$seg} // next;
push @out, $x;
$seg = '';
}
die "bad code" if length($seg);
join '', @out
# append to current segment until it's in the dictionary
for (split '', $str) {
$seg .= $_;
my $x = $dict->{$seg} // next;
push @out, $x;
$seg = '';
}
die "bad code" if length($seg);
join '', @out
}
my $txt = 'this is an example for huffman encoding';

View file

@ -1,61 +0,0 @@
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

@ -1,37 +1,37 @@
huffman :-
L = 'this is an example for huffman encoding',
atom_chars(L, LA),
msort(LA, LS),
packList(LS, PL),
sort(PL, PLS),
build_tree(PLS, A),
coding(A, [], C),
sort(C, SC),
format('Symbol~t Weight~t~30|Code~n'),
maplist(print_code, SC).
L = 'this is an example for huffman encoding',
atom_chars(L, LA),
msort(LA, LS),
packList(LS, PL),
sort(PL, PLS),
build_tree(PLS, A),
coding(A, [], C),
sort(C, SC),
format('Symbol~t Weight~t~30|Code~n'),
maplist(print_code, SC).
build_tree([[V1|R1], [V2|R2]|T], AF) :-
V is V1 + V2,
A = [V, [V1|R1], [V2|R2]],
( T=[] -> AF=A ; sort([A|T], NT), build_tree(NT, AF) ).
V is V1 + V2,
A = [V, [V1|R1], [V2|R2]],
( T=[] -> AF=A ; sort([A|T], NT), build_tree(NT, AF) ).
coding([_A,FG,FD], Code, CF) :-
( is_node(FG) -> coding(FG, [0 | Code], C1)
; leaf_coding(FG, [0 | Code], C1) ),
( is_node(FD) -> coding(FD, [1 | Code], C2)
; leaf_coding(FD, [1 | Code], C2) ),
append(C1, C2, CF).
( is_node(FG) -> coding(FG, [0 | Code], C1)
; leaf_coding(FG, [0 | Code], C1) ),
( is_node(FD) -> coding(FD, [1 | Code], C2)
; leaf_coding(FD, [1 | Code], C2) ),
append(C1, C2, CF).
leaf_coding([FG,FD], Code, CF) :-
reverse(Code, CodeR),
CF = [[FG, FD, CodeR]] .
reverse(Code, CodeR),
CF = [[FG, FD, CodeR]] .
is_node([_V, _FG, _FD]).
print_code([N, Car, Code]):-
format('~w :~t~w~t~30|', [Car, N]),
forall(member(V, Code), write(V)),
nl.
format('~w :~t~w~t~30|', [Car, N]),
forall(member(V, Code), write(V)),
nl.
packList([], []).
packList([X], [[1,X]]) :- !.

View file

@ -4,74 +4,74 @@ Red [file: %huffy.red]
msg: "this is an example for huffman encoding"
;;map to collect leave knots per uniq character of message
m: make map! []
m: make map! []
knot: make object! [
left: right: none ;; pointer to left/right sibling
code: none ;; first holds char for debugging, later binary code
count: depth: 1 ;;occurence of character - length of branch
left: right: none ;; pointer to left/right sibling
code: none ;; first holds char for debugging, later binary code
count: depth: 1 ;;occurence of character - length of branch
]
;;-----------------------------------------
set-code: func ["recursive function to generate binary code sequence"
wknot
wcode [string!]] [
wknot
wcode [string!]] [
;;-----------------------------------------
either wknot/left = none [
wknot/code: wcode
] [
set-code wknot/left rejoin [wcode "1"]
set-code wknot/right rejoin [wcode "0"]
]
] ;;-- end func
either wknot/left = none [
wknot/code: wcode
] [
set-code wknot/left rejoin [wcode "1"]
set-code wknot/right rejoin [wcode "0"]
]
] ;;-- end func
;-------------------------------
merge-2knots: func ["function to merge 2 knots into 1 new"
t [block!]][
t [block!]][
;-------------------------------
nknot: copy knot ;; create new knot
nknot/count: t/1/count + t/2/count
nknot/right: t/1
nknot/left: t/2
nknot/depth: t/1/depth + 1
tab: remove/part t 2 ;; delete first 2 knots
insert t nknot ;; insert new generated knot
] ;;-- end func
nknot: copy knot ;; create new knot
nknot/count: t/1/count + t/2/count
nknot/right: t/1
nknot/left: t/2
nknot/depth: t/1/depth + 1
tab: remove/part t 2 ;; delete first 2 knots
insert t nknot ;; insert new generated knot
] ;;-- end func
;; count occurence of characters, save in map: m
foreach chr msg [
either k: select/case m chr [
k/count: k/count + 1
][
put/case m chr nknot: copy knot
nknot/code: chr
]
either k: select/case m chr [
k/count: k/count + 1
][
put/case m chr nknot: copy knot
nknot/code: chr
]
]
;; create sortable block (=tab) for use as prio queue
foreach k keys-of m [ append tab: [] :m/:k ]
foreach k keys-of m [ append tab: [] :m/:k ]
;; build tree
while [ 1 < length? tab][
sort/compare tab function [a b] [
a/count < b/count
or ( a/count = b/count and ( a/depth > b/depth ) )
]
merge-2knots tab ;; merge 2 knots with lowest count / max depth
sort/compare tab function [a b] [
a/count < b/count
or ( a/count = b/count and ( a/depth > b/depth ) )
]
merge-2knots tab ;; merge 2 knots with lowest count / max depth
]
set-code tab/1 "" ;; generate binary codes, save at leave knot
set-code tab/1 "" ;; generate binary codes, save at leave knot
;; display codes
foreach k sort keys-of m [
print [k " = " m/:k/code]
append codes: "" m/:k/code
print [k " = " m/:k/code]
append codes: "" m/:k/code
]
;; encode orig message string
foreach chr msg [
k: select/case m chr
append msg-new: "" k/code
k: select/case m chr
append msg-new: "" k/code
]
print [ "length of encoded msg " length? msg-new]
@ -83,7 +83,7 @@ prin "decoded: "
;; decode message (destructive! ):
while [ not empty? msg-new ][
foreach [k v] body-of m [
if t: find/match msg-new v/code [
if t: find/match/tail msg-new v/code [
prin k
msg-new: t
]

View file

@ -5,18 +5,18 @@ fcn buildHuffman(text){ //-->(encode dictionary, decode dictionary)
// build the tree, which is a list of lists of ...
tree:=ft.pump(List,fcn([(c,cnt)]){ //-->L( (cnt, ((sym,code))), ...)
L(cnt, L(L(c,"")))
}).copy(); // make it writable
}).copy(); // make it writable
while(tree.len()>1){ // fake up a [lame] priorty queue
tree=tree.sort(fcn(a,b){ a[0]>b[0] }); //prioritize high to low
a,b:=tree.pop(-2,2); //remove 2 least frequent symbols
mc:=fcn(n,c){ n[1] = c + n[1]; }; //(sym,code),"0"|"1"
a,b:=tree.pop(-2,2); //remove 2 least frequent symbols
mc:=fcn(n,c){ n[1] = c + n[1]; }; //(sym,code),"0"|"1"
a[1].apply2(mc,"0"); b[1].apply2(mc,"1"); // mc(a[1],"0")
tree.append( L(a[0]+b[0],a[1].extend(b[1])) ); //(a,b)-->new node
}//-->L(L(39, L( L(" ","000"),L("e","0010"),L("a","0011") ...
tree=tree[0][1].pump(List,fcn(i){ // flatten rather than traverse
if(T.isType(i))return(Void.Recurse,i,self.fcn); i });
if(T.isType(i))return(Void.Recurse,i,self.fcn); i });
encodeTable:=tree.toDictionary(); // symbol:Huffman code
decodeTable:=encodeTable.pump(Dictionary(),"reverse"); // code:symbol
return(encodeTable,decodeTable);