Huffman coding: Difference between revisions

m
→‎{{header|Phix}}: added syntax colouring, made p2js compatible
No edit summary
m (→‎{{header|Phix}}: added syntax colouring, made p2js compatible)
Line 4,581:
=={{header|Phix}}==
{{trans|Lua}}
<!--<lang Phix>(phixonline)-->
<lang Phix>function store_nodes(object key, object data, integer nodes)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
setd({data,key},0,nodes)
<span style="color: #008080;">function</span> <span style="color: #000000;">store_nodes</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
return 1
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">({</span><span style="color: #000000;">data</span><span style="color: #0000FF;">,</span><span style="color: #000000;">key</span><span style="color: #0000FF;">},</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
constant r_store_nodes = routine_id("store_nodes")
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
 
function build_freqtable(string data)
<span style="color: #008080;">function</span> <span style="color: #000000;">build_freqtable</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">)</span>
integer freq = new_dict(),
<span style="color: #004080;">integer</span> <span style="color: #000000;">freq</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">(),</span>
nodes = new_dict()
<span style="color: #000000;">nodes</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
for i=1 to length(data) do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
integer di = data[i]
<span style="color: #004080;">integer</span> <span style="color: #000000;">di</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
setd(di,getd(di,freq)+1,freq)
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">di</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">di</span><span style="color: #0000FF;">,</span><span style="color: #000000;">freq</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
traverse_dict(r_store_nodes, nodes, freq)
<span style="color: #7060A8;">traverse_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">store_nodes</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nodes</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
destroy_dict(freq)
<span style="color: #7060A8;">destroy_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
return nodes
<span style="color: #008080;">return</span> <span style="color: #000000;">nodes</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function build_hufftree(integer nodes)
<span style="color: #008080;">function</span> <span style="color: #000000;">build_hufftree</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
sequence lkey, rkey, node
<span style="color: #004080;">sequence</span> <span style="color: #000000;">node</span>
integer lfreq, rfreq
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
while true do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lkey</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_partial_key</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span><span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
lkey = getd_partial_key({0,0},nodes)
<span style="color: #004080;">integer</span> <span style="color: #000000;">lfreq</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lkey</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
lfreq = lkey[1]
<span style="color: #7060A8;">deld</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lkey</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
deld(lkey,nodes)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rkey</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_partial_key</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span><span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
rkey = getd_partial_key({0,0},nodes)
<span style="color: #004080;">integer</span> <span style="color: #000000;">rfreq</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rkey</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
rfreq = rkey[1]
<span style="color: #7060A8;">deld</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rkey</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
deld(rkey,nodes)
<span style="color: #000000;">node</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">lfreq</span><span style="color: #0000FF;">+</span><span style="color: #000000;">rfreq</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">lkey</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rkey</span><span style="color: #0000FF;">}}</span>
node = {lfreq+rfreq,{lkey,rkey}}
 
<span style="color: #008080;">if</span> <span style="color: #7060A8;">dict_size</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nodes</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if dict_size(nodes)=0 then exit end if
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
setd(node,0,nodes)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end while
<span style="color: #7060A8;">destroy_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
destroy_dict(nodes)
<span style="color: #008080;">return</span> <span style="color: #000000;">node</span>
return node
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
end function
<span style="color: #008080;">procedure</span> <span style="color: #000000;">build_huffcodes</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">bits</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
procedure build_huffcodes(object node, string bits, integer d)
<span style="color: #0000FF;">{</span><span style="color: #004080;">integer</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">node</span>
{integer freq, object data} = node
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
if sequence(data) then
<span style="color: #000000;">build_huffcodes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">&</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
build_huffcodes(data[1],bits&'0',d)
<span style="color: #000000;">build_huffcodes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">&</span><span style="color: #008000;">'1'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
build_huffcodes(data[2],bits&'1',d)
<span style="color: #008080;">else</span>
else
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">freq</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">},</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
setd(data,{freq,bits},d)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
end procedure
 
<span style="color: #008080;">function</span> <span style="color: #000000;">print_huffcode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*user_data*/</span><span style="color: #0000FF;">)</span>
function print_huffcode(integer key, sequence data, integer /*user_data*/)
<span style="color: #0000FF;">{</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">data</span>
printf(1,"'%c' [%d] %s\n",key&data)
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"'%c' [%d] %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">})</span>
return 1
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant r_print_huffcode = routine_id("print_huffcode")
 
<span style="color: #008080;">procedure</span> <span style="color: #000000;">print_huffcodes</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
procedure print_huffcodes(integer d)
<span style="color: #7060A8;">traverse_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">print_huffcode</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
traverse_dict(r_print_huffcode, 0, d)
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
end procedure
 
<span style="color: #008080;">function</span> <span style="color: #000000;">invert_huffcode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">rd</span><span style="color: #0000FF;">)</span>
function invert_huffcode(integer key, sequence data, integer rd)
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rd</span><span style="color: #0000FF;">)</span>
setd(data[2],key,rd)
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
return 1
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
end function
constant r_invert_huffcode = routine_id("invert_huffcode")
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">)</span>
 
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
procedure main(string data)
<span style="color: #004080;">integer</span> <span style="color: #000000;">nodes</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">build_freqtable</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">)</span>
if length(data)<2 then ?9/0 end if
<span style="color: #004080;">sequence</span> <span style="color: #000000;">huff</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">build_hufftree</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nodes</span><span style="color: #0000FF;">)</span>
integer nodes = build_freqtable(data)
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
sequence huff = build_hufftree(nodes)
<span style="color: #000000;">build_huffcodes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">huff</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
integer d = new_dict()
<span style="color: #000000;">print_huffcodes</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
build_huffcodes(huff, "", d)
print_huffcodes(d)
<span style="color: #004080;">string</span> <span style="color: #000000;">encoded</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
 
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
string encoded = ""
<span style="color: #000000;">encoded</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
for i=1 to length(data) do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
encoded &= getd(data[i],d)[2]
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">shorten</span><span style="color: #0000FF;">(</span><span style="color: #000000;">encoded</span><span style="color: #0000FF;">)</span>
end for
?encoded
<span style="color: #004080;">integer</span> <span style="color: #000000;">rd</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">traverse_dict</span><span style="color: #0000FF;">(</span><span style="color: #000000;">invert_huffcode</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rd</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
integer rd = new_dict()
<span style="color: #004080;">string</span> <span style="color: #000000;">decoded</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
traverse_dict(r_invert_huffcode, rd, d)
<span style="color: #004080;">integer</span> <span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
string decoded = ""
<span style="color: #008080;">while</span> <span style="color: #000000;">done</span><span style="color: #0000FF;"><</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">encoded</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
integer done = 0
<span style="color: #004080;">string</span> <span style="color: #000000;">key</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
while done<length(encoded) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">node</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
string key = ""
<span style="color: #008080;">while</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
integer node = 0
<span style="color: #000000;">done</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
while node=0 do
<span style="color: #000000;">key</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">encoded</span><span style="color: #0000FF;">[</span><span style="color: #000000;">done</span><span style="color: #0000FF;">]</span>
done += 1
<span style="color: #000000;">node</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rd</span><span style="color: #0000FF;">)</span>
key &= encoded[done]
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
node = getd_index(key, rd)
<span style="color: #000000;">decoded</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">getd_by_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rd</span><span style="color: #0000FF;">)</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
decoded &= getd_by_index(node,rd)
<span style="color: #0000FF;">?</span><span style="color: #000000;">decoded</span>
end while
?decoded
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
 
end procedure
<span style="color: #000000;">main</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"this is an example for huffman encoding"</span><span style="color: #0000FF;">)</span>
<!--</lang>-->
main("this is an example for huffman encoding")</lang>
{{out}}
<pre>
Line 4,700:
'u' [1] 10001
'x' [1] 11110
"10000111111110010010...01101011111000001100 (157 digits)"
"1000011111111001001011110010010110010001011100111101001001001110011011100101110100110111110111111100011101110100101001000101110000001010001101011111000001100"
"this is an example for huffman encoding"
</pre>
7,805

edits