O problema é o seguinte.
Entrada: um número inteiron
Saída: O menor primo maior que n
.
O desafio é fornecer o código mais rápido possível para isso. Testarei o código em valores começando no tamanho aproximado 10^8
10^200
e dobrando de tamanho até que demore mais de um minuto e 10 segundos no meu computador.
O código vencedor encontrará o próximo primo para o maior tamanho de entrada.
A título de comparação, uma simples peneira escrita em python é capaz de encontrar o próximo primo maior do que 10^8
em 20
segundos.
O requisito de que eu possa testá-lo no meu computador ubuntu de 4 GB de RAM é rigoroso. Todo o código deve ser livre (nos dois sentidos) e, se usar bibliotecas, também deve ser gratuito e facilmente instalável. Quaisquer falsos números primos relatados desqualificarão imediatamente o envio.
Também atribuirei elogios separados aos vencedores em cada linguagem de programação se o código for totalmente escrito nessa linguagem sem o uso de bibliotecas externas. Também manterei a mesa dos tempos mais rápidos à medida que a competição avança, para que as pessoas possam ver como estão.
Tabela até agora
- Pitão. Um
357
número impressionante de dígitos343239883006530485749095039954069660863471765007165270469723172959277159169882802606127982033072727748864815569574042901856099399985832190628701414555752857600000000000000000000000000000000000000002872284792758930912601189043411951050852357613658978971208596097634095500808832510259693761982135208603287199546795000697807728609476163156438356035166156820611
era o número final em menos de 10 segundos, usando o código fornecido porprimo
. Alguém vai vencer esta primeira entrada?
fonte
fast next prime function
.Respostas:
Python ~ 451 dígitos
Isso faz parte da biblioteca que escrevi para um problema de fatoração semiprime , com funções desnecessárias removidas. Ele usa o teste de primalidade Baillie-PSW , que é tecnicamente um teste probabilístico, mas, até o momento, não existem pseudo-tempos conhecidos - e há até uma recompensa em dinheiro se você puder encontrar um (ou por fornecer uma prova de que não existe). .
Edit : Eu não tinha percebido que o Python possui exponenciação modular embutida. Substituir o meu pelos resultados embutidos em um aumento de desempenho de cerca de 33%.
my_math.py
Um script de teste de amostra:
Um fator de 317 foi escolhido, porque é aproximadamente a raiz quadrada de
10000
, adicionando aproximadamente 2,5 dígitos por iteração (e porque a duplicação era muito lenta para ser realizada). A saída mostra o número atual de dígitos e o tempo gasto.Resultados da amostra:
Todo o código agora é compatível com python 3.
fonte
next_prime((2^520)*(10^200))
cerca de 15 segundos na minha máquina, então, à primeira vista, isso é bastante impressionante. No entanto ...next_prime((2^520)*(10^200),proof=False)
leva 0,4 segundos porque verifica apenas a pseudoprimalidade. Sua afirmação de que "não existem pseudoprimes conhecidos" é muito convincente, pois o número de bits ultrapassa 64. Para 357 dígitos, não estou nem remotamente convencido pela falta de contra-exemplos.C ++ com GMP: 567 dígitos
Usa a implementação de Miller-Rabin no GMP. Pode retornar um falso positivo, mas a boa sorte realmente atinge um com probabilidade 2 ^ -200.
Encontra o primo
10^200 * 2^1216 + 361
(567 dígitos) antes de executar o tempo no meu laptop lento.fonte
Perl com módulo GMP, 1300 dígitos
Usando meu módulo Math :: Prime :: Util e seu back-end GMP . O ponto de cruzamento exato dependerá do seu computador e se você possui a biblioteca GMP mais recente. Todo o código é gratuito (os módulos estão no github e no CPAN, e o GMP está disponível gratuitamente). Eu os executei no Ubuntu da AWS, bem como no Ubuntu de desktop (e Fedora, AIX, NetBSD etc.).
O código principal está em C e C + GMP. next_prime do MPU vê que o número é muito grande e o encaminha para o back-end GMP (ou código Perl puro, se o back-end não estiver instalado). Isso stringiifica e converte em um mpz e converte o resultado novamente no tipo de objeto de entrada ou Math :: BigInt. next_prime em si faz:
O provável teste principal é:
Tudo antes do ES BPSW é apenas otimização, o que é claro que queremos para next_prime. O next_prime também é implementado no Perl usando o módulo Math :: BigInt (no núcleo com back-ends Pari e GMP opcionais). Isso faz o AES BPSW (como o Pari), mas não é tão otimizado.
Pensei nos méritos de uma versão baseada em peneira parcial, usando um intervalo de, por exemplo, 2 méritos. Só não tenho certeza se isso seria realmente melhor, pois na maioria das vezes faríamos peneiras desnecessárias, pois a lacuna era pequena e, às vezes, para uma lacuna grande, teríamos que repeti-la várias vezes.
A biblioteca implementa o ECPP (incluindo certificados) para que pudéssemos executar uma prova no resultado, mas 1200 dígitos são realmente grandes demais para o pequeno conjunto padrão de polinômios incluídos (existe um método para fazer o download de conjuntos maiores - as provas demorariam um pouco 15 minutos, um pouco mais rápido que o APR-CL da Pari, mas um pouco mais lento que o mpz_aprcl do WraithX). Uma desvantagem do ECPP vs. APR-CL é que ele tem mais variação de tempo, portanto há uma boa chance de exceder 10 segundos em algum número antes que o tempo médio chegue lá. Com uma prova, acho que estamos limitados a algo na faixa de 400 dígitos, a menos que permitamos software multiencadeado.
Eu decidi tentar com a mesma sequência usada pelo primo. Chegou a 1191 dígitos, já que atingimos uma lacuna de 18138. Também testei o código do primo usando o mais recente my_math.py. Ele chega a 630 dígitos com a sequência 10 ^ e 641 com a sequência. Muito impressionante para código compacto todo em Python sem muitos pré-testes.
fonte
Math::GMP
de uma maneira que não é tão inútil com a criação / destruição de referência do mpz.$x = new Math::GMP(0); $x += 3 for 1..1000000
. Vou postar no cpan quando terminar; você será um dos primeiros a saber;)