您听说过Code Golf吗?这有点像一个游戏,每个人都试图用尽可能少的字符来编写特定的代码。
上载到AtCoder *竞赛的一种解决方案(171字节代码)受到广泛批评,因此我决定找出问题所在。
(译者注:AtCoder是一个在开发人员之间举行各种竞赛的平台。从.jp域来看,该平台是日语,但有来自世界各地的用户。例如,在翻译本文时,网站顶部有3个俄罗斯用户。)
压缩代码
据我了解,压缩代码(=减小代码的大小-重量)会使其象征性地缩短。有人可能会说,Code Golf的成员全心全意地简化每个字符,每个字节。并且由于此竞赛的目标是编写尽可能短的代码,因此没有理由不对其进行压缩。
首先看下面的代码。
#!ruby -Knrzlib
eval Zlib.inflate'x = Q
D OS c
]r ݳ By
O{4 . i aQ(`}cB I2e ߣ IeT јL> )u, p S W H~. , :
z:Ӊ g O7ʲ vQ 1h ^< =& \u7'
我几乎看不懂。但是从第一行开始,我知道代码是用Ruby编写的。
#!ruby -Knrzlib
它是一个Shebang,并且将-Kn和-rzlib指定为命令行选项。
-Kn表示应将编写的代码视为二进制,无字符的代码。例如,#coding:binary执行相同的操作。
-rzlib-zlib库必需。首字母缩写词require“ zlib”
eval Zlib.inflate'…
下一行。
Zlib.inflate是一种解压缩压缩代码的方法。由于您可以看到'字符后还有一行,因此我们了解到,这部分代码将压缩的代码解压缩并对其进行评估。
我自己去试试
我认为创建代码压缩模板会很好。
这需要三个步骤:1)编写代码,2)压缩代码,以及3)生成最终代码。反过来,必须重复步骤1和2以降低压缩率。
编写代码
让我们先编写代码。(好吧,这一步预示着不好)
puts [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|x|[a,x,3,x]+(0..29).map{v=x+4;u=x*60+9+_1;[a,v,v,v,a,v,3,6,*[a,6,6,6]*(29-_1),?<,6,x,u,a,v,u,v]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}
该代码长216个字节。
现在让我们尝试压缩。
压缩
使用此脚本,我能够将其减少到194个字节!
$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb
194 B
提交给AtCoder
我压缩了代码并想发送它,但是有一个问题。
不幸的是,我不能只复制并粘贴此代码并按原样发送它。压缩生成的代码是二进制的。但是,AtCoder提交屏幕为UTF-8。在大多数情况下,压缩代码包含在UTF-8中无效的字节字符串,因此,如果按原样复制和粘贴它,则会出现乱码。
因此,我将直接使用DevTools发布URI编码的代码。
让我们打开提交屏幕并启动DevTools。我们保留用于提交竞赛解决方案的页面。
如上面的屏幕快照所示,一切准备就绪后,我们按下按钮以在网站上提交我们的解决方案。 DevTools将显示我们提交的请求。
选择称为“提交”的请求,然后右键单击它,按“复制”,然后按“复制为提取”。
打开控制台,然后粘贴刚刚复制的代码。
粘贴在sourceCode =我们的URI编码代码之后(屏幕截图中未显示)。我们使用此脚本将其编码为URI 。(另存为deflate-uriencode.rb)
$ ruby deflate-uriencode.rb agc047_e.rb
194 B
%23%21ruby+-Knrzlib%0Aeval+Zlib.inflate%27x%DA-%8DQ%0A%830%10D%AF%D2Ou%B7A%13%5D%14%2B%1E%24%04%C9%01%0AB%13%094%B9%7Bwc%99%8F%81%99%E1%CD%19%C3%E7ai%9CG%F4%DB%0E%D8%E3%80%06%F7%17j6%E3%C0r%E0%D4%DB%9F%DF%9C%B2%F5%988N%0E%9A%5E%29%BD%B4%B5%B8%B6%04%E3%1A%B7%D4Q%0F%0B%1C%C3%CA%BB%ABJ%DC+a%C7%09%89%5C%D7%E8%E5y%0C%AD%5C%10%D3b%DDD%BC%5C%29%95%3A%FD%A99%C8%9D%16%DDw*%DC%05%A73%04f+%C9%19N%822l%84%B2%DE%97%F2%03%93%919%B0%DE%97%F2%03%93%919%B0%27
将agc047_e.rb转换为deflate-uriencode.rb。
从输出的第二行,复制%23之后的所有内容,并粘贴在上述sourceCode =之后。
现在我们可以提交解决方案了。
更改代码(使其更短)
让我们缩短代码。有两种方法可以缩短压缩后的代码。
- 缩小源代码
- 增加压缩率
我将尝试同时使用这两种方法。缩小源代码是Code Golf贡献者最喜欢的一种方式。
增加压缩率
如何增加压缩率?现在,我们使用Deflate压缩,它是行程压缩和Huffman编码的组合。请注意此霍夫曼代码。霍夫曼码的不同之处在于,压缩率随着压缩之前熵的减小而增加。熵随着代码出现概率的变化而减小。因此,如果发生代码的可能性发生偏移,则随着发生偏移,压缩率将增加。
减少代码出现可能性的有效方法是减少字符类型。为此,您可以重命名变量。
在第一个代码中,让我们将变量x和v重命名为t和p。然后,由于将其与功能名称放置或映射一起放置,因此可以减少字符的类型。
puts [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{p=t+4;u=t*60+9+_1;[a,p,p,p,a,p,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,p,u,p]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}
$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb
275 B
嗯,它增加了。
删除p并用s替换。
puts [6484,a=?+,0,1,3,?<,2,3,3]+[0,1].map{|t|[a,t,3,t]+(0..29).map{s=t+4;u=t*60+9+_1;[a,s,s,s,a,s,3,6,*[a,6,6,6]*(29-_1),?<,6,t,u,a,s,u,s]}}+(0..59).map{|t|[a,2,2,2]+(0...t).map{[a,8+t-_1,69+_1,5,?<,3,5,6,a,2,6,2]}}
$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb
184 B
这次它正确缩小了。
(我不知道为什么它增加了,所以,如果有人知道,请告诉我们)。
因此,通过反复试验,我们能够缩短代码。
指向本文原文的链接位于此处。
如果您告诉我们您是否喜欢本文,我们将非常高兴,翻译是否清晰,对您有用吗?