huffman_coding.sf 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #!/usr/bin/ruby
  2. # https://rosettacode.org/wiki/huffman_coding
  3. func walk(Hash n, String s, Hash h) {
  4. if (n.has(:a)) {
  5. h{n{:a}} = s
  6. printf("%3s: %s\n", n{:a}, s)
  7. return nil
  8. }
  9. walk(n{:0}, s+'0', h) if n.has(:0)
  10. walk(n{:1}, s+'1', h) if n.has(:1)
  11. }
  12. func make_tree(Array bytes) {
  13. var nodes = bytes.freq.sort.map_2d { |b,f|
  14. Hash(a => b, freq => f)
  15. }
  16. loop {
  17. nodes.sort_by!{|h| h{:freq} }
  18. var(x, y) = (nodes.shift, nodes.shift)
  19. if (defined(x)) {
  20. if (defined(y)) {
  21. nodes << Hash(:0 => x, :1 => y, :freq => x{:freq}+y{:freq})
  22. }
  23. else {
  24. nodes << Hash(:0 => x, :freq => x{:freq})
  25. }
  26. }
  27. nodes.len > 1 || break
  28. }
  29. var n = nodes.first
  30. walk(n, '', n{:tree} = Hash())
  31. return n
  32. }
  33. func encode(bytes, t) {
  34. t = t{:tree}
  35. bytes.map { t{_} }.join
  36. }
  37. func decode(enc, tree) {
  38. var out = []
  39. var prefix = ''
  40. enc.each {|bit|
  41. prefix += bit
  42. if (tree.has(prefix)) {
  43. out << tree{prefix}
  44. prefix = ''
  45. }
  46. }
  47. return out
  48. }
  49. var text = "this is an example for huffman encoding"
  50. var bytes = text.bytes
  51. var tree = make_tree(bytes)
  52. var enc = encode(bytes, tree)
  53. say enc
  54. say decode(enc, tree{:tree}.flip).decode('utf8')