Introdução
Considere o processo de pegar um número inteiro positivo n em alguma base be substituir cada dígito por sua representação na base do dígito à direita.
- Se o dígito à direita for 0, use a base b .
- Se o dígito à direita for 1, use unário com zeros como marcas de contagem.
- Se não houver um dígito à direita (ou seja, você está no local certo), faça um loop até o dígito mais significativo.
Como exemplo, deixe n = 160 eb = 10. A execução do processo é semelhante a esta:
The first digit is 1, the digit to the right is 6, 1 in base 6 is 1.
The next digit is 6, the digit to the right is 0, 0 is not a base so use b, 6 in base b is 6.
The last digit is 0, the digit to the right (looping around) is 1, 0 in base 1 is the empty string (but that's ok).
Concatenating '1', '6', and '' together gives 16, which is read in the original base b = 10.
O mesmo procedimento exato, mas mover para a esquerda em vez da direita também pode ser feito:
The first digit is 1, the digit to the left (looping around) is 0, 0 is not a base so use b, 1 in base b is 1.
The next digit is 6, the digit to the left is 1, 6 in base 1 is 000000.
The last digit is 0, the digit to the left is 6, 0 in base 6 is 0.
Concatenating '1', '000000', and '0' together gives 10000000, which is read in the original base b = 10.
Assim, criamos dois números relacionados a 160 (para b = 10): 16 e 10000000.
Definiremos n como um número astuto se ele dividir uniformemente pelo menos um dos dois números gerados nesse processo em 2 ou mais partes
No exemplo n é astuto porque 160 divide 10000000 exatamente 62500 vezes.
203 NÃO é astuto porque os números resultantes são 2011 e o próprio 203, que 203 não pode se ajustar uniformemente em 2 ou mais vezes.
Desafio
(Para o resto do problema, consideraremos apenas b = 10.)
O desafio é escrever um programa que encontre o maior número astuto que também seja primo.
Os primeiros 7 primos astutos (e tudo o que encontrei até agora) são:
2
5
3449
6287
7589
9397
93557 <-- highest so far (I've searched to 100,000,000+)
Não tenho oficialmente certeza se existem mais, mas espero que sim. Se você puder provar que existem (ou não) muitos, eu darei a você +200 representantes de recompensa.
O vencedor será a pessoa que poderá fornecer o mais alto astuto, desde que seja aparente que eles foram ativos na busca e não estão intencionalmente se gloriando dos outros.
Regras
- Você pode usar as ferramentas principais de busca que desejar.
- Você pode usar testadores probabilísticos primos.
- Você pode reutilizar o código de outras pessoas com atribuição . Este é um esforço comunitário. Táticas cruéis não serão toleradas.
- Seu programa deve procurar ativamente o principal. Você pode iniciar sua pesquisa no ponto mais alto conhecido.
- Seu programa deve poder calcular todos os primos espertos conhecidos dentro de 4 horas das instâncias do Amazon EC2 t2.medium (quatro de uma vez ou uma por quatro horas ou algo intermediário). Na verdade, não vou testá-lo e você certamente não precisa. Esta é apenas uma referência.
Aqui está o meu código Python 3 que eu usei para gerar a tabela acima: (roda em um ou dois segundos)
import pyprimes
def toBase(base, digit):
a = [
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
['', '0', '00', '000', '0000', '00000', '000000', '0000000', '00000000', '000000000' ],
['0', '1', '10', '11', '100', '101', '110', '111', '1000', '1001'],
['0', '1', '2', '10', '11', '12', '20', '21', '22', '100'],
['0', '1', '2', '3', '10', '11', '12', '13', '20', '21'],
['0', '1', '2', '3', '4', '10', '11', '12', '13', '14'],
['0', '1', '2', '3', '4', '5', '10', '11', '12', '13'],
['0', '1', '2', '3', '4', '5', '6', '10', '11', '12'],
['0', '1', '2', '3', '4', '5', '6', '7', '10', '11'],
['0', '1', '2', '3', '4', '5', '6', '7', '8', '10']
]
return a[base][digit]
def getCrafty(start=1, stop=100000):
for p in pyprimes.primes_above(start):
s = str(p)
left = right = ''
for i in range(len(s)):
digit = int(s[i])
left += toBase(int(s[i - 1]), digit)
right += toBase(int(s[0 if i + 1 == len(s) else i + 1]), digit)
left = int(left)
right = int(right)
if (left % p == 0 and left // p >= 2) or (right % p == 0 and right // p >= 2):
print(p, left, right)
if p >= stop:
break
print('DONE')
getCrafty()