Created
July 24, 2012 20:35
-
-
Save lfborjas/3172495 to your computer and use it in GitHub Desktop.
Compresses a string using the literal approach to huffman encoding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def freq_table(str) | |
str.each_char.inject(Hash.new(0)) do |table, char| | |
table[char] += 1 | |
table | |
end.sort_by(&:last).reverse | |
end | |
def build_tree(freq_table) | |
until freq_table.size == 1 | |
less_frequent = 2.times.map{ freq_table.pop } | |
left, right = less_frequent | |
new_node = [ | |
less_frequent.map(&:first).join(","), | |
left, right, | |
less_frequent.map(&:last).inject(:+) | |
] | |
freq_table.push new_node | |
end | |
freq_table.first | |
end | |
def draw_tree(tree) | |
chars = tree.shift | |
freq = tree.pop | |
left, right = tree | |
label = %Q{"{#{chars.gsub(/\s+/, "_")}}:#{freq}"} | |
if [left, right].all?(&:nil?) | |
label | |
else | |
"#{label}->#{draw_tree(left)};#{label}->#{draw_tree(right)}" | |
end | |
end | |
def draw(dot) | |
File.open("dotit", 'w') do |f| | |
f.write("digraph{#{dot}}") | |
end | |
`dot -Tpng dotit -o dotted.png && open dotted.png` | |
end | |
def encode(table, tree, acum = "") | |
chars = tree.shift | |
freq = tree.pop | |
left, right = tree | |
unless [left, right].all?(&:nil?) | |
encode table, left, acum + "0" | |
encode table, right, acum + "1" | |
else | |
table[chars] = acum | |
end | |
end | |
def huffman_codes(tree) | |
codes = {} | |
encode(codes, tree) | |
codes | |
end | |
def compress(str) | |
tree = build_tree(freq_table(str)) | |
draw(draw_tree(tree)) | |
codes = huffman_codes(build_tree(freq_table(str))) | |
puts "The huffman codes are: #{codes.inspect}" | |
str.each_char.map do |char| | |
codes[char] | |
end.join("") | |
end | |
puts "The compressed string is", compress(ARGV.pop) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment