fork download
  1. compress=->bytes,verbose=false{
  2. wmax=4095
  3. dmax=255
  4. search=->pos{
  5. bestl,bestp=1,0
  6. (0..[wmax,pos-1].min).each{|i|
  7. matched = 0.step{|j|
  8. break j if j>=dmax || pos+j>=bytes.size || bytes[pos+j]!=bytes[pos+j-i-1]
  9. }
  10. next if matched<bestl||matched<2
  11. bestl=matched
  12. bestp=i
  13. }
  14. [bestl-1,bestp]
  15. }
  16. pools=[]
  17. pool=0
  18. pooledbit=0
  19. addpool=->len,pos{
  20. raise 'unexpected' unless len<=dmax && pos<=wmax
  21. addlen=[14,len.bit_length*2-1].min
  22. pool=(pool<<addlen)|(len&0x7f)
  23. pooledbit+=addlen
  24. ret=addlen
  25. addlen,bias=case pos
  26. when 0..3; [6,0]
  27. when 4..7; [7,4]
  28. when 8..31; [8,16]
  29. when 32..127; [9,64]
  30. else
  31. blen=pos.bit_length
  32. [blen+2, (blen-6) << blen]
  33. end
  34. pool=(pool<<addlen)|(pos+bias)
  35. pooledbit+=addlen
  36. ret+=addlen
  37. while pooledbit>=16
  38. sword=pool>>(pooledbit-16)
  39. pools.push(sword&0x7f,sword>>8)
  40. pooledbit-=16
  41. pool&=(1<<pooledbit)-1
  42. end
  43. ret
  44. }
  45. i=0
  46. elems=[]
  47. while i<bytes.size
  48. len,pos=search[i]
  49. warn "search @#{i} -> len,pos=#{len},#{pos}" if verbose
  50. if len==0
  51. elems.push([1,bytes[i]])
  52. i+=1
  53. else
  54. pbit=addpool[len,pos]
  55. elems.push([0,pbit])
  56. i+=len+1
  57. end
  58. end
  59. addpool[255,0]
  60. elems.push([0,14])
  61. ((-elems.size)%8).times{
  62. elems.push([0,0])
  63. }
  64. margin=0
  65. if pooledbit>0
  66. raise 'unexpected' unless pooledbit<16
  67. margin=16-pooledbit
  68. pool<<=margin
  69. pools.push(pool&0xff,pool>>8)
  70. end
  71. cbytes=[]
  72. pooledbit=0
  73. consume=->bit{
  74. pooledbit -= bit
  75. while pooledbit<16
  76. cbytes.push(*pools.shift(2))
  77. pooledbit+=16
  78. end
  79. }
  80. consume[0]
  81. elems.each_slice(8){|chunk|
  82. cbytes.push((chunk.map{|e| e[0] }*'').to_i(2))
  83. chunk.each{|(dtype,val)|
  84. if dtype==1
  85. cbytes.push(val)
  86. else
  87. consume[val]
  88. end
  89. }
  90. }
  91. warn "margin bit: #{margin}" if verbose
  92. cbytes
  93. }
  94.  
  95. rbytes = $<.flat_map{|line| line.scan(/\w\w/).map{|t| t.to_i(16) } }
  96. cbytes=compress[rbytes,true]
  97.  
  98. 0.step{|off|
  99. bytes=[]
  100. dobreak=false
  101. 16.times{|i|
  102. b=cbytes[off*16+i] or break
  103. bytes[i]=b
  104. } or dobreak=true
  105. break if bytes.size==0
  106. bstrs=[" "]*16
  107. bytes.each_with_index{|b,i| bstrs[i]="%02x" % b}
  108. puts (" %02x0: %s" % [off, bstrs.each_slice(2).map{|(s1,s2)| s1+s2 }*" "])
  109. break if dobreak
  110. }
Success #stdin #stdout #stderr 0.02s 8344KB
stdin
 7106 0100 3fff ffff 0100 0000 0000 0000
 0000 0000 0000 0000 0000 0000 0000 0000
 0000 0000 0000 0000 0000 0000 8301 0000
 0000 0000 0000 0000 0000 0000 0000 0000
 8000 011e 8225 0478 c0d5 001e 0000 1e00
stdout
    000: 1281 fc71 0601 003f ff40 085f 1909 8328
    010: 283f 4080 0001 1e82 fe25 0478 c0d5 001e
    020: 0000 80                                
stderr
search @0 -> len,pos=0,0
search @1 -> len,pos=0,0
search @2 -> len,pos=0,0
search @3 -> len,pos=0,0
search @4 -> len,pos=0,0
search @5 -> len,pos=0,0
search @6 -> len,pos=1,0
search @8 -> len,pos=1,5
search @10 -> len,pos=33,0
search @44 -> len,pos=0,0
search @45 -> len,pos=18,36
search @64 -> len,pos=0,0
search @65 -> len,pos=0,0
search @66 -> len,pos=0,0
search @67 -> len,pos=0,0
search @68 -> len,pos=0,0
search @69 -> len,pos=0,0
search @70 -> len,pos=0,0
search @71 -> len,pos=0,0
search @72 -> len,pos=0,0
search @73 -> len,pos=0,0
search @74 -> len,pos=0,0
search @75 -> len,pos=0,0
search @76 -> len,pos=1,66
search @78 -> len,pos=1,2
margin bit: 9