Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compress a bitstring using Ruby

For a Bioinformatics project I need to compress a large amount of bitstrings (strings containing only 0's and 1's) in Ruby to smaller strings to reduce memory usage.

So ideally a string like "0001010010010010010001001" becomes something like "2a452c66". I first used MD5 hashes until I read something about possible collisions which I would like to avoid.

I have tried a lot of different combinations of unpack, to_i, to_s, etc, but can't seem to get the right combination.

The solution should:

  • Keep any leading 0's.
  • Be reversible.
  • Compress (obviously).
  • And the output should avoid strange characters. Preferably I would like to stay in the alphanumeric space. (a-zA-Z0-9).

Thanks!

like image 742
jlmr Avatar asked Sep 24 '26 19:09

jlmr


1 Answers

Try:

FORMAT = '%0.*b'

bitmask = "0001010010010010010001001"
bitmask.to_i(2) # => 2696329
hexval = bitmask.to_i(2).to_s(16) # => "292489"
FORMAT % [bitmask.size, hexval.to_i(16)] # => "0001010010010010010001001"

What it's doing is:

  • to_i(2) converts the string from binary to its integer value just to show what's happening.
  • to_i(2).to_s(16) converts it to its hexadecimal representation as a string.
  • FORMAT contains a printf format string saying to convert the passed in value into its binary string representation (%b) with leading 0 bytes (%0b) for an unknown length (%0.*b) which it gets from the first parameter passed (bitmask.size).

Here's another example using a longer bitmask:

bitmask = "11011110101011011011111011101111"

hexval = bitmask.to_i(2).to_s(16) # => "deadbeef"
FORMAT % [bitmask.size, hexval.to_i(16)] # => "11011110101011011011111011101111"

And longer still:

bitmask = "1101111010101101101111101110111111111110111011011010110111011010"

hexval = bitmask.to_i(2).to_s(16) # => "deadbeeffeedadda"
FORMAT % [bitmask.size, hexval.to_i(16)] # => "1101111010101101101111101110111111111110111011011010110111011010"
like image 188
the Tin Man Avatar answered Sep 27 '26 12:09

the Tin Man