Mit dem jüngsten Python- Bashing wird hier versucht, die Stärken von Python zu demonstrieren. Ihre Herausforderung besteht darin, ein Programm zu schreiben, das n
innerhalb von 10 Sekunden die Fakultät einer möglichst hohen Zahl berechnet .
Ihre Punktzahl wird sein (highest n for your program on your machine)/(highest n for my program on your machine)
Regeln
- Sie müssen eine genaue ganzzahlige Lösung berechnen. Da die Fakultät viel höher ist als diejenige, die in eine 64-Bit-Ganzzahl ohne Vorzeichen passen kann, können Sie Zeichenfolgen verwenden, wenn Ihre Sprache keine großen Ganzzahlen unterstützt
- Standardlücken sind verboten. Insbesondere können Sie keine externen Ressourcen verwenden.
- Nur der Berechnungsteil (dies schließt die Zeit für Umgehungen mit Zeichenfolgen ein) addiert sich zur Gesamtzeit, die im Durchschnitt unter 10 Sekunden liegen sollte.
- Nur Programme mit einem Thread.
- Sie müssen die Ausgabe in einer einfach zu druckenden Form speichern (da das Drucken einige Zeit in Anspruch nimmt) (siehe mein Programm weiter unten), in einer Zeichenfolge, einer Variablen, einem Zeichenarray usw.
BEARBEITEN:
- Ihr Programm muss für alle die richtige Ausgabe liefern
n
:1 <= n <= (your highest n)
EDIT2:
- Ich hasse es, dies ausdrücklich zu sagen, aber die Verwendung der eingebauten Fakultätsfunktionen Ihrer Sprache fällt unter die Standardlücken http://meta.codegolf.stackexchange.com/a/1078/8766 Sorry Mathematica and Sage
Mein Programm
from __future__ import print_function
import time
def factorial( n ):
return reduce( ( lambda x , y : x * y ) , xrange( 1 , n + 1 ) , 1 )
start = time.clock()
answer = factorial( 90000 )
end = time.clock()
print ( answer )
print ( "Time:" , end - start , "sec" )
Höchste Punktzahl gewinnt. Für die Aufzeichnung kann mein Code n = 90000
in ungefähr 9.89
Sekunden auf einem Pentium 4 3.0 GHz verwalten
EDIT: Kann jeder bitte die Punktzahl und nicht nur die höchste n hinzufügen . Nur das Höchste n
hat für sich genommen keine Bedeutung, da es von Ihrer Hardware abhängt. Andernfalls ist es unmöglich, ein objektives Gewinnkriterium zu haben. ali0shas Antwort macht das richtig.
Wir haben einen Sieger. Ich habe die Java-Antwort /codegolf//a/26974/8766 nicht akzeptiert, da sie sich in der Nähe von http://meta.codegolf.stackexchange.com/a/1080/8766 befindet
quelle
operator.mul
anstelle der Lambda-Funktionfactorial(Inf)
liefertInf
in Sekundenbruchteilen.Antworten:
C ++ mit GMP, Score = 55,55 (10.000.000 / 180.000)
quelle
Python 2.7
42,575 = (6,812,000 / 160,000) Ca.
Code:
Prüfung:
Ausgabe:
Wie es funktioniert:
Größere Multiplikationen brauchen mehr Zeit, deshalb wollen wir so viele kleine Multiplikationen wie möglich machen. Dies gilt insbesondere in Python, wo für Zahlen, die weniger
2^64
Hardware-Arithmetik verwenden, und darüber hinaus Software verwendet wird. Alsom(L)
beginnen wir mit einer ListeL
; Wenn die Länge ungerade ist, entfernen wir eine Zahl aus der Überlegung, um sie wieder gerade zu machen. Dann multiplizieren wir Element1
mit Element-2
, Element3
mit-4
usw., so dassDieser Ansatz stellt sicher, dass wir die Hardwarearithmetik so lange wie möglich verwenden. Anschließend wechseln wir zur effizienten gmc-Arithmetikbibliothek.
In
fac2
nehmen wir auch einen klassischeren Divide and Conquer-Ansatz, bei dem wir jedes Vielfache von 2 aufteilen und sie am Ende bitweise verschieben, um die Leistung zu verbessern. Ich habe es hier aufgenommen, weil es normalerweise etwa 0,5% schneller ist alsfac1
.Golf Version von
fac1
(weil ich kann), 220Bquelle
gmpy2
? $ python Python 2.7.3 (Standard, 27. Februar 2014, 19:58:35) [GCC 4.6.3] unter Linux2 Geben Sie "help", "copyright", "credits" oder "license" ein, um weitere Informationen zu erhalten. >>> aus gmpy2 importieren mpz Traceback (letzter Aufruf zuletzt): Datei "<stdin>", Zeile 1, in <module> ImportError: Kein Modul namens gmpy2 >>>while len(L): ...
stattdessen tunwhile len(L)>1: ...
?Java - 125,15 (21.400.000 / 171.000)
Ebenfalls schamlos von Peter Luschnys Github-Repo kopiert (danke an @ semi-extrinsic) und unter der MIT-Lizenz lizenziert, verwendet dies den von Albert Schönhage et al. (gemäß Luschnys Seite mit der Beschreibung der faktoriellen Algorithmen ).
Ich habe den Algorithmus leicht angepasst, um Javas BigInteger zu verwenden und keine Nachschlagetabelle für n <20 zu verwenden.
Kompiliert mit gcj, das GMP für seine BigInteger-Implementierung verwendet und unter Linux 3.12.4 (Gentoo) auf einem Core i7 4700MQ mit 2,40 GHz ausgeführt wird
quelle
gcj -O3 --main=PrimeSieveFactorialSchoenhage PrimeSieveFactorialSchoenhage.java -o pf_nest_square_fact
Python 3, n = 100000
Eine einfache Änderung des Algorithmus reichte aus, um den Beispielcode um 10000 zu erhöhen.
Offensichtlich nicht die kreativste Antwort, aber es gibt wirklich nur einen Weg, eine Fakultät zu machen ....
quelle
Perl + C, n = ungefähr 3 Millionen
Hier verwende ich die auf CPAN verfügbare Math :: BigInt :: GMP- Bibliothek, die eine enorme Geschwindigkeitssteigerung für Perls Kern-Math :: BigInt-Objekte bietet.
Denken Sie daran, dass mein Computer wahrscheinlich etwas langsamer ist als Ihr Computer. Mit Ihrem ursprünglichen Python-Skript kann ich nur
factorial(40000)
in 10 Sekunden rechnen .factorial(90000)
dauert viel länger. (I drücken Sie Strg + C nach einer Minute) . Auf Ihrer Hardware, mit Math :: BigInt :: GMP, Sie können auch in der Lage sein , die Fakultät zu berechnen 5 Millionen oder mehr in weniger als 10 Sekunden.Sie werden feststellen, dass die Fakultät zwar unglaublich schnell berechnet wird, der Ausdruck des Ergebnisses jedoch sehr langsam ist und etwa dreimal länger dauert als die ursprüngliche Berechnung. Dies liegt daran, dass GMP intern eine Binärdarstellung anstelle einer Dezimaldarstellung verwendet und für den Ausdruck eine Umwandlung von Binärdarstellung in Dezimaldarstellung erforderlich ist.
quelle
Math::BigInt
Python 2.7
5.94 = 1'200'000 / 202'000
Verwendet die relative Leichtigkeit der Multiplikation vieler Gruppen kleiner Zahlen und deren anschließende Multiplikation mit einer großen Anzahl von Multiplikationen mit großen Zahlen.
quelle
C #: 0,48 (77.000 / 160.000)
Ich bin damit nicht zufrieden.
Ist C # so langsam?
Aber hier ist trotzdem mein Eintrag.
Wenn n = 77000 ist, dauert es, um
00:00:09:8708952
zu berechnen.Ich arbeite außerhalb von Visual Studio im Release-Modus mit einem Core i3-2330M bei 2,2 GHz.
Bearbeiten: Da ich nichts Intelligentes mache, akzeptiere ich dieses Ergebnis. Möglicherweise ist .NET Framework 4.5 zusätzlich mit etwas Overhead verbunden (oder BigInteger ist nicht so schnell).
quelle
n
zero approached by
Operator verwenden, um es schöner zu machen (wie beginnen mitn = ... + 1
dann tunwhile (0 <-- n) result *= n;
)bc, Score = 0,19
Was zum Teufel, hier ist mein Anwärter auf "Wie viel kannst du langsam multiplizieren?"
bc ist "Eine beliebige Präzisionsrechnersprache", aber leider ziemlich langsam:
In ungefähr 10 Sekunden kann die Referenz-Python-Antwort auf meinem MacBook Pro (2,3 GHz Intel Core i7) von Mitte 2012 122000! Berechnen, aber dieses bc-Skript kann nur 23600!
Umgekehrt 10000! dauert 1,5 s mit dem Python-Referenzskript, aber das bc-Skript dauert 50 s.
Ach je.
quelle
read()
, also bin ich gerannttime sed 's/read()/28000/' factorial.bc | bc
.Bash: score = 0.001206 (181/150000)
Ich habe die mathematischen Funktionen von Rosettacode gestohlen - Lange Multiplikation, die ich weder analysiert noch optimiert habe.
Sie können den Algorithmus ändern oder eine andere Strings-Split-Methode ausprobieren.
quelle
Python 3, fortgeschrittenes Algo von Peter Luschny: 8,25x (1 280 000/155 000)
Schamlos kopiert von Peter Luschny,
http://www.luschny.de/math/factorial/FastFactorialFunctions.htm ,
der diesen Code unter der Lizenz "Creative Commons Attribution-ShareAlike 3.0" zur Verfügung stellt.
Dies ist eigentlich ein ziemlich fortgeschrittener Algorithmus, der das sogenannte "Swinging Factorial" und eine Liste von Primzahlen verwendet. Ich vermute, es könnte sogar noch schneller gehen, wenn es viele der anderen Antworten gefallen und die meisten Multiplikationen mit 32-Bit-Ganzzahlen durchgeführt hätte.
quelle
Java - 10.9
n = 885000
Mergesort-y.
BigInteger
s sind langsam.Empfehlungen für beliebig genaue Hochgeschwindigkeits-Java-Integer-Bibliotheken? : P
quelle
C ++ (x86_64-spezifisch) - 3.0 (390000/130000)
(Einfach auf x86-32 portierbar, Portierung auf andere Architekturen bedeutet erheblichen Geschwindigkeitsverlust.)
Hier ist meine eigene Mikroimplementierung der langen Arithmetik.
Die Berechnung selbst dauert 10 Sekunden, und während die Ausgabe in leicht druckbarer Form vorliegt (siehe
operator<<
Überladung), dauert es etwas länger, sie zu drucken.quelle
g++ -O2 factorial.cc -o factorial
und es erreicht 3.90 = 382000 / 98000.r
zunehmendem Umfang seinen Vorteil gegenüber Python . Wenn ja, und Sie könnenr
in 10 Sekunden eine höhere machen , dann sinkt Ihre Punktzahl.Python 3: 280000/168000
Laufzeit Ihres Programms: zwischen
9.87585953253
und10.3046453994
. Die Zeit läuft mein Programm: über10.35296977897559
.Ich habe diese Antwort auf cs.SE gelesen und beschlossen, sie in Python zu implementieren. Allerdings habe ich das versehentlich entdeckt
n! = (⌊n / 2⌋)! * 2**(⌊n / 2⌋) * n!!
(Anmerkung:!!
ist die doppelte Fakultät ). Also habe ich das in eine nicht-rekursive Form umgewandelt.Die Kommentare zeigen meinen Versuch, die doppelte Fakultät nicht erneut zu berechnen, aber ich stellte fest, dass das Speichern jedes Werts zu speicherintensiv war, als dass mein Computer noch langsamer laufen würde. Ich kann dies verbessern, indem ich nur das speichere, was benötigt wird.
Seltsamerweise habe ich die naive Straight-Multiplikation in Python 3 implementiert und sie ist besser als Ihr Programm:
n = 169000
in 10 Sekunden:quelle
Ruby 2.1
score = 1.80 = 176_000 / 98_000
EDIT: verbessert von
1,35 = 132_000 / 98_000Ich habe Ideen aus dem faktoriellen GMP-Algorithmus übernommen . Dieses Programm verwendet die Standardbibliothek, um Primzahlen zu generieren. Ruby ist eine schlechte Wahl, da die Multiplikation in Ruby langsamer erscheint als in Python.
Ja, meine binäre
ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-openbsd]
Links gegen GMP. Ruby 2.1 hat eine Funktion hinzugefügt, mit der GMP für große Multiplikationen verwendet werden kann, die jedoch langsamer zu sein scheint als Python 2.7.quelle
Julia - Score = 15,194
Unter Verwendung des exakt gleichen Ansatzes wie beim Referenzprogramm ... das heißt,
Daher werden die binäre Grundmultiplikationsoperation "Reduzieren" und ein Bereich (in diesem Fall "Big (n)" verwendet, um die Berechnung in "BigInt" anstelle von "Int64" zu erzwingen) verwendet. Daraus bekomme ich
Auf meinem Computer mit einem Referenzprogramm, das mit der Eingabe von 154000 ausgeführt wird, erhalte ich die
Time: 10.041181 sec
Ausgabe (wird ausgeführt mitpython ./test.py
, wobei test.py der Name der Datei ist, die den Referenzcode enthält).quelle
tcl, 13757
Meine Antwort ist, die Grenzen von tcl zu überprüfen.
In der ersten Zeile wird nur ein Eingabeparameter festgelegt:
Die anderen sind der Algorithmus selbst:
Ich habe meinen Code unter http://rextester.com/live/WEL36956 getestet . Wenn ich n größer mache, bekomme ich einen SIGKILL; Kann n auf einem lokalen tcl-Interpreter größer werden, den ich nicht habe.
quelle