|Just another Perl shrine|
Fast - Compact That Stringby Limbic~Region (Chancellor)
|on Feb 09, 2012 at 21:13 UTC||Need Help??|
Limbic~Region has asked for the
wisdom of the Perl Monks concerning the following question:
I have millions of strings that are exactly 6 characters (bytes) long. Each position in the string can be one of 37 possible characters (space, 0-9 and A-Z). I need to very quickly compress these strings into the smallest space possible and also be able to expand them back again later as quickly as possible.
The implementation I have now uses 6 bits per character and compresses the string into 36 bits. I split the string in half (3 characters each) and use a hash look up to convert each half to a series of 1s and 0s. I concatenate the bitstrings together (with 4 bits of padding) and used pack('B*', $bitstr) to get from 6 bytes to 5.
I know that I can do better. 37 ^ 6 = 2_565_726_409 while 2 ^ 32 = 4_294_967_296. If I treated the string as a base 37 number, it would easily fit into a 32 bit integer (4 bytes). What I am at a loss for is how to quickly translate 0 into ' ' and 2_565_726_409 into 'ZZZZZZ';
My environment is perl 5.8.8 with no compiler so I am limited to pure perl modules only. What's the best that you can do?
Cheers - L~R