Regeln sind einfach:
- Die ersten n Primzahlen (keine Primzahlen unter n ) sollten durch Zeilenumbrüche getrennt auf die Standardausgabe gedruckt werden (Primzahlen sollten innerhalb des Codes generiert werden)
- Primzahlen können nicht durch eine eingebaute Funktion oder durch eine Bibliothek generiert werden , dh die Verwendung einer eingebauten oder Bibliotheksfunktion wie prime = get_nth_prime (n), is_a_prime (number) oder factorlist = list_all_factors (number) ist nicht sehr kreativ.
Wertung - Angenommen, wir definieren Score = f ([Anzahl der Zeichen im Code]), wobei O ( f (n)) die Komplexität Ihres Algorithmus ist, wobei n die Anzahl der gefundenen Primzahlen ist. Wenn Sie beispielsweise einen 300-Zeichen-Code mit der Komplexität O (n ^ 2) haben, ist die Punktzahl 300 ^ 2 = 90000 , für 300 Zeichen mit O (n * ln (n)) wird die Punktzahl 300 * 5,7 = 1711,13 ( Nehmen wir der Einfachheit halber an, dass alle Protokolle natürliche Protokolle sind.
Verwenden Sie eine vorhandene Programmiersprache, die niedrigste Punktzahl gewinnt
Bearbeiten: Das Problem wurde von der Suche nach 'ersten 1000000 Primzahlen' zu 'ersten n Primzahlen' geändert, da wir uns nicht sicher sind, was 'n' in O (f (n)) ist. N ist die Anzahl der gefundenen Primzahlen das Problem hier und so hängt die Komplexität des Problems von der Anzahl der gefundenen Primzahlen ab)
Hinweis: Um einige Unklarheiten in Bezug auf die Komplexität zu klären : Wenn 'n' die Anzahl der gefundenen Primzahlen und 'N' die n-te gefundene Primzahl ist, ist die Komplexität in Bezug auf n gleich und N ist nicht äquivalent, dh O (f (n))! = O (f (N)) als, f (N)! = Konstante * f (n) und N! = Konstante * n, weil wir wissen, dass die n-te Primfunktion nicht linear ist, obwohl wir 'n' gefunden haben Die Komplexität von Primzahlen sollte sich leicht mit 'n' ausdrücken lassen.
Wie von Kibbee erwähnt, können Sie diese Website besuchen , um Ihre Lösungen zu überprüfen ( hier ist die alte Google Docs-Liste).
Bitte fügen Sie diese in Ihre Lösung ein -
Welche Komplexität hat Ihr Programm (einschließlich der grundlegenden Analyse, wenn nicht trivial)?
Zeichenlänge des Codes
die endgültig berechnete Punktzahl
Dies ist meine erste CodeGolf-Frage. Wenn es also einen Fehler oder eine Lücke in den obigen Regeln gibt, machen Sie sie bitte darauf aufmerksam.
quelle
1[\p:i.78498
meine Antwort darauf1[\p:i.1000000
. Selbst wenn Js interner Prim-Algorithmus O (n ^ 2) ist, würde mein Score immer noch nur 196 sein.n
die Anzahl der Primzahlen oder die maximalen Primzahl, und jeder ignoriert die Tatsache , dass die Zugabe von Zahlen im Bereich0..n
istO(logn)
, und die Multiplikation und Division ist noch teurer. Ich schlage vor, dass Sie einige Beispielalgorithmen zusammen mit ihrer korrekten Komplexität angeben.O-tilde(k^6)
. Dies führt zu der Folgerung, dass jeder, der eine bessere Laufzeit behauptet, alsO-tilde(n ln n (ln(n ln n))^6)
einen Teil des Problems missverstanden hat; und auf die Frage, wie mitO-tilde
Komplexität in der Wertung umgegangen werden soll.Antworten:
Python (129 Zeichen, O (n * log log n), Punktzahl von 203,948)
Ich würde sagen, das Sieb des Eratosthenes ist der richtige Weg. Sehr einfach und relativ schnell.
Verbesserter Code von vor.
Python (
191 156152 Zeichen, O (n * log log n) (?), Punktzahl von 252,620 (?))Ich kann die Komplexität überhaupt nicht berechnen, das ist die beste Annäherung, die ich geben kann.
n*int(l(n)+l(l(n)))
ist die obere Grenze dern
th Primzahl.quelle
n
jedoch nicht auf der Anzahl der Primzahlen. Daher gehe ich davon aus, dass die Punktzahl höher sein muss. Siehe meinen Kommentar oben.n
? Was ist das?N=15485864
. Für Komplexitätsberechnungen basierend aufn=1000000
kann man sagenN=n*log(n)
(wegen der Dichte der Primzahlen).Haskell, n ^ 1.1 empirische Wachstumsrate, 89 Zeichen, Score 139 (?)
Das Folgende funktioniert an der GHCi-Eingabeaufforderung, wenn die verwendete allgemeine Bibliothek zuvor geladen wurde. Drucke n- te Primzahl, 1-basiert:
let s=3:minus[5,7..](unionAll[[p*p,p*p+2*p..]|p<-s])in getLine>>=(print.((0:2:s)!!).read)
Dies ist ein unbegrenztes Sieb von Eratosthenes, das eine allgemein verwendbare Bibliothek für geordnete Listen verwendet. Empirische Komplexität zwischen 100.000 und 200.000 Primzahlen
O(n^1.1)
. Passt zuO(n*log(n)*log(log n))
.Über die Komplexitätsschätzung
Ich habe die Laufzeit für 100k und 200k Primzahlen gemessen und dann berechnet
logBase 2 (t2/t1)
, was produziert hatn^1.09
. Definiereng n = n*log n*log(log n)
, RechnenlogBase 2 (g 200000 / g 100000)
gibtn^1.12
.Dann
89**1.1 = 139
, obwohlg(89) = 600
. --- (?)Es scheint, dass für die Bewertung die geschätzte Wachstumsrate anstelle der Komplexitätsfunktion selbst verwendet werden sollte. Zum Beispiel
g2 n = n*((log n)**2)*log(log n)
ist viel besser alsn**1.5
, aber für 100 Zeichen ergeben die beiden Punkte3239
und1000
. Das kann nicht richtig sein. Schätzung auf 200k / 100k Range ergibtlogBase 2 (g2 200000 / g2 100000) = 1.2
und somit Score von100**1.2 = 251
.Außerdem versuche ich nicht, alle Primzahlen auszudrucken, sondern nur die n- te Primzahl.
Keine Importe, 240 Zeichen. n ^ 1,15 empirische Wachstumsrate, Punktzahl 546.
quelle
Haskell,
7289 Zeichen, O (n 2), Score 7921Die höchste Punktzahl pro Zeichenanzahl gewinnt, oder? Geändert für das erste N. Außerdem kann ich anscheinend keinen Taschenrechner verwenden, sodass meine Punktzahl nicht so miserabel ist, wie ich dachte. (unter Verwendung der Komplexität für die grundlegende Teilung der Studie, wie in der Quelle unten zu finden).
Nach Will Ness ist das unten stehende Programm kein vollständiges Haskell-Programm (es stützt sich tatsächlich auf die REPL). Das Folgende ist ein vollständigeres Programm mit einem Pseudosieb (die Importe sparen tatsächlich ein Zeichen, aber ich mag keine Importe in Code Golf).
Diese Version ist zweifellos (n ^ 2). Der Algorithmus ist nur eine Golfversion des naiven "Siebes", wie hier Old Ghci 1 Liner zu sehen ist
Die alte, betrügerische Antwort aufzugeben, weil die Bibliothek, mit der sie verknüpft ist, ziemlich nett ist.
Siehe hier für eine Implementierung und die Links für die zeitliche Komplexität. Leider haben Räder eine log (n) Nachschlagezeit, die uns um einen Faktor verlangsamt.
quelle
C #, 447 Zeichen, Bytes 452, Score?
scriptcs Variante, 381 Zeichen, 385 Bytes, Score?
Wenn Sie scriptcs installieren, können Sie es ausführen.
PS: Ich habe das in Vim geschrieben
:D
quelle
=
und<
-Zeichen zu setzen. Ich glaube auch nicht, dass es für diesen Code einen Unterschied zwischen Bytes und Zeichen gibt - es sind 548 Zeichen und 548 Bytes.GolfScript (45 Zeichen, Spielstand beansprucht ~ 7708)
Dies führt eine einfache Versuchsteilung durch Primzahlen durch. Wenn die Arithmetik in der Nähe der Schneide von Ruby (dh unter Verwendung von 1.9.3.0) die Toom-Cook 3-Multiplikation verwendet, ist eine Testdivision O (n ^ 1.465) und die Gesamtkosten der Divisionen betragen
O((n ln n)^1.5 ln (n ln n)^0.465) = O(n^1.5 (ln n)^1.965)
†. Beim Hinzufügen eines Elements zu einem Array in GolfScript muss das Array jedoch kopiert werden. Ich habe dies so optimiert, dass die Liste der Primzahlen nur kopiert wird, wenn eine neue Primzahl gefunden wird, also nurn
mal insgesamt. Jeder Kopiervorgang hat dieO(n)
GrößeO(ln(n ln n)) = O(ln n)
† und gibt anO(n^2 ln n)
.Und deshalb, Jungs und Mädels, wird GolfScript eher zum Golfen als zum ernsthaften Programmieren verwendet.
†
O(ln (n ln n)) = O(ln n + ln ln n) = O(ln n)
. Ich hätte das sehen sollen, bevor ich verschiedene Posts kommentierte ...quelle
Das ist so einfach, dass selbst mein Texteditor das kann!
Vim: 143 Tastenanschläge (115 Aktionen): O (n ^ 2 * log (n)): Score: 101485.21
Einreichung:
Eingabe: N sollte in der ersten Zeile eines leeren Dokuments stehen. Nachdem dies beendet ist, wird jede Primzahl von 2 bis N eine separate Zeile sein.
Befehle ausführen:
Beachten Sie zunächst, dass Sie bei Befehlen, denen ein Caret vorangestellt ist, die Strg-Taste gedrückt halten und den nächsten Buchstaben eingeben müssen (z. B. ^ V ist Ctrl-vund ^ R ist Ctrl-r).
Dadurch wird alles in Ihren Registern @a, @b, @d und @p überschrieben.
Da dies qBefehle verwendet, kann es nicht einfach in ein Makro eingefügt werden. Hier sind jedoch einige Tipps zum Ausführen.
qpqqdq
löscht nur die RegisterA^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd
erstellt eine Liste mit den Nummern 2 bis N + 1. Dies ist eine Pause zwischen den beiden Hauptteilen. Wenn dies erledigt ist, sollten Sie es nicht noch einmal tun müssenmpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qqpmp"aywgg@dqgg@p
muss auf einmal eingegeben werden. Vermeiden Sie die Rücktaste, da dies zu Problemen führen kann.qdqqpq
und versuchen Sie es erneut.Für große N ist dies sehr langsam. Es dauerte ungefähr 27 Minuten, um N = 5000 auszuführen; Betrachten Sie sich als gewarnt.
Algorithmus:
Dies verwendet einen grundlegenden rekursiven Algorithmus zum Auffinden von Primzahlen. Bei einer Liste aller Primzahlen zwischen 1 und A ist A + 1 eine Primzahl, wenn sie nicht durch eine der Zahlen in der Liste der Primzahlen teilbar ist. Beginnen Sie bei A = 2 und fügen Sie der Liste Primzahlen hinzu, sobald diese gefunden wurden. Nach N Rekursionen enthält die Liste alle Primzahlen bis N.
Komplexität
Dieser Algorithmus hat eine Komplexität von O (nN), wobei N die Eingangszahl und n die Anzahl der Primzahlen bis N ist. Jede Rekursion testet n Zahlen, und N Rekursionen werden durchgeführt, was O (nN) ergibt.
N ~ n * log (n), wobei die endgültige Komplexität als O (n 2 * log (n)) angegeben wird ( https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number )
Erläuterung
Es ist nicht einfach, den Programmablauf anhand der vim-Befehle zu erkennen, daher habe ich ihn in Python nach demselben Ablauf neu geschrieben. Wie der Vim-Code wird der Python-Code am Ende fehlerhaft ausgegeben. Python mag nicht zu viele Rekursionen. Wenn Sie diesen Code mit N> 150 oder so versuchen, wird die maximale Rekursionstiefe erreicht
Nun, um die tatsächlichen Tastenanschläge aufzuschlüsseln!
qpqqdq
Löscht die Register @d und @p. Dadurch wird sichergestellt, dass beim Einrichten dieser rekursiven Makros nichts ausgeführt wird.A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dd
Verwandelt die Eingabe in eine Liste mit Zahlen von 2 bis N + 1. Der Eintrag N + 1 wird als Nebeneffekt beim Einrichten des Makros @d gelöscht.mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0q
schreibt das @d-Makro, das die obige Funktion d () implementiert. "If" -Anweisungen sind interessant in Vim zu implementieren. Mit dem Suchoperator * kann ein bestimmter Pfad ausgewählt werden. Wenn wir den Befehl weiter auflösen, erhalten wirmpqd
Setzen Sie hier die p-Markierung und starten Sie die Aufnahme des @d-Makros. Die p-Markierung muss gesetzt werden, damit es einen bekannten Punkt gibt, zu dem gesprungen werden kann, während dieser ausgeführt wirdo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>
Schreibt den if / else-Anweisungstext0*w*wyiWdd@0
führt tatsächlich die if-Anweisung aus.@a @b 0 0 `pj@p @a 0 (@a%@b) `pdd@p 0 `dj@d
0
Bewegt den Cursor an den Zeilenanfang*w*w
Bewegt den Cursor auf den Code, der als nächstes ausgeführt werden soll`pj@p
, das zur nächsten Zahl für @a wechselt und @p darauf ausführt.`pdd@p
, wenn die aktuelle Nummer @a gelöscht wird, wird @p für die nächste ausgeführt.`dj@d
die nächste Zahl für @b überprüft, um festzustellen, ob es sich um einen Faktor von @a handeltyiWdd@0
Zieht den Befehl in das Register 0, löscht die Zeile und führt den Befehl ausq
Beendet die Aufzeichnung des @d-MakrosBei der ersten Ausführung wird der
`pdd@p
Befehl ausgeführt und die Zeile N + 1 gelöscht.qpmp"aywgg@dq
Schreibt das @p-Makro, das die Nummer unter dem Cursor speichert, springt dann zum ersten Eintrag und führt @d darauf aus.gg@p
Führt tatsächlich @p aus, sodass es die gesamte Datei durchläuft.quelle
QBASIC, 98 Zeichen, Komplexität N Sqrt (N), Score 970
quelle
IF K=
(die Programmlänge würde also die Ziffer nicht enthalten). So wie es aussieht, druckt das Programm die ersten n Primzahlen ohne 2, die durch Addieren?2
am Anfang und ÄndernK=...
auf festgelegt werden könnenK=...-1
. Das Programm kann auch , indem sie die Räume aus etwas golfed werdenJ=2 TO
,J=0 THEN
,K=...-1 THEN
und durch das Einrücken zu entfernen. Ich glaube, das ergibt ein Programm mit 96 Zeichen.Scala 263 Zeichen
Aktualisiert, um den neuen Anforderungen zu entsprechen. 25% des Codes befassen sich mit dem Finden einer vernünftigen Obergrenze zum Berechnen von Primzahlen.
Ich habe auch ein Sieb.
Hier ist ein empirischer Test der Berechnungskosten, der nicht zur Analyse herangezogen wurde:
führt zu folgenden Zählungen:
Ich bin mir nicht sicher, wie ich die Punktzahl berechnen soll. Lohnt es sich, noch 5 Zeichen zu schreiben?
Für ein größeres n werden die Berechnungen in diesem Bereich um etwa 16% reduziert. Berücksichtigen wir für die Bewertungsformel jedoch keine konstanten Faktoren?
neue Big-O-Überlegungen:
Um 1 000, 10 000, 100 000 Primzahlen usw. zu finden, verwende ich eine Formel über die Dichte der Primzahlen x => (math.log (x) * x * 1,3, die die äußere Schleife bestimmt, die ich gerade durchlaufe.
Also für Werte i in 1 bis 6 => NPrimes (10 ^ i) läuft 9399, 133768 ... mal die äußere Schleife.
Ich fand diese O-Funktion iterativ mit Hilfe des Kommentars von Peter Taylor, der einen viel höheren Wert für die Potenzierung vorschlug, anstelle von 1,01 schlug er 1,5 vor:
O: (n: Int) Long
ns: List [Long] = List (102, 4152, 91532, 1612894, 25192460, 364664351)
Dies sind die Quotienten, wenn ich 1.01 als Exponenten verwende. Folgendes findet der Zähler empirisch:
Die ersten beiden Werte sind Ausreißer, da ich meine Schätzformel für kleine Werte (bis zu 1000) konstant korrigiert habe.
Mit Peter Taylors Vorschlag von 1.5 würde es so aussehen:
Jetzt mit meinem Wert komme ich zu:
Ich bin mir aber nicht sicher, wie nahe ich mit meiner O-Funktion an die beobachteten Werte herankommen kann.
quelle
O(M^1.5 / ln M)
und jedes Mal, wenn SieO(ln M)
arbeiten (Addition), also insgesamtO(M^1.5) = O((n ln n)^1.5)
.def O(n:Int) = (math.pow((n * math.log (n)), 1.02)).toLong
komme ich den mit meinem Zähler empirisch ermittelten Werten viel näher. Ich füge meine Ergebnisse in meinen Beitrag ein.Ruby 66 Zeichen, O (n ^ 2) Score - 4356
lazy
ist seit Ruby 2.0 verfügbar und1.0/0
ist ein cooler Trick, um eine unendliche Reichweite zu erhalten:quelle
(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.take(n).to_a
(2..(1.0/0)).lazy.select{|i|(2..i).one?{|j|i%j<1}}.take(n).to_a
. Dies spart zwei weitere Zeichen.(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.first(n)
61 Zeichen.Ruby, 84 Zeichen, 84 Bytes, Score?
Dieser ist wahrscheinlich ein bisschen zu neu für diese Teile, aber ich hatte eine lustige Zeit dabei. Es wird einfach wiederholt, bis
f
(gefundene Primzahlen)n
der gewünschten Anzahl gefundener Primzahlen entspricht.Der unterhaltsame Teil ist, dass für jede Schleife ein Array von 2 bis eins weniger als die Zahl erstellt wird, die geprüft wird. Dann ordnet es jedes Element im Array als Modul der ursprünglichen Zahl und des Elements zu und prüft, ob eines der Ergebnisse Null ist.
Außerdem habe ich keine Ahnung, wie ich es erzielen soll.
Aktualisieren
Der Code wurde komprimiert und enthielt einen (völlig willkürlichen) Wert für
n
Original
Das
i += 1
Bit und deruntil
Loop springen mir irgendwie als Verbesserungspotential entgegen, aber auf dieser Strecke stecke ich irgendwie fest. Jedenfalls hat es Spaß gemacht, darüber nachzudenken.quelle
Scala, 124 Zeichen
Einfache Versuchsaufteilung bis zur Quadratwurzel. Die Komplexität sollte daher O (n ^ (1,5 + epsilon)) sein.
124 ^ 1.5 <1381, also würde das wohl meine Punktzahl sein?
quelle
Perl - 94 Zeichen, O (n log (n)) - Score: 427
Python - 113 Zeichen
quelle
AWK,
9686 BytesUntertitel: Schau Mama! Nur hinzufügen und etwas Buchhaltung!
Datei
fsoe3.awk
:Lauf:
BASH, 133 Bytes
Datei
x.bash
:Lauf:
Primzahlen werden berechnet, indem die bereits gefundenen Primzahlen auf das "Band positiver Ganzzahlen" springen. Grundsätzlich handelt es sich um ein serialisiertes Sieb von Eratosthenes.
... ist der gleiche Algorithmus in Python und gibt die Zeit aus, zu der die
l
-te Primzahl statt der Primzahl selbst gefunden wurde.Die mit geplottete Ausgabe
gnuplot
ergibt Folgendes:Die Sprünge haben wahrscheinlich etwas mit Datei-E / A-Verzögerungen zu tun, die durch das Schreiben von gepufferten Daten auf die Festplatte verursacht wurden ...
Die Verwendung einer viel größeren Anzahl von Primzahlen zum Auffinden bringt zusätzliche systemabhängige Verzögerungen in das Spiel, z. B. wächst das Array, das das "Band positiver Ganzzahlen" darstellt, kontinuierlich und wird früher oder später jeden Computer dazu bringen, nach mehr RAM zu verlangen (oder später zu tauschen).
... daher hilft es nicht viel, sich anhand der experimentellen Daten ein Bild von der Komplexität zu machen ... :-(
Zählen Sie nun die Ergänzungen, die zum Finden von
n
Primzahlen erforderlich sind :quelle
Gnuplot
mitset term xterm
und dann Screenshot vonxterm
's Grafikfenster (wahrscheinlich ein fast vergessenes Feature). ;-)Scala 121 (99 ohne Boilerplate der Hauptklasse)
quelle
Python 3,
117106 BytesDiese Lösung ist etwas trivial, da sie 0 ausgibt, wenn eine Zahl keine Primzahl ist, aber ich werde sie trotzdem posten:
Ich bin mir auch nicht sicher, wie ich die Komplexität eines Algorithmus berechnen soll. Bitte stimmen Sie deshalb nicht ab. Sei stattdessen nett und kommentiere, wie ich es herausfinden könnte. Sagen Sie mir auch, wie ich das verkürzen könnte.
quelle
print(i)
auf der gleichen Linie wie die for - Schleife und entfernen Sie die Räume anin [2]
,0 if
,0 in [i%j
und+1,2)] else
.Haskell (52² = 2704)
quelle
Perl 6, 152 Bytes, O (n Protokoll n Protokoll (n Protokoll n) Protokoll (Protokoll (n Protokoll n)) (?), 9594,79 Punkte
Nach dieser Seite ist die Bitkomplexität des Findens aller Primzahlen bis zu n O (n log n log log n); Die obige Komplexität nutzt die Tatsache, dass die n-te Primzahl proportional zu n log n ist.
quelle
Groovy (50 Bytes) - O (n * sqrt (n)) - Ergebnis 353,553390593
Nimmt n auf und gibt alle Zahlen von 1 bis n aus, die Primzahlen sind.
Der Algorithmus, den ich ausgewählt habe, gibt nur Primzahlen n> 2 aus, daher ist das Hinzufügen von 1,2 am Anfang erforderlich.
Nervenzusammenbruch
x%it
- Implizite Wahrheit, wenn sie nicht teilbar ist, falsch, wenn sie es ist.(2..x**0.5).every{...}
- Stellen Sie für alle Werte zwischen 2 und sqrt (x) sicher, dass sie nicht teilbar sind, damit true zurückgegeben wird, muss true für jeden zurückgegeben werden .(1..it).findAll{x->...}
- Finden Sie für alle Werte zwischen 1 und n alle Werte, die den Kriterien der Nichtteilbarkeit zwischen 2 und sqrt (n) entsprechen.{[1,2]+...}
- Addiere 1 und 2, weil sie immer Primzahlen sind und niemals vom Algorithmus abgedeckt werden.quelle
Schläger 155 Bytes
Es führt eine Liste der gefundenen Primzahlen und überprüft die Teilbarkeit jeder nächsten Zahl durch bereits gefundene Primzahlen. Außerdem wird nur bis zur Quadratwurzel der getesteten Zahl geprüft, da dies ausreicht.
Ungolfed:
Testen:
Ausgabe:
quelle
awk 45 (Komplexität N ^ 2)
eine andere
awk
für Primzahlen bis zu 100Code Golf gezählt Teil ist
die kann in eine Skriptdatei gestellt und ausgeführt werden als
awk -f prime.awk <(seq 100)
quelle
Javascript, 61 Zeichen
Ein bisschen schlechter als O (n ^ 2), hat kein Stapelspeicher mehr für großes n.
quelle