From: Karl Czisch Date: 2006-09-12T04:52:48+09:00 Subject: [QUIZ][SOLUTION] Secret Agent 00111 (#94) --=-G3ysep+M9+Uyx8QCd/kj Content-Type: text/plain Content-Transfer-Encoding: 7bit Hi, here is my solution (00111_gizmo.rb) Karl #################################### require 'stringio' class SecretAgent00111CommunicationGizmo class UndefinedRLE < StandardError end private class Rle def initialize @data = [] @count = 0 end def <<(event) if event @count += 1 else @data << @count @count = 0 end end def get @count == 0 ? @data : nil end end class UnRle def initialize @data = [] end attr_reader :data def <<(count) count.times { @data << true } @data << false end end public class Encoder < Rle def initialize(exponent, output) super() @output = output @exponent = exponent @byte = 0 @byte_bit = 0x80 insert @exponent, 8 end def <<(event) super(event) while count = @data.shift (count >> @exponent).times { insert 1 } insert 0 insert count, @exponent end end def finish self << false insert 1 while @byte_bit != 0x80 end private def insert(num, bits = 1) (bits-1).downto(0) do |n| @byte |= @byte_bit if num[n] == 1 if (@byte_bit >>= 1) == 0 @output.putc @byte @byte_bit = 0x80 @byte = 0 end end end end class Decoder < UnRle def initialize(input) super() @exponent = 0 @input = input @count = 0 @remainder_bit = 0 end def exponent decode @exponent end def read decode data = @data @data = [] data end private def decode while byte = @input.getc if @exponent == 0 @exponent = byte else insert byte end end end def insert(byte) 7.downto(0) do |n| if @remainder_bit == 0 if byte[n] == 1 @count += 1 << @exponent else @remainder_bit = 1 << (@exponent - 1) end else @count += @remainder_bit if byte[n] == 1 if (@remainder_bit >>= 1) == 0 self.<<(@count) @count = 0 end end end end end def SecretAgent00111CommunicationGizmo.rle(arr) rle = Rle.new arr.each do |event| rle << event end out = rle.get raise UndefinedRLE, "undefined rle" unless out and not out.empty? out end def SecretAgent00111CommunicationGizmo.unrle(arr) unrle = UnRle.new arr.each do |count| unrle << count end unrle.data end def SecretAgent00111CommunicationGizmo.encode(arr, exp) io = StringIO.new encoder = Encoder.new(exp, io) arr.each do |event| encoder << event end encoder.finish io.string end def SecretAgent00111CommunicationGizmo.decode(bits) io = StringIO.new(bits) decoder = Decoder.new(io) arr = decoder.read arr.pop if arr.last == false arr end end --=-G3ysep+M9+Uyx8QCd/kj--