SF (n) é uma função que calcula o menor fator primo para um determinado número n.
Vamos chamar T (N) a soma de todos os SF (n) com 2 <= n <= N.
T (1) = 0 (a soma ultrapassa 0 soma)
T (2) = 2 (2 é o primeiro primo)
T (3) = 5 = 2 + 3
T (4) = 7 = 2 + 3 + 2
T (5) = 12 = 2 + 3 + 2 + 5
...
T (10000) = 5786451
O vencedor será aquele que conseguir calcular o maior T (N) em 60 segundos no meu próprio laptop (Toshiba Satellite L845, Intel Core i5, 8 GB de RAM).
Current top score: Nicolás Siplis - 3.6e13 points - Nim
math
fastest-code
primes
division
Nicolás Siplis
fonte
fonte
Respostas:
Nim, 3.6e13
Simplesmente peneirar não é a melhor resposta ao tentar calcular o N mais alto possível, pois os requisitos de memória se tornam muito altos. Aqui está uma abordagem diferente (iniciada com Nim há alguns dias e apaixonada pela velocidade e sintaxe, qualquer sugestão para torná-la mais rápida ou legível é bem-vinda!).
fonte
return
naf
definição 's. Procs de expressão única retornam automaticamente.C, peneira principal: 5e9
Resultados:
Programa:
Embora seja um programa bastante simples, levei um tempo para descobrir como obter o gerenciamento de memória correto - eu só tenho memória RAM suficiente para 1 byte por número no intervalo, então tive que ter cuidado. É uma peneira padrão de Erasthones.
fonte
Perl, fator de força bruta
Posso chegar a 9e7 em 25 segundos na minha máquina Linux. Poderia ser mais rápido, digitando o código C, como está dizendo após uma verificação de 2/3/5, fatorar completamente o número.
Existem maneiras muito mais inteligentes de fazer isso usando peneiração. Eu pensei que uma maneira simples de força bruta seria um começo. Este é basicamente o problema do Projeto Euler 521, a propósito.
fonte
Go, 21e9
Faz uma peneira para encontrar o fator mínimo de cada número <= N. Gera goroutines para contar seções do espaço numérico.
Execute com "vá executar prime.go -P 4 -N 21000000000".
Observe que a resposta para N = 21e9 está entre 2 ^ 63 e 2 ^ 64, então tive que usar ints de 64 bits não assinadas para contar corretamente ...
fonte
C ++, 1 << 34 ~ 1.7e10
fonte
Java 8:
1.8e82.4e8Esta entrada não se compara a várias outras já publicadas, mas eu queria postar minha resposta, pois me diverti trabalhando nisso.
As principais otimizações da minha abordagem são as seguintes:
T(N)
quandoN % 2 == 1
, você sabe dissoT(N + 1) == T(N) + 2
. Isso me permite iniciar minha contagem às três e incrementar por iteração em dois.Collection
tipo. Isso mais que dobrou o queN
eu posso alcançar.Isso é tudo o que há para isso. Meu código itera de três em dois até detectar que atingiu ou excedeu o limite de tempo; nesse momento, ele fornece a resposta.
A execução em um sistema diferente (Windows 8.1, Intel core i7 a 2,5 GHz, 8 GB de RAM) com a versão mais recente do Java 8 apresenta resultados significativamente melhores, sem alterações de código:
fonte
mayContinue()
emfor loop condition
com apenas uma condição simples, você poderia alcançar maior resultado. E eu gosto da sua maneira de pré-calcular a soma uniforme e depois aumentar em dois.startTime
para umendTime
para eliminar as subtrações ~ 2e7, mas isso me custou 3e7 da minha pontuação!System.nanoTime() - startTime < TIME_LIMIT
, porque ele prende seu código um pouco para mim. Não é incrivelmente rápido, considerando o fato, essa condição é verificada milhões de vezes, será um pouco rápido. Uma coisa que aprendi com o seu código é: não coloquefor
dentro de umfor
.. Depois de passarfor
para outro método no meu código, minha velocidade de código aumenta em 40%, obrigado. Uma coisa que ainda estou descobrindo é: Arrays são muito mais eficientes do que ArrayList quando se considera o fato de que é milhões obtida de vezes ..x2
resultado se implementarMultiThreading
. Mas seria necessário pré-calcular toda a matriz antes de executar o cálculo Prime.mayContinue()
método para o loop for me custa 8e6 da minha pontuação. Isso pode ser um problema de otimizações locais. Eu experimentei vários tipos de dados para armazenar os primos quando desenvolvi esta solução. Eu só consegui alcançar 8.8e7 comArrayList
, mas atingi 1.8e8 (agora 2.4e8) usando uma matriz. Pode haver alguns aprimoramentos de desempenho envolvidos na pesquisa, mas há aprimoramentos definidos para a alocação de memória. Eu pensei em multi-threading o algoritmo, mas tive problemas.R, 2.5e7
Peneira simples de Eratóstenes, vetorizada tanto quanto possível. O R não foi realmente projetado para esse tipo de problema e tenho certeza de que pode ser feito mais rapidamente.
fonte
sum(vec)
leva a um excesso de número inteiro e retorna NA.sum(as.numeric(vec))
é soma de um vector de duplas que não transborde (embora possa não dar a resposta certa)Python, ~ 7e8
Usando uma peneira incremental de Erathostenes. É necessário tomar cuidado para que um valor marcado seja marcado com seu divisor mais baixo, mas a implementação é razoavelmente direta.
O tempo foi determinado com o PyPy 2.6.0; a entrada é aceita como argumento da linha de comando.
Uso da amostra
fonte
Julia, 5e7
Certamente Julia pode fazer melhor, mas é isso que tenho por enquanto. Isso faz 5e7 em cerca de 60 segundos no JuliaBox, mas ainda não posso testar localmente. Espero que até lá eu tenha pensado em uma abordagem mais inteligente.
Aqui, estamos criando uma função
lpf
que itera através de números primos sequenciais e verifica a entrada quanto à divisibilidade de cada um. A função retorna o primeiro divisor encontrado, obtendo assim o menor fator primo.A função principal calcula
lpf
os números inteiros de 2 à entrada em paralelo e reduz o resultado somando.fonte
Lisp comum, 1e7
Optei por gerar primeiro uma lista de números primos de 2 a
(sqrt input)
e depois testar todos os valores com os números primos, enquanto anteriormente eu testaria todos os números até(sqrt input)
, o que seria inútil (por exemplo, se um número é divisível por 4, também é divisível por 2, por isso já é contabilizado.)Graças a Deus pelos efeitos colaterais enquanto estou nisso. O remove-if reduz o tamanho da lista e conta quantos elementos foram removidos, então eu apenas tenho que multiplicar por qualquer valor que o loop esteja e adicionar isso ao total em execução.
(Curiosidade:
delete
é o equivalente destrutivo deremove
, mas por qualquer motivo,delete
é mais lento do queremove
neste caso.)fonte
Ferrugem 1.5e9
Uma peneira muito ingênua de Eratosthene, mas eu senti que Rust não recebeu nenhum amor aqui!
fonte
Java 2.14e9
Peneira pura de Eratóstenes com vantagem do BitSet
Eu calculei a soma do fator menor menor até
Integer.MAX_VALUE - 1
just in33.89 s
. Mas não posso continuar maior porque mais adiante levará ao Estouro Inteiro no Tamanho do Bitset. Então, estou trabalhando para criar outro Bitset para o próximo conjunto de intervalos. Até lá, é o mais rápido que consigo gerar.fonte