adaptive_huffman_coding.sf 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #!/usr/bin/ruby
  2. # Implementation of the Adaptive Huffman Coding.
  3. # See also:
  4. # https://rosettacode.org/wiki/huffman_coding
  5. func walk(Hash n, String s, Hash h) {
  6. if (n.has(:a)) {
  7. h{n{:a}} = s
  8. return nil
  9. }
  10. walk(n{:0}, s+'0', h) if n.has(:0)
  11. walk(n{:1}, s+'1', h) if n.has(:1)
  12. }
  13. func mktree_from_freq(Hash freqs) {
  14. var nodes = freqs.sort.flip.map_2d { |b,f|
  15. Hash(a => b, freq => f)
  16. }
  17. loop {
  18. nodes.sort_by!{|h| h{:freq} }
  19. var(x, y) = (nodes.shift, nodes.shift)
  20. if (defined(x)) {
  21. if (defined(y)) {
  22. nodes << Hash(:0 => x, :1 => y, :freq => x{:freq}+y{:freq})
  23. }
  24. else {
  25. nodes << Hash(:0 => x, :freq => x{:freq})
  26. }
  27. }
  28. nodes.len > 1 || break
  29. }
  30. var n = nodes.first
  31. walk(n, '', n{:tree} = Hash())
  32. return n
  33. }
  34. func encode(Array bytes, Array alphabet) {
  35. var freq = alphabet.freq
  36. var enc = []
  37. bytes.each {|b|
  38. var tree = mktree_from_freq(freq)
  39. ++freq{b}
  40. enc << tree{:tree}{b}
  41. }
  42. return enc.join
  43. }
  44. func decode(String enc, Array alphabet) {
  45. var out = []
  46. var prefix = ''
  47. var freq = alphabet.freq
  48. var tree = mktree_from_freq(freq){:tree}.flip
  49. enc.each {|bit|
  50. prefix += bit
  51. if (tree.has(prefix)) {
  52. out << tree{prefix}
  53. ++freq{tree{prefix}}
  54. tree = mktree_from_freq(freq){:tree}.flip
  55. prefix = ''
  56. }
  57. }
  58. return out
  59. }
  60. var text = "this is an example for huffman encoding"
  61. var bytes = text.bytes
  62. say var enc = encode(bytes, bytes.uniq)
  63. say var dec = decode(enc, bytes.uniq).pack('C*')
  64. assert_eq(dec, text)