Hi, here's my solution. It's based on strings of "1"s and "0"s, so the encoding can be done mainly with a format string ("%0#{@exponent+1}B") and the decoding with regular expressions. Regards, Boris ### 00111_gizmo.rb require 'stringio' module SecretAgent00111CommunicationGizmo class ExponentUndefined < Exception end class UndefinedRLE < Exception end def self.decode data events = Decoder.new(StringIO.new(data)).read events.pop # remove last false events end def self.encode events, exponent io = StringIO.new e = Encoder.new(exponent, io) events.each do |result| e << result end e.finish io.string end def self.rle events raise UndefinedRLE.new if events.size == 0 rl = [] truevals = 0 events.each do |result| if result truevals += 1 else rl << truevals truevals = 0 end end raise UndefinedRLE.new if truevals != 0 rl end def self.unrle rl events = [] rl.each {|n| events += [true]*n + [false]} events end class Encoder def initialize exponent, io @exponent = exponent @io = io @events = [] @bits = '' @io << exponent.chr end def << result @events << result if result == false encode_events end end def encode_events n = @events.size - 1 @events = [] @bits << "1" * (n / 2**@exponent) @bits << "%0#{@exponent+1}B" % (n % 2**@exponent) flush_bytes end def flush_bytes # write every 8 bits to the stream: @bits.gsub!(/[01]{8}/) do |byte| @io << byte.to_i(2).chr '' end end def finish @events << false encode_events # fill up remaining byte with "1"s: rest = @bits.size % 8 if rest != 0 @bits << "1" * (8 - rest) end flush_bytes end end class Decoder def bits(string) string.unpack("B*")[0] end def initialize io @io = io @exponent = nil @bits = '' @t = @n = nil end def exponent return @exponent if @exponent e = @io.getc if e @exponent = e else raise ExponentUndefined.new end @exponent end def add_events n = @n n += @t * 2**exponent if @t @t = @n = nil @events += SecretAgent00111CommunicationGizmo.unrle([n]) end def decode_bits loop do found = false if @bits =~ /^(1+)0/ @t = $1.size @bits.sub!(/^(1+)/, '') found = true end re = Regexp.new("^0([01]{#{exponent}})") if @bits =~ re @n = $1.to_i(2) @bits.sub!(re, '') add_events found = true end return unless found end end def read @events = [] begin exponent data = @io.read @bits += bits(data) decode_bits rescue ExponentUndefined # exponent not available yet in stream, try again later end @events end end end