打代码高尔夫:代码压缩和提交给AtCoder平台竞赛

哈Ha!我请您注意文章“ attentionーコルフフーゴーをーをーをーlateーlateーをーをーをーをーをーてててCode Code Code Code Code Code Code Code Code Code Code Code Codeフフフ] ”的翻译。



您听说过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


这次它正确缩小了。



(我不知道为什么它增加了,所以,如果有人知道,请告诉我们)。

因此,通过反复试验,我们能够缩短代码。



指向本文原文的链接位于此处。



如果您告诉我们您是否喜欢本文,我们将非常高兴,翻译是否清晰,对您有用吗?



All Articles