A few days ago I was thinking about all those link shortening sites and wondered how easy it would be to compress a base-10 number like 1,234,567,890 to something much smaller like 1LY7VK. Here’s what I came up with:

``````class IntegerCompressor

CompressionCharacterSet = %w(0 1 2 3 4 5 6 7 8 9
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z)

def self.to_base
CompressionCharacterSet.length
end

def self.compress(number_to_convert)
digits_needed = Math.log(number_to_convert, IntegerCompressor.to_base).floor + 1
compressed_number_string = ''
previous_remainder = number_to_convert
(digits_needed-1).downto(0) do |power|
r=previous_remainder.divmod(IntegerCompressor.to_base**power)
compressed_number_string << CompressionCharacterSet[r]
previous_remainder = r
end
compressed_number_string
end

def self.decompress(compressed_number)
power = 0
base_10_integer = 0
compressed_number.to_s.reverse.each_char do |digit|
base_10_integer += ((IntegerCompressor.to_base**power)*CompressionCharacterSet.index(digit))
power+=1
end
base_10_integer
end

end
``````

It seems to work:

``````\$ irb
>> require '/path/to/file/integer_compressor.rb'
=> true
>> IntegerCompressor.compress 1234567890
=> "1LY7VK"
>> IntegerCompressor.decompress "1LY7VK"
=> 1234567890
``````

If anyone has a more elegant solution, I’d be curious to see it.

(Thanks to Tamara for the log refresher.)