Você já ouviu falar do Code Golf ? É como um jogo em que todos tentam escrever um código específico com o mínimo de caracteres possível.
Uma das soluções (código de 171 bytes) enviada para o concurso AtCoder * foi amplamente criticada, então decidi descobrir qual era o problema.
(Nota do tradutor: AtCoder é uma plataforma onde várias competições entre desenvolvedores são realizadas. A julgar pelo domínio .jp, a plataforma é japonesa, mas há usuários de todo o mundo. Por exemplo, no momento da tradução deste artigo, havia 3 usuários da Rússia no topo do site.)
Código de compressão
Pelo que entendi, compactar o código (= reduzir seu tamanho e peso) o encurta simbolicamente. Os membros do Code Golf, pode-se dizer, colocam suas almas na redução de cada personagem, cada byte. E como o objetivo dessa competição é escrever o código mais curto possível, não há razão para não compactá-lo.
Dê uma olhada no código a seguir primeiro.
#!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'
Eu mal consigo ler. Mas desde a primeira linha, entendi que o código é escrito em Ruby.
#!ruby -Knrzlib
É um shebang e tem -Kn e -rzlib especificados como opções de linha de comando.
-Kn indica que o código escrito deve ser tratado como um código binário sem caracteres. Por exemplo, #coding: binary faz a mesma coisa.
-rzlib - Requerido pela biblioteca zlib. Acrônimo para require "zlib".
eval Zlib.inflate'…
Próxima linha.
Zlib.inflate é um método para descompactar código compactado. Como você pode ver que ainda há uma linha após o caractere ', entendemos que esta parte do código descompacta o código compactado e aplica a avaliação a ele.
Vou tentar sozinho
Achei que seria bom criar um modelo de compressão de código.
Isso requer três etapas: 1) escrever o código, 2) compactar o código e 3) produzir o código final. Por sua vez, os passos 1 e 2 devem ser repetidos para diminuir a taxa de compressão.
Escrevendo o código
Vamos escrever o código primeiro. (Bem, esta etapa não é um bom presságio)
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]}}
Este código tem 216 bytes.
Agora vamos tentar comprimir.
Comprimir
Usando esse script, consegui reduzi-lo para 194 bytes!
$ ruby deflate.rb agc047_e.rb > agc047_e.min.rb
194 B
Enviar para AtCoder
Compactei o código e quis enviá-lo, mas havia um problema.
Infelizmente, não posso simplesmente copiar e colar este código e enviá-lo como está. O código gerado pela compressão é binário. No entanto, a tela de envio do AtCoder é UTF-8. Na maioria das vezes, o código compactado contém cadeias de bytes que não são válidas em UTF-8, portanto, se você copiar e colar como está, ficará distorcido.
Então, vou postar o código codificado URI diretamente usando DevTools.
Vamos abrir a tela de envio e lançar DevTools. Mantemos aberta a página de envio da solução ao concurso.

Quando tudo estiver preparado, conforme indicado na imagem acima, pressionamos o botão para submeter nossa solução no site. O DevTools exibirá a solicitação enviada.
Selecione a solicitação chamada “enviar” e clique com o botão direito sobre ela, pressione Copiar e Copiar como busca.

Abra seu console e cole o código que você acabou de copiar.

Cole após sourceCode = nosso código codificado de URI (não mostrado na captura de tela). Usamos este script para codificar para URI . (Salve como 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
Converta agc047_e.rb em deflate-uriencode.rb.
Na segunda linha de saída, copie tudo após% 23 e cole após sourceCode = acima.

Agora podemos enviar nossa solução.
Alterar o código (tornando-o ainda mais curto)
Vamos encurtar o código. Existem duas maneiras de encurtar o código após a compressão.
- Reduza o código-fonte
- Aumentar a taxa de compressão
Vou tentar usar os dois métodos. Reduzir o código-fonte é a forma favorita dos colaboradores do Code Golf.
Aumentando a taxa de compressão
Como posso aumentar a taxa de compressão? Agora usamos a compressão Deflate, que é uma combinação de compressão run-length e codificação Huffman. Preste atenção a este código de Huffman. O código de Huffman é diferente porque a taxa de compressão aumenta à medida que a entropia diminui antes da compressão. A entropia diminui à medida que as probabilidades de aparecimento do código mudam. Portanto, se a probabilidade de ocorrência de códigos for alterada, a taxa de compressão aumentará conforme a mudança ocorrer.
Uma maneira eficaz de reduzir a probabilidade de exibição de código é reduzir o tipo de caractere. Para fazer isso, você pode renomear a variável.
No primeiro código, vamos renomear as variáveis x e v para t e p. Então, como ele é colocado com o nome da função puts ou map, o tipo do caractere pode ser reduzido.
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
Hmm, aumentou.
Remova p e substitua por 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
Desta vez, ele encolhe corretamente.
(Não sei porque aumentou, então por favor, se tiver gente que saiba, diga-nos).
Assim, por tentativa e erro, conseguimos encurtar o código.
Um link para o original deste artigo está aqui.
Ficaremos muito felizes se você nos disser se gostou deste artigo, a tradução foi clara, foi útil para você?