compress=->bytes,verbose=false{
wmax=4095
dmax=255
search=->pos{
bestl,bestp=1,0
(0..[wmax,pos-1].min).each{|i|
matched = 0.step{|j|
break j if j>=dmax || pos+j>=bytes.size || bytes[pos+j]!=bytes[pos+j-i-1]
}
next if matched<bestl||matched<2
bestl=matched
bestp=i
}
[bestl-1,bestp]
}
pools=[]
pool=0
pooledbit=0
addpool=->len,pos{
raise 'unexpected' unless len<=dmax && pos<=wmax
addlen=[14,len.bit_length*2-1].min
pool=(pool<<addlen)|(len&0x7f)
pooledbit+=addlen
ret=addlen
addlen,bias=case pos
when 0..3; [6,0]
when 4..7; [7,4]
when 8..31; [8,16]
when 32..127; [9,64]
else
blen=pos.bit_length
[blen+2, (blen-6) << blen]
end
pool=(pool<<addlen)|(pos+bias)
pooledbit+=addlen
ret+=addlen
while pooledbit>=16
sword=pool>>(pooledbit-16)
pools.push(sword&0x7f,sword>>8)
pooledbit-=16
pool&=(1<<pooledbit)-1
end
ret
}
i=0
elems=[]
while i<bytes.size
len,pos=search[i]
warn "search @#{i} -> len,pos=#{len},#{pos}" if verbose
if len==0
elems.push([1,bytes[i]])
i+=1
else
pbit=addpool[len,pos]
elems.push([0,pbit])
i+=len+1
end
end
addpool[255,0]
elems.push([0,14])
((-elems.size)%8).times{
elems.push([0,0])
}
margin=0
if pooledbit>0
raise 'unexpected' unless pooledbit<16
margin=16-pooledbit
pool<<=margin
pools.push(pool&0xff,pool>>8)
end
cbytes=[]
pooledbit=0
consume=->bit{
pooledbit -= bit
while pooledbit<16
cbytes.push(*pools.shift(2))
pooledbit+=16
end
}
consume[0]
elems.each_slice(8){|chunk|
cbytes.push((chunk.map{|e| e[0] }*'').to_i(2))
chunk.each{|(dtype,val)|
if dtype==1
cbytes.push(val)
else
consume[val]
end
}
}
warn "margin bit: #{margin}" if verbose
cbytes
}
rbytes = $<.flat_map{|line| line.scan(/\w\w/).map{|t| t.to_i(16) } }
cbytes=compress[rbytes,true]
0.step{|off|
bytes=[]
dobreak=false
16.times{|i|
b=cbytes[off*16+i] or break
bytes[i]=b
} or dobreak=true
break if bytes.size==0
bstrs=[" "]*16
bytes.each_with_index{|b,i| bstrs[i]="%02x" % b}
puts (" %02x0: %s" % [off, bstrs.each_slice(2).map{|(s1,s2)| s1+s2 }*" "])
break if dobreak
}
Y29tcHJlc3M9LT5ieXRlcyx2ZXJib3NlPWZhbHNlewogIHdtYXg9NDA5NQogIGRtYXg9MjU1CiAgc2VhcmNoPS0+cG9zewogICAgYmVzdGwsYmVzdHA9MSwwCiAgICAoMC4uW3dtYXgscG9zLTFdLm1pbikuZWFjaHt8aXwKICAgICAgbWF0Y2hlZCA9IDAuc3RlcHt8anwKICAgICAgICBicmVhayBqIGlmIGo+PWRtYXggfHwgcG9zK2o+PWJ5dGVzLnNpemUgfHwgYnl0ZXNbcG9zK2pdIT1ieXRlc1twb3Mrai1pLTFdCiAgICAgIH0KICAgICAgbmV4dCBpZiBtYXRjaGVkPGJlc3RsfHxtYXRjaGVkPDIKICAgICAgYmVzdGw9bWF0Y2hlZAogICAgICBiZXN0cD1pCiAgICB9CiAgICBbYmVzdGwtMSxiZXN0cF0KICB9CiAgcG9vbHM9W10KICBwb29sPTAKICBwb29sZWRiaXQ9MAogIGFkZHBvb2w9LT5sZW4scG9zewogICAgcmFpc2UgJ3VuZXhwZWN0ZWQnIHVubGVzcyBsZW48PWRtYXggJiYgcG9zPD13bWF4CiAgICBhZGRsZW49WzE0LGxlbi5iaXRfbGVuZ3RoKjItMV0ubWluCiAgICBwb29sPShwb29sPDxhZGRsZW4pfChsZW4mMHg3ZikKICAgIHBvb2xlZGJpdCs9YWRkbGVuCiAgICByZXQ9YWRkbGVuCiAgICBhZGRsZW4sYmlhcz1jYXNlIHBvcwogICAgd2hlbiAwLi4zOyBbNiwwXQogICAgd2hlbiA0Li43OyBbNyw0XQogICAgd2hlbiA4Li4zMTsgWzgsMTZdCiAgICB3aGVuIDMyLi4xMjc7IFs5LDY0XQogICAgZWxzZQogICAgICBibGVuPXBvcy5iaXRfbGVuZ3RoCiAgICAgIFtibGVuKzIsIChibGVuLTYpIDw8IGJsZW5dCiAgICBlbmQKICAgIHBvb2w9KHBvb2w8PGFkZGxlbil8KHBvcytiaWFzKQogICAgcG9vbGVkYml0Kz1hZGRsZW4KICAgIHJldCs9YWRkbGVuCiAgICB3aGlsZSBwb29sZWRiaXQ+PTE2CiAgICAgIHN3b3JkPXBvb2w+Pihwb29sZWRiaXQtMTYpCiAgICAgIHBvb2xzLnB1c2goc3dvcmQmMHg3Zixzd29yZD4+OCkKICAgICAgcG9vbGVkYml0LT0xNgogICAgICBwb29sJj0oMTw8cG9vbGVkYml0KS0xCiAgICBlbmQKICAgIHJldAogIH0KICBpPTAKICBlbGVtcz1bXQogIHdoaWxlIGk8Ynl0ZXMuc2l6ZQogICAgbGVuLHBvcz1zZWFyY2hbaV0KICAgIHdhcm4gInNlYXJjaCBAI3tpfSAtPiBsZW4scG9zPSN7bGVufSwje3Bvc30iIGlmIHZlcmJvc2UKICAgIGlmIGxlbj09MAogICAgICBlbGVtcy5wdXNoKFsxLGJ5dGVzW2ldXSkKICAgICAgaSs9MQogICAgZWxzZQogICAgICBwYml0PWFkZHBvb2xbbGVuLHBvc10KICAgICAgZWxlbXMucHVzaChbMCxwYml0XSkKICAgICAgaSs9bGVuKzEKICAgIGVuZAogIGVuZAogIGFkZHBvb2xbMjU1LDBdCiAgZWxlbXMucHVzaChbMCwxNF0pCiAgKCgtZWxlbXMuc2l6ZSklOCkudGltZXN7CiAgICBlbGVtcy5wdXNoKFswLDBdKQogIH0KICBtYXJnaW49MAogIGlmIHBvb2xlZGJpdD4wCiAgICByYWlzZSAndW5leHBlY3RlZCcgdW5sZXNzIHBvb2xlZGJpdDwxNgogICAgbWFyZ2luPTE2LXBvb2xlZGJpdAogICAgcG9vbDw8PW1hcmdpbgogICAgcG9vbHMucHVzaChwb29sJjB4ZmYscG9vbD4+OCkKICBlbmQKICBjYnl0ZXM9W10KICBwb29sZWRiaXQ9MAogIGNvbnN1bWU9LT5iaXR7CiAgICBwb29sZWRiaXQgLT0gYml0CiAgICB3aGlsZSBwb29sZWRiaXQ8MTYKICAgICAgY2J5dGVzLnB1c2goKnBvb2xzLnNoaWZ0KDIpKQogICAgICBwb29sZWRiaXQrPTE2CiAgICBlbmQKICB9CiAgY29uc3VtZVswXQogIGVsZW1zLmVhY2hfc2xpY2UoOCl7fGNodW5rfAogICAgY2J5dGVzLnB1c2goKGNodW5rLm1hcHt8ZXwgZVswXSB9KicnKS50b19pKDIpKQogICAgY2h1bmsuZWFjaHt8KGR0eXBlLHZhbCl8CiAgICAgIGlmIGR0eXBlPT0xCiAgICAgICAgY2J5dGVzLnB1c2godmFsKQogICAgICBlbHNlCiAgICAgICAgY29uc3VtZVt2YWxdCiAgICAgIGVuZAogICAgfQogIH0KICB3YXJuICJtYXJnaW4gYml0OiAje21hcmdpbn0iIGlmIHZlcmJvc2UKICBjYnl0ZXMKfQoKcmJ5dGVzID0gJDwuZmxhdF9tYXB7fGxpbmV8IGxpbmUuc2NhbigvXHdcdy8pLm1hcHt8dHwgdC50b19pKDE2KSB9IH0KY2J5dGVzPWNvbXByZXNzW3JieXRlcyx0cnVlXQoKMC5zdGVwe3xvZmZ8CiAgYnl0ZXM9W10KICBkb2JyZWFrPWZhbHNlCiAgMTYudGltZXN7fGl8CiAgICBiPWNieXRlc1tvZmYqMTYraV0gb3IgYnJlYWsKICAgIGJ5dGVzW2ldPWIKICB9IG9yIGRvYnJlYWs9dHJ1ZQogIGJyZWFrIGlmIGJ5dGVzLnNpemU9PTAKICBic3Rycz1bIiAgIl0qMTYKICBieXRlcy5lYWNoX3dpdGhfaW5kZXh7fGIsaXwgYnN0cnNbaV09IiUwMngiICUgYn0KICBwdXRzICgiICAgICUwMngwOiAlcyIgJSBbb2ZmLCBic3Rycy5lYWNoX3NsaWNlKDIpLm1hcHt8KHMxLHMyKXwgczErczIgfSoiICJdKQogIGJyZWFrIGlmIGRvYnJlYWsKfQ==
000: 1281 fc71 0601 003f ff40 085f 1909 8328
010: 283f 4080 0001 1e82 fe25 0478 c0d5 001e
020: 0000 80
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