SF (n) est une fonction qui calcule le plus petit facteur premier pour un nombre n donné.
Nous appellerons T (N) la somme de chaque SF (n) avec 2 <= n <= N.
T (1) = 0 (la somme est supérieure à 0 somme)
T (2) = 2 (2 est le premier nombre premier)
T (3) = 5 = 2 + 3
T (4) = 7 = 2 + 3 + 2
T (5) = 12 = 2 + 3 + 2 + 5
...
T (10000) = 5786451
Le gagnant sera celui qui parvient à calculer le plus grand T (N) en 60 secondes sur mon propre ordinateur portable (Toshiba Satellite L845, Intel Core i5, 8 Go de RAM).
Current top score: Nicolás Siplis - 3.6e13 points - Nim
math
fastest-code
primes
division
Nicolás Siplis
la source
la source
Réponses:
Nim, 3.6e13
Le simple tamisage n'est pas la meilleure réponse lorsque vous essayez de calculer le N le plus élevé possible car les besoins en mémoire deviennent trop élevés. Voici une approche différente (commencé avec Nim il y a quelques jours et tombé amoureux de la vitesse et de la syntaxe, toutes les suggestions pour le rendre plus rapide ou plus lisible sont les bienvenues!).
la source
return
inf
. Les procs d'expression simple reviennent automatiquement.C, tamis principal: 5e9
Résultats:
Programme:
Bien que ce soit un programme plutôt simple, il m'a fallu un certain temps pour comprendre comment gérer la mémoire correctement - je n'ai que suffisamment de RAM pour 1 octet par numéro dans la plage, j'ai donc dû faire attention. C'est un tamis standard d'Erasthones.
la source
Perl, affacturage par force brute
Je peux atteindre environ 9e7 en 25 secondes sur ma machine Linux. Cela pourrait être plus rapide en fouillant dans le code C, comme il est dit après une vérification des 2/3/5, factorisez complètement le nombre.
Il existe des moyens beaucoup plus intelligents de le faire en utilisant le tamisage. Je pensais qu'un simple moyen de force brute serait un début. Il s'agit en fait du problème 521 de Project Euler.
la source
Go, 21e9
Fait un tamis pour trouver le facteur minimum de chaque nombre <= N. Fait apparaître des goroutines pour compter les sections de l'espace numérique.
Exécutez avec "go run prime.go -P 4 -N 21000000000".
Notez que la réponse pour N = 21e9 se situe entre 2 ^ 63 et 2 ^ 64, j'ai donc dû utiliser des entiers 64 bits non signés pour compter correctement ...
la source
C ++, 1 << 34 ~ 1.7e10
la source
Java 8:
1.8e82.4e8Cette entrée ne se compare pas à plusieurs autres déjà en place, mais je voulais poster ma réponse car je me suis amusé à travailler dessus.
Les principales optimisations de mon approche sont les suivantes:
T(N)
quandN % 2 == 1
, vous le savezT(N + 1) == T(N) + 2
. Cela me permet de commencer mon comptage à trois et d'incrémenter par itération par deux.Collection
type. Cela a plus que doublé le nombre queN
je peux atteindre.C'est à peu près tout. Mon code réitère à partir de 3 par deux jusqu'à ce qu'il détecte qu'il a atteint ou dépassé le délai, auquel cas il crache la réponse.
Fonctionnant sur un système différent (Windows 8.1, Intel Core i7 @ 2,5 GHz, 8 Go de RAM) avec la dernière version de Java 8 a des résultats nettement meilleurs sans changement de code:
la source
mayContinue()
dansfor loop condition
avec juste une condition simple, vous pouvez obtenir le résultat plus élevé. Et j'aime votre façon de précalculer la somme paire, puis de l'incrémenter de deux.startTime
à unendTime
pour éliminer les soustractions ~ 2e7, mais cela m'a coûté 3e7 de mon score!System.nanoTime() - startTime < TIME_LIMIT
, car il fixe un peu votre code pour moi. Ce n'est pas incroyablement rapide, compte tenu du fait, cette condition est vérifiée des millions de fois, ce sera un peu rapide. Une chose que j'ai apprise de votre code est, ne mettez pas à l'for
intérieur d'unfor
.. Après être passéfor
à une autre méthode dans mon code, la vitesse de mon code augmente de 40%, merci .. Une chose que je comprends toujours, c'est que les tableaux sont beaucoup plus efficaces que ArrayList si l'on considère le fait qu'il est récupéré des millions de fois ..x2
résultats si vous implémentezMultiThreading
. Mais il faudrait précalculer l'ensemble du tableau avant d'exécuter le calcul Prime.mayContinue()
méthode dans la boucle for me coûte 8e6 de mon score. Cela peut être un problème d'optimisations locales. J'ai expérimenté plusieurs types de données pour stocker les nombres premiers lorsque je développais cette solution. Je n'ai pu atteindre que 8.8e7 avecArrayList
, mais j'ai atteint 1.8e8 (maintenant 2.4e8) en utilisant un tableau. Il peut y avoir des augmentations de performances impliquées avec la recherche, mais il existe des augmentations définies pour l'allocation de mémoire. J'ai pensé au multi-threading de l'algorithme, mais j'ai rencontré des problèmes.R, 2,5e7
Tamis simple d'ératosthène, vectorisé autant que possible. Les R ne sont pas vraiment conçus pour ce genre de problème et je suis sûr qu'il peut être fait plus rapidement.
la source
sum(vec)
conduit à un débordement d'entier et retourne NA.sum(as.numeric(vec))
résume un vecteur de doubles qui ne déborde pas (bien qu'il ne donne pas la bonne réponse)Python, ~ 7e8
Utilisation d'un tamis incrémental d'Erathostènes. Il faut prendre soin qu'une valeur marquée soit marquée avec son plus petit diviseur, mais l'implémentation est par ailleurs assez simple.
La synchronisation a été prise avec PyPy 2.6.0, l'entrée est acceptée comme argument de ligne de commande.
Exemple d'utilisation
la source
Julia, 5e7
Julia peut sûrement faire mieux, mais c'est ce que j'ai pour l'instant. Cela fait 5e7 en environ 60 secondes sur JuliaBox mais je ne peux pas encore tester localement. J'espère que d'ici là, j'aurai pensé à une approche plus intelligente.
Ici, nous créons une fonction
lpf
qui itère à travers des nombres premiers séquentiels et vérifie la divisibilité de l'entrée par chacun. La fonction renvoie le premier diviseur rencontré, obtenant ainsi le plus petit facteur premier.La fonction principale calcule
lpf
sur les entiers de 2 à l'entrée en parallèle et réduit le résultat en sommant.la source
Lisp commun, 1e7
J'ai choisi de générer d'abord une liste de nombres premiers de 2 à
(sqrt input)
, puis de tester chaque valeur avec les nombres premiers, alors qu'auparavant je testais contre chaque nombre jusqu'à(sqrt input)
, ce qui serait inutile (par exemple, si un nombre est divisible par 4, il est également divisible par 2, il est donc déjà pris en compte.)Dieu merci pour les effets secondaires pendant que j'y suis. Le retrait-si à la fois réduit la taille de la liste et compte le nombre d'éléments supprimés, il me suffit donc de multiplier cela par la valeur de la boucle et de l'ajouter au total cumulé.
(Fait amusant:
delete
est l'équivalent destructeur deremove
, mais pour une raison quelconque, ildelete
est de toutes sortes plus lent queremove
dans ce cas.)la source
Rouille 1.5e9
Un tamis Eratosthene très naïf, mais je sentais que Rust n'avait reçu aucun amour ici!
la source
Java 2.14e9
Tamis pur d'Ératosthène avec avantage de BitSet
J'ai calculé la plus petite somme du facteur premier jusqu'à
Integer.MAX_VALUE - 1
juste en dedans33.89 s
. Mais je ne peux pas continuer plus loin car tout autre entraînera un débordement d'entier sur la taille du Bitset. Je travaille donc sur la création d'un autre ensemble de bits pour le prochain ensemble de plages. Jusque-là, c'est le plus rapide que je puisse générer.la source