Skip to content

Instantly share code, notes, and snippets.

@John-Lin
Last active March 3, 2016 15:17
Show Gist options
  • Save John-Lin/4b8074c8261fc01a3bf3 to your computer and use it in GitHub Desktop.
Save John-Lin/4b8074c8261fc01a3bf3 to your computer and use it in GitHub Desktop.
Assignment: Data Packer
require 'minitest/autorun'
require './short_string_packer'
def random_string
[*'a'..'z'].sample(rand(1..12)).join
end
test_cases = %w(a z asdf abcdefghijkl aaaaaazzzzzz)
describe 'Test whether packing methods are valid' do
it 'should pack strings into numbers' do
packed = ShortStringPacker.pack(random_string)
packed.must_be_instance_of Fixnum
end
it 'should unpack numbers back into strings' do
rand_packed = (rand * 10000000).to_i
str = ShortStringPacker.unpack(rand_packed)
str.must_be_instance_of String
end
end
describe 'Test whether roundtripping of packing works' do
test_cases.each do |str|
it "should pack and unpack \'#{str}\' correctly" do
packed = ShortStringPacker.pack(str)
unpacked = ShortStringPacker.unpack(packed)
unpacked.must_equal str
end
end
end
class ShortStringPacker
## Packs a short string into a Fixnum
# Arguments:
# str - String object
# Returns: a Fixnum object
def self.pack(str)
puts 'Packing string: ' + str
ret = []
char_len = str.length
str.each_char do |c|
bits = ((c.ord - 96) << ((char_len-1) * 5))
ret << bits
char_len -= 1
end
inject_or = ret.inject(0, :|)
# showing
# ret.each do |p|
# puts p.to_s(2)
# end
# p ret
inject_or
end
## Unpacks a Fixnum from pack() method into a short string
# Arguments:
# packed - a Fixnum object
# Returns: a String object
def self.unpack(packed)
puts 'Unpacking'
len = packed.to_s(2).length
r = len % 5
q = len / 5
if r == 0
if q > 0
actual_len = len
else
actual_len = 0
end
else
actual_len = len + (5-r)
end
# puts 'length: ' + actual_len.to_s
mask = 0b11111 << (actual_len - 5)
# puts 'mask:' + mask.to_s(2)
ret = []
until mask == 0
bits = (packed & mask)
ret << bits
mask = mask >> 5
end
# showing
# ret.each do |p|
# puts p.to_s(2)
# end
# p ret
str = []
i = 0
ret.each do |p|
i += 1
seg = p >> (actual_len - (5 * i))
char = (seg.to_i + 96).chr
str << char
end
str.join
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment