Eu tenho um número específico em mente, mas é parte de um desafio que estou fazendo e não quero que as pessoas façam (todo) o trabalho para mim.
Aqui está um número que tem os mesmos dígitos, mas embaralhados:
5713167915926167134578399473447223554460066674314639815391281352328315313091488448321843
8892917486601064146636679920143691047671721184150386045081532202458651561779976236919751
5521854951599379666116678853267398393892536121049731949764192014193648608210652358947001
6332620900065461061195026191178967128001712341637591690941978871368243245270800684616029
6679555942849366434586090627998161441134473428845367022486230724219981658438108844675033
4461550796750244527407413996606134735852639191026103378962082622204359677030054592798927
4145951979523473408718011778751084514127053772614511042703365596651912104541233491744530
87457854312602843967491787086250478422477028164189
O número tem 666 dígitos (decimal). Porque eu estou usando Python, números inteiros (ou tecnicamente longos) são automaticamente bignums.
Eu tenho 255 caracteres para usar e preciso descrever o mesmo número. A descrição deve ser executada através de eval () para produzir o número original.
Em quais estratégias devo procurar?
code-golf
kolmogorov-complexity
tips
python
compression
Christian Sonne
fonte
fonte
Respostas:
Codificação base
Uma técnica padrão para compactar números é expressá-los em uma grande base e codificar os dígitos como caracteres. Por exemplo, se você codificar o número na base 256, ele teria apenas 277 dígitos:
Ou expresso como uma sequência
(Além disso, alguns caracteres não imprimíveis que são retirados pelo SE.)
Claro, isso ainda é muito longo para o seu subsídio de 255 caracteres. Se você está realmente falando sobre caracteres (em vez de bytes), poderá entrar no Unicode e usar uma base muito maior. Que tal 2 16 ? São apenas 139 dígitos:
(Não posso incluir a string real aqui, porque ela contém alguns caracteres CJK que são banidos pelo SE.)
Agora isso parece mais factível. Você só precisa decodificá-lo em 116 caracteres. Se não puder, o Unicode possui muito mais do que 2 16 caracteres, para que você possa tentar usar uma base ainda maior.
fonte
Fatoração Prime
Se o número não possui recursos interessantes, a codificação base é a melhor maneira de fazê-lo. A próxima coisa a fazer é procurar por recursos interessantes do número. O primeiro que vem à mente é que ele pode ter fatores de primos pequenos (2,3,5,7, etc.) elevados a potências bastante grandes. Se você não tiver mais nada para continuar, continue tentando dividir por números primos pequenos e veja o que acontece. Se seus fatores incluem
2**4
,3**4
e7**4
, você pode escreverbig number *42**4
que está a poucos bytes menor do quebig number * 3111696
fonte
n
th prime, você poderá salvar um dígito ou mais por prime armazenando seu índice em vez do próprio prime.Remoção recursiva do maior quadrado
Essa abordagem remove o maior número quadrado de N, repetidamente, até que não haja valor em continuar.
Se você ignorar os caracteres "** 2 +", este será aproximadamente o mesmo número de dígitos que o número original, em média. A compensação desses 4 caracteres extras por iteração requer um pouco de sorte. No caso do seu número, o resultado possui 670 dígitos de números quadrados, mais 7x "** 2+", outra falha:
Ao quase empatar, em média, esse algoritmo se presta bem ao uso em conjunto com outros algoritmos (ou até a si próprio) para reduzir ainda mais os números na expressão (ao custo de alguns parênteses). Esses outros algoritmos podem ser mais caros, pois estarão operando em números significativamente menores que o original. No exemplo dado, um ganho líquido poderia ser obtido se um algoritmo mais caro e eficaz pudesse cortar 25% dos caracteres de
33300095205899066129442737321270515378501483166974896029394675779096351509514355500527819871697116193238261137790928953798777695127752032484956608505929119246433389165
(o segundo grande valor no resultado)fonte
Grandes potências próximas
Essa abordagem procura por números [relativamente] pequenos aumentados para um poder que se aproxima do número alvo. Na maioria dos casos, redefinir N como A ** B + C não será uma melhoria, mas em alguns casos será.
10000
é uma constante arbitrária. A condição de resgate também pode ser baseada em algum objetivomindiff
.No caso de seu número de amostra N com 666 dígitos, esta função (com o limite de 10k aumentou um pouco) descobre que
N ~= 165661162**81.0000000025
, assimN-165661162**81
como um número de 659 dígitos, corta 7 dígitos do número a ser tratado com um custo de 14 caracteres de expressão , uma falha.fonte