PNG主题的python code golf

2020-02-09  本文已影响0人  此间不留白

来源:pageout
译者:此间不留白
协议:CC BY-NC-SA 4.0

介绍

早在2019年5月, Gynvael Coldwind组织了一场code golf竞赛(短码比赛)。参赛者的奖品是国际IT安全会议CONFidence的门票。实际上,这次竞赛包含了C++,javascript和python的3种编程语言环境的比赛,我的关注点在python环境下的比赛。赛题的目标是生成一个命名为confidence.png有效的PNG图像,并且其像素值与指定的模型图像相匹配。参赛作品在全新安装的离线Ubuntu 19.04服务器使用python3 confidence.py的命令上运行,并且有60秒的执行时间限制。不能使用暴力方法,最后,代码量最小的confidence.py将会赢得比赛。

图像

模型图像是一个大小为11746字节大小的文件,如下所示:


第一步是在保留像素值的同时使图像尽可能小。并且有以下分析:

遗憾的是,默认的python3环境中不包含任何第三方的图像处理库,所以不得已放弃以上方法。使用GIMP删除元数据和alpha通道并将图像转换为索引模式,得到了4283字节的PNG文件。然后我们可以使用PNG优化器optipng或pngcrush可以压缩至2547字节。使用参数为-iterations = 50 --filters = 01234mepb的zopflipng可获得2428字节的最佳结果。对一些web浏览器和移动app而言,2428字节足以显示损坏的png文件。但是,我们需要的是正确的png文件,所以可能做不到保留像素值的同时,使其大小小于2428字节。

脚本

至此,我们已经尽可能的优化PNG文件了,怎样使用通用的压缩方法进一步压缩呢?我们可以使用的python方法,而zopfliwins再次使用原生的deflate流。要在Python中解压缩,我们需要使用wlibs = -8作为加参数的zlib.decompress. 现在,如何将这710字节的二进制数据放入Python脚本?我们将需要整个2009个字节才能将其表示为字节文字.首先想到的是base64编码,等等,base64编码也支持base85编码,字符集越大,效率越高,毕竟是一个是短码比赛,每个字节都很重要,所以,综上,可以得到如下代码:

import zlib,base64 as b;open('confidence.png','wb').
write(zlib.decompress(b.b85decode('>kRO7=jD>(Vqjq4_4
IHFVqjozU|?XeU||M|Nd3K20Hh=Wd_r7-bSx7~4>Q~U|Nj@Wupez~y4cvfuA$LVZp&W=2
2OcT7srqa#y58yCq8lzX?Pee!gk9^=LnP7F(Bd=3*#0`QWX2fGJVOexNm|C-+uQsdM-Eq
8eUw*$Uq_Z5J94bE&77_?*v#6TxaFskPt8cVTA;T10dYc;0VNwjLb}IAj|?(z;Y+Z$CXJ
Ps06MItfU!;!AhXYKxPrI2yPi+MYru0<}n~Ef+)ad5@AIU1*9q>97^OWLO2?TQM^x*qFY
@rq{6=JpT770r(3%|-B&9!xp(w##q_&@FaMTuO8odhRJa^hh`MuTqsfu8SN4is^%q`tW6
cMh%b)hHk$U`0s`hm0^Eb=yX6xGB{PR$qxZp}q3+rCn7BOr0e81CIy_Ov+S@ZAnRMoKEW
$SzSD_2#1{$EqZ#7tD`NlU8T88&avlo@@YGsLcPUEef$*|R5ee_LnGPM@;%-BwKt7NX)V
p4WJz&t9)M>7>k6{>N8&`|W*|*=iY5oO<_c`MkNr#TK*v6*FnMHMR#o6#cgSyz;@?vbYB
<Z1xMOn(*|?d2Sq(u?)`S<zu9BI)Ct&$8-6Tu!2`o?;o9=8{VVML|P^#od0qzlo_jRU2<
Ra=6l}QpQc%_exKO)e7@-4x%Fo120u7?ku`ouf*46j_Mvtj>kB+&S)|wce(NbI*RQo-?q
3!0zFwiFPO^FU!}WmSC5hyhLj9$EOYK|t-~IpdQ+ABpo?|jHN%}M{T`5mc7bewBjymWcU
fR1WeDCTTQ-x98MzOUG-`v{PeY@WkYuO03m0GDJLtgn?J4w!^+)rdG!sByt6fsZ_{M*LP
ZUka9|5^L~W2ieZdIS=8Jghz&<lY0~c)I$ztaD0e0ss'),-8))

Method 大小
bz2.compress 950
lzma.compress 768
gzip.compress 732
zlib.compress 722
zlib.compress (level=9) 720
zopfli --deflate 710
Method len() len(repr())
b64encode 948 951
a85encode 888 915
b85encode 888 891

注意import语句,在编码数据字符串之前没有b。 请记住,许多文本编辑器会在保存的文件中添加其他换行符。 摆脱它! 对于代码高尔夫比赛来说8位太多了。

全二进制

跳过base85编码,直接在原始文件中嵌入二进制数据怎么样?当然,这种方法在短码比赛中是非法的。但是非比赛代码中可以尝试一下!


#coding=l1
import zlib;open('confidence.png','wb').write(zlib.d
ecompress(open(__file__,'rb').read()[111:],-8))

这种解决方案指需要821个字节,确实是一种不合竞赛规则,但是有效的解决方案。无论出于何种原因,都可以暴力地从encodings.aliases.aliases.keys()和二进制数据生成具有所有Python编码的文件,然后尝试运行它们。 选择最小的方案。

上一篇 下一篇

猜你喜欢

热点阅读