original = (<<'THE_END_OF_PICTURE'.split("\n").reverse.join("\n")+"\n").scan(/./m)
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM>MMMMMMMM'MMMMMMMMMMMM
MMMMMMx*MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM?MMMMMMMMMMMMMMMMM\MMMMMMMM'MMMMMMMMMMMM
MMMMMMMMx*MMMMMMMMMMMMMMMMMMMMMMMMMMMM#xMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMM(MMMMMMMMMMMMMMMMMMMMMMMMM*xMMMMMMMMMMMMMMMMMMMMMMMMMMMM:MMMMMMMMMMMMM
MMMMMMMMMMMM"MMMMMMMMMMMMMMMMMMMMMM"MMMMMMMMMMMMMMMMMMMMMMMMMMMMM\MMMMMMMMMMMMMM
MMX*MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM)MMMMMMMMMMMMMMM
*MMMHMMMMMMMMMMMMMMM*******"""""""""""""""*""""***MMMMMMMMMMMMM:MMMMMMMMMMMMMMMM
Mn?MMMM"` ....:::===:::::........ .x!MSXMMMX `MM"*MMMMMMMMMMMMMMMMM
*MMMMM ` .HXMMSX!XSX!MMMMx /M! `""*MMMMMMMM
MMMMMM dX!XSX!XSX!XSMMMSXh.MM `""MM
**MMMM MSX!XSX!XSX!XMMMMSXHMSX! `"~+..
MM"MMf X!XSX!XSX!XSMMMMMHMSX!XSX ^"=..
)HMMM 'X!XSX!XSXHMMMMMMMMMSX!XSM ^~:.
MMMMM MSX!XMMMMSXMMMM!XSX!XSX!~==:...
MMMMM ...... .MMMMSX!MSXHMMX!XSX!XSP*+x. `""~=::..
MMMMM .=" ```^"""!!*-*M*tXSX!XMMMXSX!XSXf `"*+x.
MMMMX .+~` ..::::+=======~~~~~n%!:.X.. `*X!MMM!XSX!X" `"*%x..
MMMMM~" .xnMHX ." " ` ``"MMM"MX. `""-=:.. "
MMMMMf" 'MM~M~ ...x. " 'MMX `"~=:.. `"+.
MMMMMX MxMM '""```` `"MMMHx. XMM )MH:.`~+.
MMMMMX MM.! `"*MMMh. XMM .xHMM*" `". `~+.
MMMMMM / HM '!!XXXXXXXX!:: '. MMM :MMM*" .....::. `~:.
XMMMMM ".?MM MM***MMMHXX^"XX!x MMX x::!XXHHHHHHHHHh MM
XMMMMM>' 'MM 'Mk !!MM!!"?x `"! !MX f` .nMMMMMM""MMM M
MMMMMMM XMM `Mh !!!~ ..\ X MM " -M^'!!??!! XMM 4
MMMMMMM 'MM `""""" M*k f ~.....(!!(..nMM* '
MMMMMMMM MM > M?: X
MMMMMMMMMX?M ! M:" M
MMMM#XMMMX ML M. M
MM*xMM)MMXX?M #: 'M
M!MMMMMMX/M-M `: XM
MHMMM>MMX`M !M + MM
MMMMMXMMX`MM`' MX
MMMMfMMMX/MM:! X M
MMMMMMMMX/MMM ! :!MM
MMMMMMMMX`?M4> . .!:MM
XM*""` X`'M X . .. :: fMM
X/'M : - ^~!! .x+! ~/ / MM
X/'M ': '!:.:!~ ~ / MM
X`'M `. ``` .` : MM
X`'X . .~ MM!
X/'X .xnh x.. .~ MM>
X/'!X ! xHMMMMMMMMMMMHx ~ 'MM>
X`'!' !: +MMMM?????MMMMMMMMMMx. .~ 'MMX
X`'! X!! `X!!!!!!!!!!!!!!X" : :MMX
X/'! X!!. `!!!!!!~`` !X" / XMMX
X/'! 'X!!x ^"~%!!*~` ! XMMX
X`'! !!!! ." MMMX
X`'! !!!!x X MMM?
X/'! !!!!!x .!!!x MMM'
X/'! '!!!!!!x. .!!!!!!?. MMM'
X`'! `!!!!!!!!: .:!!!!!!!!!!!. MMX'
. X`'! ~!!!!!!X!!%... ..:!!!M!!!!!!!!!~``% MMX
". X/'! ~!!!!!!!!!!!!!!!!???!!!!!!!!!M!!!!~` XMMHMMX
% X/'! !!!!!!!!!!!!!!!!!!!!!!!!!X!!!!` dMMMMMMMM
`+ X`'! !!!!!!!!!!!!!!!!!!!!!!!!!~ :MMMMMMMMM
`+X`'! `!!!!!!!!!!!!!!!!!!!!!!` MMMMMMMMMM
X/X! `!!!!!!!!!!!!!!!!!!~ MMMMMMMMMM
X/`?x `!!!!!!!!!!!!!!! XMMMMMMMMMM
X`/! `+. ~!!!!!!!!!!! MMMMMMMMMMM
X`/! ". `~!!!!!!~ :MMMMMMMMMMM
X/`! ^%. ~ MMMMMMMMMMMM
X/`! `~: ~ MMMMMMMMMMMM
X`/! ^=x. MMMMMMMMMMMMM
X'/! `~+.. /MMMMMMMMMMMMM
X'`! `"~~=::.. :MMMMMMMMMMMMMM
X'`! ``""~~=+::..... xMMMMMMMMMMMMMMM
X'/! XMMMMMMMMMMMMMMMM
X'/! MMMMMMMMMMMMMMMMMM
X'`! .MMMMMMMMMMMMMMMMMMM
X'`! nMMMMMMMMMMMMMMMMMMMM
""'` MMMMMMMMMMMMMMMMMMMMM!
.MMMMMMMMMMMMMMMMMMMMM!.
XMMMMMMMMMMMMMMMMMMMM!/.>
MMMMMMMMMMMMMMMMMMMMM"/.>/
.MMMMMMMMMMMMMMMMMMMMM~/.>//
THE_END_OF_PICTURE
def rle(a)
result = []
until a.empty?
i = 0
c = 0
while i < a.size
if a[i] == a[0]
c += 1
else
break
end
i += 1
end
result << [a[0], c]
a = a[c..-1]
end
result
end
data = rle(original)
stat = data.group_by{|x|x[0]}.map{|k,v|[k,v.map{|a,b|b}.inject(&:+)]}.sort_by{|k,v|-v}
STDERR << "NSYM: " << stat.size << $/
STDERR << "ORIGINAL: " << original.size << $/
STDERR << stat.inspect << $/
$bad = 0
def strpush(str, c)
case c
when "\\".ord; $bad+=1; str << "\\\\"
when "\"".ord; $bad+=1; str << "\\\""
when "\n".ord; $bad+=1; str << "\\n"
when "\r".ord; $bad+=1; str << "\\r"
else; str << c.chr
end
end
############################################################
spec = Hash.new
spec[" "] = ["100", 5]
spec["M"] = ["101", 5]
spec["!"] = ["110", 5]
spec["X"] = ["1110", nil, ""]
spec["."] = ["1111", nil, ""]
DEFAULT_BITS = 5
STDERR << "HOGEHOGEHOGE!" << $/ if (1<<DEFAULT_BITS) < (stat.size - spec.size)
DEFAULT_TABLE = ""
id = 0
data.each do |c,n|
unless spec[c]
spec[c] = ["0", nil, "%0#{DEFAULT_BITS}b"%id]
id += 1
DEFAULT_TABLE << c;
end
end
DEFAULT_TABLE << "!"
bits = ""
data.each{|c,n|
prefix, rle_bits, id_bits = spec[c]
if rle_bits
if c=="!" && n==1
bits += "011111"
else
while n>0
len = [(1<<rle_bits)-1, n].min
n -= len
bits += prefix
bits += "%0#{rle_bits}b" % len
end
end
else
while n>0
n -= 1
bits += prefix
bits += id_bits
end
end
}
STDERR << "EST: " << bits.size/8 << $/
bits << "0"*(8-bits.size%8)%8
ENCODED_LIT = (str = ""
for i in 0 ... bits.size/8
strpush(str, bits[i*8 ... i*8+8].to_i(2))
end
str
)
STDERR.puts "LIT :: #{ENCODED_LIT.size} bytes"
#####################################################
code = <<THE_END_OF_C
char*p="ENCODED_LIT";
b,l,t=#{original.size},c,n;
r(n){
l<n?b=b<<8|*p++&255,l+=8:0;
l-=n;
return(1<<n)-1&b>>l;
}
main(){
for(;t;)
for(c=r(n=1)
? (c="@M!"[r(2)]) ? n=r(5),c
: "X."[r(1)]
: DEFAULT_TABLE[r(5)];
n--;
t--)putchar(c);
}
THE_END_OF_C
code = code.gsub(/(?<!\w\w)\s*/,"").gsub("@"," ")
code["ENCODED_LIT"] = ENCODED_LIT
code["DEFAULT_TABLE"] = DEFAULT_TABLE.dump
STDERR.puts "#{code.size} bytes"
STDOUT.binmode
print code