// Builds a HuffmanTree from a byte histogram sclass HuffmanTreeMaker { delegate Node, Branch, Leaf to HuffmanTree. // output gettable new HuffmanTree tree; // internal new TreeSet pool; // combinable trees sorted by incidence (symbol frequency) int indexCounter; // counter to keep order deterministic class Head is Comparable { int index = indexCounter++; settable Node node; settable double freq; // using floating point to keep things futureproof // sort by frequency first, then by index (order of creation) public int compareTo(Head h) { if (this == h) ret 0; var c = cmp(freq, h.freq); if (c != 0) ret c; ret cmp(index, h.index); } toString { ret freq + "x " + node; } } // histogram[0] = incidence for byte 00 // histogram[1] = incidence for byte 01 // etc. up to 255 (or less) selfType importByteHistogram(int[] histogram) { int n = l(histogram); for i to n: { double freq = histogram[i]; if (freq != 0) pool.add(new Head().freq(freq).node(tree.new Leaf(i))); } this; } run { while ping (l(pool) > 1) { var it = iterator(pool); var a = it.next(); it.remove(); var b = it.next(); it.remove(); //print("Merging frequencies: " + commaCombine(a.freq, b.freq)); var newHead = new Head() .freq(a.freq+b.freq) .node(tree.new Branch().zero(b.node).one(a.node)); //print("Merging: " + commaCombine(a, b) + " to " + newHead); pool.add(newHead); } } HuffmanTree get() { run(); if (nempty(pool)) tree.root(popFirst(pool).node()); ret tree; } }