Compactando matrizes de seqüência de caracteres
ATUALIZAÇÃO: As ferramentas apresentadas nesta dica foram reescritas, aprimoradas e integradas ao meu intérprete Japt . Para obter os melhores resultados, é recomendável usar esse compressor sobre qualquer um dos links abaixo. Vou revisitar esta dica quando tiver mais tempo e reescrevê-la com o novo compressor em mente.
Introdução
Se você tiver uma matriz de seqüências de caracteres em seu código, a maneira mais óbvia de compactá-la seria executar cada sequênciaOc
individualmente. Para os fins desta dica, trabalharemos com a matriz ["lollipop","marshmallow","nougat","oreo"]
, que pesa 42 bytes inicialmente. A execução de cada string Oc
nos fornece:
[`lo¥ipop`,`Ú\hÚaow`,`Í`,`eo`]
Agora são 33 bytes, uma economia decente.
Passo 1
Mas podemos fazer melhor. Se unirmos a matriz a uma cadeia separada de nova linha, podemos nos livrar dos colchetes, vírgulas e reticulares estranhos e dividir na nova linha para obter nossa matriz. A aplicação disso ao nosso exemplo de matriz nos dá o seguinte:
`lo¥ipop
Ú\hÚaow
Í
eo`·
Abaixo de 26 bytes agora.
Passo 2
Mas , podemos fazer melhor ainda! Poderíamos usar uma letra minúscula para delimitar as strings em vez de uma nova linha, que pode ser incluída na compactação. z
não é usado em nenhuma das nossas strings, então vamos explicar isso e ver como vamos.
`lo¥ipopzÚ\hÚaowzÍzeo`qz
Ah, nozes - nenhuma melhoria lá; nossa contagem de bytes aumentou em um! Pode haver outra carta que você poderia usar, mas, dependendo de suas cordas, poderia haver muito poucos para tentar - em nosso exemplo, existem 11: b,c,d,f,j,k,q,v,x,y,z
. Tentar cada um deles seria bastante tedioso, e é aí que esta ferramenta útil entra; alimente-o com suas seqüências separadas de nova linha e ele tentará delimitar as seqüências com cada letra que não estiver contida em nenhuma delas e na saída:
- a menor corda compactada,
- o delimitador usado e
- seu comprimento.
A execução de nossas seqüências de amostra mostra que b
dá os melhores resultados:
`lo¥ipáæqrÚaowbÍÞo`qb
E aí está, temos apenas 24 bytes.
etapa 3
Mas podemos fazer ainda melhor! Se a ordem das seqüências de caracteres em sua matriz não importa, talvez exista uma permutação diferente combinada com um delimitador diferente que possa funcionar ainda mais. Tentar cada possibilidade será muito mais entediante. Com nossas 4 cordas, existem 24 permutações diferentes para tentar. Com cada uma das 11 letras possíveis que se tornam 264! É aí que esta ferramenta entra em jogo. Novamente, alimente suas seqüências de caracteres separadas por nova linha e ele tentará todas as combinações de todas as permutações e todas as letras delimitadoras, produzindo:
- a ordem das strings na menor string compactada,
- a corda compactada,
- o delimitador usado e
- seu comprimento.
Correndo nossas cordas de amostra através dele mostra que "nougat","oreo","lollipop","marshmallow"
com b
como delimitador dá os melhores resultados, com uma contagem de bytes finais de apenas 23:
`ÍÞo½o¥ipáæqrÚaow`qb
Dica de bônus: Compactação de matriz inteira
Você pode aplicar o mesmo princípio a matrizes de números inteiros, primeiro convertendo cada uma em uma base mais alta. Usando este exemplo, matriz de 36 bytes:
[588181,156859,595676,475330,680474]
Podemos reduzir isso para 29 bytes, primeiro convertendo-o em uma matriz de 32 strings base e depois executando-o no primeiro programa de compactação:
`huclt4p5r5ÛÊg62tkogq`qt mnH
Ou tão baixo quanto 27 bytes usando o segundo programa:
`4p5Ïcl5ÛÊg62tkogq`qt mnH
Você pode salvar outro byte ou 2 além disso, movendo a conversão de número inteiro para um método que você já está executando na matriz.
Notas
- Não se esqueça de levar em consideração os
q<letter>(<space>)
custos de 1 ou 2 bytes extras ·
. Embora, você pode ser capaz de usar um dos atalhos Unicode para obter uma volta byte, dependendo do seu delimitador ( qÊ
é o mesmo que ql<space>
, por exemplo).
- Uma palavra de cautela ao usar a última ferramenta: quanto mais strings você tiver, mais permutações existirão e mais lento o programa será executado, até que ele acabe. Conforme detalhado acima, com nossas 4 seqüências de amostra e 11 letras possíveis para tentar, existem 264 combinações possíveis, aumente o número de cadeias em apenas 1 com as mesmas 11 letras e já temos 1320 combinações para tentar. (Você pode usar esta ferramenta para contar o número de combinações, se desejar).
Créditos
- Oliver, pela inspiração para criar as ferramentas encontradas nesta dica.
- ETHproduções para revisão.