Die Aufgabe besteht einfach darin, herauszufinden, wie viel schneller Sie n choose n / 2 (für gerade n) berechnen können als die in Python integrierte Funktion. Natürlich ist dies für große n eine ziemlich große Zahl. Anstatt die ganze Zahl auszugeben, sollten Sie die Summe der Ziffern ausgeben. Zum Beispiel n = 100000
lautet die Antwort 135702
. Für n=1000000
es ist 1354815
.
Hier ist der Python-Code:
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))
Ihre Punktzahl ist (highest n on your machine using your code)/(highest n on your machine using my code)
. Ihr Code muss in höchstens 60 Sekunden enden.
Ihr Programm muss für alle gerade n die richtige Ausgabe liefern: 2 <= n <= (Ihr höchstes n)
Sie können keinen eingebauten Code oder keine eingebauten Bibliotheken verwenden, die Binomialkoeffizienten oder Werte berechnen, die schnell in Binomialkoeffizienten umgewandelt werden können.
Sie können jede Sprache Ihrer Wahl verwenden.
Führende Antwort Die aktuelle führende Antwort mit erstaunlichen 680.09 ist nur halb so hoch.
n
und in die Millionen geht, während ich bezweifle, dass die Python-Funktion etwas Größeres bewältigen würde alsn = 1e5
ohne Würgen.Antworten:
C ++ (GMP) - (287.000.000 / 422.000) = 680,09
Kombinieren Sie schamlos Kummers Theorem von xnor und GMP von qwr.
Immer noch nicht einmal in der Nähe der Go-Lösung, weiß nicht warum.Bearbeiten: Danke Keith Randall für die Erinnerung, dass die Multiplikation schneller ist, wenn die Zahl in der Größe ähnlich ist. Ich habe Multi-Level-Multiplikation implementiert, ähnlich dem Memory-Coalescing-Konzept für die Speicherverwaltung. Das Ergebnis kann sich sehen lassen. Was früher 51 Sekunden dauerte, dauert jetzt nur noch 0,5 Sekunden (dh 100-fache Verbesserung !!)
Der Lauf nach
n=287,000,000
Der Code. Kompilieren mit
-lgmp -lgmpxx -O3
quelle
n
18s bei der Berechnung des zentralen Binomialkoeffizienten und die restlichen 37s bei der Umwandlung des Ergebnisses in eine Zeichenfolge und der Summierung der Ziffer.Los, 33,96 = (16300000/480000)
Zählt alle Primfaktoren des Zählers und Nenners und hebt Übereinstimmungsfaktoren auf. Multipliziert die Reste, um das Ergebnis zu erhalten.
Mehr als 80% der Zeit wird für die Umstellung auf Basis 10 aufgewendet. Es muss einen besseren Weg geben, dies zu tun ...
quelle
Python 3 (8,8 = 2,2 Millionen / 0,25 Millionen)
Dies ist in Python, das nicht für Geschwindigkeit bekannt ist, also können Sie dies wahrscheinlich besser in eine andere Sprache portieren.
Primes-Generator aus diesem StackOverflow-Wettbewerb .
Die Hauptidee des Algorithmus ist die Verwendung des Kummer-Theorems , um die Primfaktorisierung des Binomials zu erhalten. Für jede Primzahl lernen wir die höchste Potenz, die die Antwort teilt, und multiplizieren das laufende Produkt mit dieser Potenz der Primzahl. Auf diese Weise müssen wir in der Primfaktorisierung der Antwort für jede Primzahl nur einmal multiplizieren.
Ausgabe mit zeitlicher Aufteilung:
Überraschenderweise wird die meiste Zeit damit verbracht, die Zahl in eine Zeichenfolge umzuwandeln, um ihre Ziffern zu summieren. Auch überraschend, Konvertierung in einen String war viel schneller als Ziffern wiederholt immer
%10
und//10
, obwohl die gesamte Zeichenfolge muss vermutlich im Speicher gehalten werden.Das Generieren der Primzahlen nimmt vernachlässigbare Zeit in Anspruch (und daher fühle ich mich nicht unfair, wenn ich vorhandenen Code kopiere). Das Summieren von Ziffern ist schnell. Die tatsächliche Multiplikation dauert ein Drittel der Zeit.
Angesichts der Tatsache, dass die Ziffernsummierung der einschränkende Faktor zu sein scheint, würde ein Algorithmus zum Multiplizieren von Zahlen in Dezimaldarstellung insgesamt Zeit sparen, indem die Binär / Dezimal-Konvertierung verkürzt wird.
quelle
Java (Punktzahl 22500/365000 = 0,062)
Ich habe kein Python auf diesem Rechner, also wäre ich dankbar, wenn jemand dies bewerten könnte. Wenn nicht, muss es warten.
Der Engpass ist die Addition zur Berechnung des relevanten Abschnitts des Pascalschen Dreiecks (90% der Laufzeit), daher würde die Verwendung eines besseren Multiplikationsalgorithmus nicht wirklich helfen.
Beachten Sie, dass die Frage das
n
ist, was ich anrufe2n
. Das Befehlszeilenargument ist das, was die Frage aufruftn
.quelle
javac CodeGolf37270.java
) kompiliert und mit Java 1.8 (java CodeGolf37270 n
) ausgeführt. Ich bin nicht sicher, ob es Optimierungsoptionen gibt, die mir nicht bekannt sind. Ich kann nicht versuchen, mit Java 1.8 zu kompilieren, da es mit meinem Java-Paket nicht installiert wird ...GMP - 1500000/300000 = 5,0
Obwohl diese Antwort nicht mit Sieben konkurriert, kann ein kurzer Code manchmal dennoch zu Ergebnissen führen.
quelle
Java, benutzerdefinierte Big Integer-Klasse: 32.9 (120000000/365000)
Die Hauptklasse ist ziemlich einfach:
Es basiert auf einer großen Ganzzahlklasse, die für die Multiplikation optimiert ist und
toString()
bei der es sich um erhebliche Engpässe bei einer Implementierung mit handeltjava.math.BigInteger
.Der große Engpass ist die naive Multiplikation (60%), gefolgt von der anderen Multiplikation (37%) und dem Sieben (3%). Der
digsum()
Anruf ist unbedeutend.Leistung gemessen mit OpenJDK 7 (64 Bit).
quelle
Python 2 (PyPy): 1.134.000 / 486.000 = 2,32
Ergebnis: 1.537.506
Unterhaltsame Tatsache: Der Engpass in Ihrem Code besteht darin, die Ziffern zu addieren und nicht den Binomialkoeffizienten zu berechnen.
quelle
Java (2.020.000 / 491.000) = 4,11
aktualisiert, zuvor 2.24
Java
BigInteger
ist nicht der schnellste Cruncher, aber besser als nichts.Die Grundformel dafür scheint zu sein
n! / ((n/2)!^2)
, aber das scheint ein Haufen redundanter Multiplikation zu sein.Sie können eine erhebliche Beschleunigung erzielen, indem Sie alle Primfaktoren entfernen, die sowohl im Zähler als auch im Nenner enthalten sind. Dazu starte ich zuerst ein einfaches Hauptsieb. Dann zähle ich für jede Primzahl, zu welcher Kraft sie erhöht werden muss. Erhöhe jedes Mal, wenn ich einen Faktor im Zähler sehe, um den Nenner.
Ich behandle zwei getrennt (und zuerst), da es einfach ist, sie vor dem Factoring zu zählen / zu eliminieren.
Sobald dies erledigt ist, haben Sie die erforderliche Mindestmenge an Multiplikationen, was gut ist, weil die BigInt-Multiplikation langsam ist .
Oh, und die Ausgabesumme für n = 2020000 ist
2735298
zu Überprüfungszwecken.quelle