La tâche consiste simplement à voir combien plus rapidement vous pouvez calculer n choisissez n / 2 (pour même n) que la fonction intégrée en python. Bien sûr, pour les grands n, il s'agit d'un nombre plutôt élevé, donc plutôt que de sortir le nombre entier, vous devez sortir la somme des chiffres. Par exemple, pour n = 100000
, la réponse est 135702
. Car n=1000000
ça l'est 1354815
.
Voici le code python:
from scipy.misc import comb
def sum_digits(n):
r = 0
while n:
r, n = r + n % 10, n / 10
return r
sum_digits(comb(n,n/2,exact=True))
Votre score est (highest n on your machine using your code)/(highest n on your machine using my code)
. Votre code doit se terminer en 60 secondes ou moins.
Votre programme doit donner la sortie correcte pour tous les n pairs: 2 <= n <= (votre n le plus élevé)
Vous ne pouvez pas utiliser de code intégré ou de bibliothèques qui calculent des coefficients binomiaux ou des valeurs qui peuvent rapidement être transformées en coefficients binomiaux.
Vous pouvez utiliser n'importe quelle langue de votre choix.
Réponse principale La réponse principale actuelle avec un incroyable 680.09 est de moitié.
n
bien des millions, alors que je doute que la fonction Python puisse gérer quelque chose de plus quen = 1e5
sans s'étouffer.Réponses:
C ++ (GMP) - (287 000 000/422 000) = 680,09
Combinez sans vergogne le théorème de Kummer par xnor et GMP par qwr.
Pas encore proche de la solution Go, je ne sais pas pourquoi.Edit: Merci Keith Randall pour le rappel que la multiplication est plus rapide si le nombre est de taille similaire. J'ai implémenté une multiplication à plusieurs niveaux, similaire au concept de coalescence de la mémoire sur la gestion de la mémoire. Et le résultat est impressionnant. Ce qui prenait auparavant 51 secondes ne prend plus que 0,5 seconde (c'est-à-dire une amélioration de 100 fois !!)
La course pour
n=287,000,000
Le code. Compiler avec
-lgmp -lgmpxx -O3
la source
n
, 18s pour calculer le coefficient binomial central, et les 37s restants pour convertir le résultat en chaîne et additionner le chiffre.Aller, 33,96 = (16300000/480000)
Fonctionne en comptant tous les facteurs premiers du numérateur et du dénominateur et en annulant les facteurs d'appariement. Multiplie les restes pour obtenir le résultat.
Plus de 80% du temps est consacré à la conversion en base 10. Il doit y avoir une meilleure façon de le faire ...
la source
Python 3 (8,8 = 2,2 millions / 0,25 million)
C'est en Python, qui n'est pas connu pour sa vitesse, vous pouvez donc probablement mieux le porter dans une autre langue.
Générateur d' amorces extrait de ce concours StackOverflow .
L'idée principale de l'algorithme est d'utiliser le théorème de Kummer pour obtenir la factorisation première du binôme. Pour chaque nombre premier, nous en apprenons la puissance la plus élevée qui divise la réponse et multiplions le produit en cours d'exécution par cette puissance du nombre premier. De cette façon, nous n'avons besoin de multiplier qu'une seule fois pour chaque nombre premier dans la décomposition en facteurs premiers de la réponse.
Sortie montrant la répartition du temps:
Étonnamment, la plupart du temps est consacré à la conversion du nombre en chaîne pour additionner ses chiffres. Aussi surprenant, la conversion en une chaîne était beaucoup plus rapide que d'obtenir des chiffres à partir de répétitions
%10
et//10
, même si la chaîne entière doit probablement être conservée en mémoire.La génération des nombres premiers prend un temps négligeable (et donc je ne me sens pas injuste de copier du code existant). La somme des chiffres est rapide. La multiplication réelle prend un tiers du temps.
Étant donné que la sommation des chiffres semble être le facteur limitant, peut-être qu'un algorithme pour multiplier les nombres en représentation décimale gagnerait du temps au total en raccourcissant la conversion binaire / décimale.
la source
Java (score 22500/365000 = 0,062)
Je n'ai pas Python sur cette machine, donc si quelqu'un pouvait marquer cela, je serais reconnaissant. Sinon, il faudra attendre.
Le goulot d'étranglement est l'ajout pour calculer la section pertinente du triangle de Pascal (90% du temps d'exécution), donc l'utilisation d'un meilleur algorithme de multiplication ne serait pas vraiment utile.
Notez que ce que la question appelle
n
est ce que j'appelle2n
. L'argument de ligne de commande est ce que la question appellen
.la source
javac CodeGolf37270.java
) et s'exécute avec Java 1.8 (java CodeGolf37270 n
). Je ne sais pas s'il existe des options d'optimisation que je ne connais pas. Je ne peux pas essayer de compiler avec Java 1.8, car il n'est pas installé avec mon package Java ...GMP - 1500000/300000 = 5,0
Bien que cette réponse ne soit pas en concurrence avec les tamis, le code court peut parfois obtenir des résultats.
la source
Java, grande classe entière personnalisée: 32,9 (120000000/365000)
La classe principale est assez simple:
Il repose sur une grande classe entière qui est optimisée pour la multiplication et
toString()
qui sont toutes deux des goulots d'étranglement importants dans une implémentation avecjava.math.BigInteger
.Le gros goulot d'étranglement est la multiplication naïve (60%), suivie de l'autre multiplication (37%) et du tamisage (3%). L'
digsum()
appel est insignifiant.Performances mesurées avec OpenJDK 7 (64 bits).
la source
Python 2 (PyPy), 1.134.000 / 486.000 = 2,32
Résultat: 1537506
Fait amusant: le goulot d'étranglement de votre code consiste à ajouter des chiffres, et non à calculer le coefficient binomial.
la source
Java (2 020 000/491 000) = 4,11
mis à jour, précédemment 2.24
Java
BigInteger
n'est pas le calculateur de nombres le plus rapide, mais c'est mieux que rien.La formule de base pour cela semble être
n! / ((n/2)!^2)
, mais cela ressemble à un tas de multiplication redondante.Vous pouvez obtenir une accélération significative en éliminant tous les facteurs premiers du numérateur et du dénominateur. Pour ce faire, je lance d'abord un tamis primaire simple. Ensuite, pour chaque prime, je compte la puissance à laquelle il doit être élevé. Incrémenter chaque fois que je vois un facteur dans le numérateur, décrémenter pour le dénominateur.
Je gère les deux séparément (et d'abord), car il est facile de les compter / éliminer avant de les factoriser.
Une fois cela fait, vous disposez du minimum de multiplications nécessaires, ce qui est bien car la multiplication BigInt est lente .
Oh, et la somme de sortie pour n = 2020000 est
2735298
, à des fins de vérification.la source