Liste der ersten n Primzahlen am effizientesten und im kürzesten Code [geschlossen]

27

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.

Optimus
quelle
5
Dies ist codegolf.stackexchange.com/questions/5977/… sehr ähnlich .
Gareth
2
Meine Antwort auf diese Frage war 1[\p:i.78498meine Antwort darauf 1[\p:i.1000000. Selbst wenn Js interner Prim-Algorithmus O (n ^ 2) ist, würde mein Score immer noch nur 196 sein.
Gareth
2
Niemand scheint es zu schaffen, ihre Komplexität richtig zu berechnen. Es gibt Verwirrung darüber , ob ndie Anzahl der Primzahlen oder die maximalen Primzahl, und jeder ignoriert die Tatsache , dass die Zugabe von Zahlen im Bereich 0..nist O(logn), und die Multiplikation und Division ist noch teurer. Ich schlage vor, dass Sie einige Beispielalgorithmen zusammen mit ihrer korrekten Komplexität angeben.
Ugoren
3
Der derzeit bekannteste Primalitätstest für eine k-Bit-Zahl ist O-tilde(k^6). Dies führt zu der Folgerung, dass jeder, der eine bessere Laufzeit behauptet, als O-tilde(n ln n (ln(n ln n))^6)einen Teil des Problems missverstanden hat; und auf die Frage, wie mit O-tildeKomplexität in der Wertung umgegangen werden soll.
Peter Taylor
2
Niemand hat darauf hingewiesen, dass O (n) in Bezug auf die Komplexität mit O (kn) (für die Konstante k) äquivalent ist, jedoch nicht in Bezug auf die Punktzahl. Angenommen, meine Komplexität ist O (n ^ 10). Das entspricht O (n ^ 10 * 1E-308), und ich kann die Herausforderung immer noch mit einem riesigen Programm mit schrecklicher Komplexität gewinnen.
JDL

Antworten:

10

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.

N=15485864
a=[1]*N
x=xrange
for i in x(2,3936):
 if a[i]:
  for j in x(i*i,N,i):a[j]=0
print [i for i in x(len(a))if a[i]==1][2:]

Verbesserter Code von vor.

Python ( 191 156 152 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.

from math import log as l
n=input()
N=n*int(l(n)+l(l(n)))
a=range(2,N)
for i in range(int(n**.5)+1):
 a=filter(lambda x:x%a[i] or x==a[i],a)
print a[:n]

n*int(l(n)+l(l(n)))ist die obere Grenze der nth Primzahl.

beary605
quelle
1
Die Berechnung der Komplexität (und damit der Punktzahl) basiert auf der Obergrenze, njedoch nicht auf der Anzahl der Primzahlen. Daher gehe ich davon aus, dass die Punktzahl höher sein muss. Siehe meinen Kommentar oben.
Howard
Obergrenze n? Was ist das?
beary605
Die Obergrenze ist hier N=15485864. Für Komplexitätsberechnungen basierend auf n=1000000kann man sagen N=n*log(n)(wegen der Dichte der Primzahlen).
Ugoren
Wenn meine Punktzahl korrigiert werden muss, korrigieren Sie sie bitte für mich. Ich verstehe das Punktesystem immer noch nicht gut.
beary605
@ beary605 wäre es in ordnung, wenn ich die probleme dahingehend modifizieren würde, zuerst n primes zu finden? das würde eine Menge Verwirrung über die Komplexität und was n in O (f (n)) ist lösen
Optimus
7

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 zu O(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 hat n^1.09. Definieren g n = n*log n*log(log n), Rechnen logBase 2 (g 200000 / g 100000)gibt n^1.12.

Dann 89**1.1 = 139, obwohl g(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 als n**1.5, aber für 100 Zeichen ergeben die beiden Punkte 3239und 1000. Das kann nicht richtig sein. Schätzung auf 200k / 100k Range ergibt logBase 2 (g2 200000 / g2 100000) = 1.2und somit Score von 100**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.

main=getLine>>=(print.s.read)
s n=let s=3:g 5(a[[p*p,p*p+2*p..]|p<-s])in(0:2:s)!!n
a((x:s):t)=x:u s(a$p t)
p((x:s):r:t)=(x:u s r):p t
g k s@(x:t)|k<x=k:g(k+2)s|True=g(k+2)t
u a@(x:r)b@(y:t)=case(compare x y)of LT->x:u r b;EQ->x:u r t;GT->y:u a t
Will Ness
quelle
5

Haskell, 72 89 Zeichen, O (n 2), Score 7921

Die 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).

main=getLine>>= \x->print.take(read x).(let s(x:y)=x:s(filter((>0).(`mod`x))y)in s)$[2..]

Diese Version ist zweifellos (n ^ 2). Der Algorithmus ist nur eine Golfversion des naiven "Siebes", wie hier Old Ghci 1 Liner zu sehen ist

getLine>>= \x->print.take(read x)$Data.List.nubBy(\x y->x`mod`y==0)[2..]

Die alte, betrügerische Antwort aufzugeben, weil die Bibliothek, mit der sie verknüpft ist, ziemlich nett ist.

print$take(10^6)Data.Numbers.Primes.primes

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.

walpen
quelle
• Primzahlen können nicht durch eine eingebaute Funktion oder durch eine Bibliothek generiert werden
beary605
@walpen Es tut mir leid, dass ich die Regeln ohne Benachrichtigung geändert habe. Bitte nehmen Sie die Änderungen nach Belieben vor
Optimus
Wäre die Komplexität nicht so etwas wie O ((n ln n) ^ 1,5 ln (n ln n) ^ 0,585)? (Oder O ((n ln n) ^ 1,5 ln (n ln n)), wenn Haskell naive Division verwendet, anstatt, wie ich angenommen habe, Karatsuba)
Peter Taylor
Nein, denn das gibt mir eine horrende Punktzahl: /. Aber ich bin sicher, du hast recht. Es sah aus wie eine Probedivision, und das ist die zeitliche Komplexität der Probedivision (nach meinem schlechten Leseverständnis einer möglicherweise falschen Quelle). Im Moment nenne ich meine Punktzahl NaN, das scheint sicher zu sein.
Walpen
Ich gehe davon aus (mein Haskell ist vernachlässigbar, aber ich weiß, wie es natürlich wäre, es in SML zu tun ...), dass Sie nur eine Versuchsteilung durch kleinere Primzahlen durchführen. In diesem Fall macht die Versuchsteilung auf einem P O ( P ^ 0,5 / ln P) Teilungen. Wenn P jedoch k Bits hat, benötigt eine Division die Zeit O (k ^ 1.585) (Karatsuba) oder O (k ^ 2) (naiv), und Sie müssen O (n lg n) Zahlen der Länge O (ln ( n lg n)) Bits.
Peter Taylor
5

C #, 447 Zeichen, Bytes 452, Score?

using System;namespace PrimeNumbers{class C{static void GN(ulong n){ulong primes=0;for (ulong i=0;i<(n*3);i++){if(IP(i)==true){primes++;if(primes==n){Console.WriteLine(i);}}}}static bool IP(ulong n){if(n<=3){return n>1;}else if (n%2==0||n%3==0){return false;}for(ulong i=5;i*i<=n;i+=6){if(n%i==0||n%(i+2)==0){return false;}}return true;}static void Main(string[] args){ulong n=Convert.ToUInt64(Console.ReadLine());for(ulong i=0;i<n;i++){GN(i);}}}}

scriptcs Variante, 381 Zeichen, 385 Bytes, Score?

using System;static void GetN(ulong n){ulong primes=0;for (ulong i=0;i<(n*500);i++){if(IsPrime(i)==true){primes++;if(primes==n){Console.WriteLine(i);}}}}public static bool IsPrime(ulong n){if(n<=3){return n>1;}else if (n%2==0||n%3==0){return false;}for(ulong i=5;i*i<=n;i+=6){if(n%i==0||n%(i+2)==0){return false;}}return true;}ulong n=Convert.ToUInt64(Console.ReadLine());for(ulong i=0;i<n;i++){GetN(i);}

Wenn Sie scriptcs installieren, können Sie es ausführen.

PS: Ich habe das in Vim geschrieben :D

XiKuuKy
quelle
2
Sie können einige Zeichen speichern, indem Sie unnötige Leerzeichen entfernen. Beispielsweise ist es nicht erforderlich, Leerzeichen um ein =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.
ProgramFOX
2
Oh danke, das ist mein erster CodeGolf!
XiKuuKy
4

GolfScript (45 Zeichen, Spielstand beansprucht ~ 7708)

~[]2{..3${1$\%!}?={.@\+\}{;}if)1$,3$<}do;\;n*

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 nur nmal insgesamt. Jeder Kopiervorgang hat die O(n)Größe O(ln(n ln n)) = O(ln n)† und gibt an O(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 ...

Peter Taylor
quelle
4

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:

qpqqdqA^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"ddmpqdmd"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

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 Register
  • A^V^Ayyp<Esc>3h"aC@a<Esc>0C1<Esc>@"dderstellt 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üssen
  • mpqdmd"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@pmuss auf einmal eingegeben werden. Vermeiden Sie die Rücktaste, da dies zu Problemen führen kann.
    • Wenn Sie einen Fehler machen, geben Sie Folgendes ein qdqqpqund 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

N = 20
primes = range(2, N+1)

# Python needs these defined.
mark_p = b = a = -1

# Check new number for factors. 
# This macro could be wrapped up in @d, but it saves space to leave it separate.
def p():
    global mark_d, mark_p, primes, a
    mark_d = 0
    print(primes)
    a = primes[mark_p]
    d()      

# Checks factor and determine what to do next
def d():
    global mark_d, mark_p, a, b, primes
    b = primes[mark_d]
    if(a == b): # Number is prime, check the next number
        mark_p += 1
        p()
    else:
        if(a%b == 0): # Number is not prime, delete it and check next number
            del(primes[mark_p])
            p()
        else: # Number might be prime, try next possible factor
            mark_d += 1
            d()

mark_p = 0 #Start at first number         
p()

Nun, um die tatsächlichen Tastenanschläge aufzuschlüsseln!

  • qpqqdqLö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>@"ddVerwandelt 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.

    • Schreibt speziell ein Makro, das eine Zahl inkrementiert, kopiert es dann in die nächste Zeile, schreibt dann eine 1 und führt dieses Makro N-mal aus.
  • mpqdmd"bywo^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc>0*w*wyiWdd@0qschreibt 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 wir

    • mpqdSetzen 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 wird
    • o^Ra ^Rb 0 0 `pj@p ^Ra 0 ^R=@a%@b<Enter> `pdd@p 0 `dj@d<Esc> Schreibt den if / else-Anweisungstext
    • 0*w*wyiWdd@0 führt tatsächlich die if-Anweisung aus.
    • Vor dem Ausführen dieses Befehls enthält die Zeile @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

      1. wenn @a == @b, das heißt `pj@p, das zur nächsten Zahl für @a wechselt und @p darauf ausführt.
      2. Wenn @a! = @b und @a% @b == 0, das heißt `pdd@p, wenn die aktuelle Nummer @a gelöscht wird, wird @p für die nächste ausgeführt.
      3. Wenn @a! = @b und @a %%b! = 0 ist, wird `dj@ddie nächste Zahl für @b überprüft, um festzustellen, ob es sich um einen Faktor von @a handelt
    • yiWdd@0 Zieht den Befehl in das Register 0, löscht die Zeile und führt den Befehl aus

    • q Beendet die Aufzeichnung des @d-Makros
  • Bei der ersten Ausführung wird der `pdd@pBefehl 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.

Dominic A.
quelle
3

QBASIC, 98 Zeichen, Komplexität N Sqrt (N), Score 970

I=1
A:I=I+2
FOR J=2 TO I^.5
    IF I MOD J=0 THEN GOTO A
NEXT
?I
K=K+1
IF K=1e6 THEN GOTO B
GOTO A
B:
Kibbee
quelle
Ich habe die Problembeschreibung ein wenig geändert. Jetzt werden die ersten "n" Primzahlen gefunden. Es tut mir leid, dass ich keine Benachrichtigung erhalten habe
Optimus
Ich nehme an, wir können "In-Source" -Eingaben für dieses Programm annehmen. dh die Eingabe ist die Ziffer direkt nach dem 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 ?2am Anfang und Ändern K=...auf festgelegt werden können K=...-1. Das Programm kann auch , indem sie die Räume aus etwas golfed werden J=2 TO, J=0 THEN, K=...-1 THENund durch das Einrücken zu entfernen. Ich glaube, das ergibt ein Programm mit 96 Zeichen.
Res
3

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.

object P extends App{
def c(M:Int)={
val p=collection.mutable.BitSet(M+1)
p(2)=true
(3 to M+1 by 2).map(p(_)=true)
for(i<-p){
var j=2*i;
while(j<M){
if(p(j))p(j)=false
j+=i}
}
p
}
val i=args(0).toInt
println(c(((math.log(i)*i*1.3)toInt)).take(i).mkString("\n"))
}

Ich habe auch ein Sieb.

Hier ist ein empirischer Test der Berechnungskosten, der nicht zur Analyse herangezogen wurde:

object PrimesTo extends App{
    var cnt=0
    def c(M:Int)={
        val p=(false::false::true::List.range(3,M+1).map(_%2!=0)).toArray
        for (i <- List.range (3, M, 2)
            if (p (i))) {
                var j=2*i;
                while (j < M) {
                    cnt+=1
                    if (p (j)) 
                        p(j)=false
                    j+=i}
            }
        (1 to M).filter (x => p (x))
    }
    val i = args(0).toInt
    /*
        To get the number x with i primes below, it is nearly ln(x)*x. For small numbers 
        we need a correction factor 1.13, and to avoid a bigger factor for very small 
        numbers we add 666 as an upper bound.
    */
    val x = (math.log(i)*i*1.13).toInt+666
    println (c(x).take (i).mkString("\n"))
    System.err.println (x + "\tcount: " + cnt)
}
for n in {1..5} ; do i=$((10**$n)); scala -J-Xmx768M P $i ; done 

führt zu folgenden Zählungen:

List (960, 1766, 15127, 217099, 2988966)

Ich bin mir nicht sicher, wie ich die Punktzahl berechnen soll. Lohnt es sich, noch 5 Zeichen zu schreiben?

scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.13).toInt+666) 
res42: List[Int] = List(672, 756, 1638, 10545, 100045, 1000419, 10068909, 101346800, 1019549994)

scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.3)toInt) 
res43: List[Int] = List(7, 104, 1119, 11365, 114329, 1150158, 11582935, 116592898, 1172932855)

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:

def O(n:Int) = (math.pow((n * math.log (n)), 1.01)).toLong

O: (n: Int) Long

val ns = List(10, 100, 1000, 10000, 100000, 1000*1000).map(x=>(math.log(x)*x*1.3)toInt).map(O) 

ns: List [Long] = List (102, 4152, 91532, 1612894, 25192460, 364664351)

 That's the list of upper values, to find primes below (since my algorithm has to know this value before it has to estimate it), send through the O-function, to find similar quotients for moving from 100 to 1000 to 10000 primes and so on: 

(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
40.705882352941174
22.045279383429673
17.62109426211598
15.619414543051187
14.47513863274964
13.73425213148954

Dies sind die Quotienten, wenn ich 1.01 als Exponenten verwende. Folgendes findet der Zähler empirisch:

ns: Array[Int] = Array(1628, 2929, 23583, 321898, 4291625, 54289190, 660847317)

(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
1.799140049140049
8.051553431205189
13.649578085909342
13.332251210010625
12.65003116535112
12.172723833234572

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:

245.2396265560166
98.8566987153728
70.8831374743478
59.26104390040363
52.92941829568069
48.956394784317816

Jetzt mit meinem Wert komme ich zu:

O(263)
res85: Long = 1576

Ich bin mir aber nicht sicher, wie nahe ich mit meiner O-Funktion an die beobachteten Werte herankommen kann.

Benutzer unbekannt
quelle
Tut mir leid, ich habe einige Änderungen an der Problembeschreibung vorgenommen, um die Mehrdeutigkeit im Zusammenhang mit der Komplexität zu verringern (ich bin sicher, dass sich an Ihrer Lösung nicht viel ändert)
Optimus,
Dies ist effektiv eine Versuchsteilung durch Primzahlen. Die Anzahl der Durchläufe durch die innere Schleife ist O(M^1.5 / ln M)und jedes Mal, wenn Sie O(ln M)arbeiten (Addition), also insgesamt O(M^1.5) = O((n ln n)^1.5).
Peter Taylor
Mit ^ 1.02 statt ^ 1.5 def O(n:Int) = (math.pow((n * math.log (n)), 1.02)).toLongkomme ich den mit meinem Zähler empirisch ermittelten Werten viel näher. Ich füge meine Ergebnisse in meinen Beitrag ein.
Benutzer unbekannt
3

Ruby 66 Zeichen, O (n ^ 2) Score - 4356

lazyist seit Ruby 2.0 verfügbar und 1.0/0ist ein cooler Trick, um eine unendliche Reichweite zu erhalten:

(2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j==0}}.take(n).to_a
Uri Agassi
quelle
1
Sie können ein (2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.take(n).to_a
Zeichen
Oder sogar: (Dies macht die Lösung weniger effizient, ändert aber nicht die obere O (n²) -Grenze) (2..(1.0/0)).lazy.select{|i|(2..i).one?{|j|i%j<1}}.take(n).to_a. Dies spart zwei weitere Zeichen.
Qqwy
Wenn Sie dies ändern, erhalten Sie (2..(1.0/0)).lazy.select{|i|!(2...i).any?{|j|i%j<1}}.first(n)61 Zeichen.
Richie
2

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) nder 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

n,f,i=5**5,0,2
until f==n;f+=1;p i if !(2...i).to_a.map{|j|i%j}.include?(0);i+=1;end

Original

f, i = 0, 2
until f == n
  (f += 1; p i) if !(2...i).to_a.map{|j| i % j}.include?(0)
  i += 1
end

Das i += 1Bit und der untilLoop springen mir irgendwie als Verbesserungspotential entgegen, aber auf dieser Strecke stecke ich irgendwie fest. Jedenfalls hat es Spaß gemacht, darüber nachzudenken.

tydotg
quelle
2

Scala, 124 Zeichen

object Q extends App{Stream.from(2).filter(p=>(2 to p)takeWhile(i=>i*i<=p)forall{p%_!= 0})take(args(0)toInt)foreach println}

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?

Jin
quelle
1

Perl - 94 Zeichen, O (n log (n)) - Score: 427

perl -wle '$n=1;$t=1;while($n<$ARGV[0]){$t++;if((1x$t)!~/^1?$|^(11+?)\1+$/){print $t;$n++;}}'

Python - 113 Zeichen

import re
z = int(input())
n=1
t=1
while n<z:
    t+=1
    if not re.match(r'^1?$|^(11+?)\1+$',"1"*t):
        print t
        n+=1
alfasin
quelle
1

AWK, 96 86 Bytes

Untertitel: Schau Mama! Nur hinzufügen und etwas Buchhaltung!

Datei fsoe3.awk:

{for(n=2;l<$1;){if(n in L)p=L[n]
else{print p=n;l++}
for(N=p+n++;N in L;)N+=p
L[N]=p}}

Lauf:

$ awk -f fsoe3.awk <<< 5
2
3
5
7
11
$ awk -f fsoe3.awk <<< 1000 | wc -l
1000

BASH, 133 Bytes

Datei x.bash:

a=2
while((l<$1));do if((b[a]))
then((c=b[a]));else((c=a,l++));echo $a;fi;((d=a+c))
while((b[d]));do((d+=c));done
((b[d]=c,a++));done

Lauf:

$ bash x.bash 5
2
3
5
7
11
$ bash x.bash 1000 | wc -l
1000

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.

from time import time as t

L = {}
n = 2
l = 0

t0=t()

while l<1000000:

        if n in L:
                P = L[n]
        else:
                P = n
                l += 1
                print t()-t0

        m = n+P
        while m in L:
                m += P
        L[m] = P

        n += 1

... 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 gnuplotergibt Folgendes:

Bildbeschreibung hier eingeben

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 nPrimzahlen erforderlich sind :

cells = {}
current = 2
found = 0

additons = 0

while found < 10000000:

        if current in cells:
                candidate = cells[current]
                del cells[current] # the seen part is irrelevant
        else:
                candidate = current
                found += 1 ; additons += 1
                print additons

        destination = current + candidate ; additons += 1
        while destination in cells:
                destination += candidate ; additons += 1
        cells[destination] = candidate

        current += 1 ; additons += 1

Bildbeschreibung hier eingeben


quelle
Wie haben Sie diese Grafiken erstellt?
Katze
1
Gnuplotmit set term xtermund dann Screenshot von xterm's Grafikfenster (wahrscheinlich ein fast vergessenes Feature). ;-)
0

Scala 121 (99 ohne Boilerplate der Hauptklasse)

object Q extends App{Stream.from(2).filter{a=>Range(2,a).filter(a%_==0).isEmpty}.take(readLine().toInt).foreach(println)}
Krzysztof Wende
quelle
0

Python 3, 117 106 Bytes

Diese Lösung ist etwas trivial, da sie 0 ausgibt, wenn eine Zahl keine Primzahl ist, aber ich werde sie trotzdem posten:

r=range
for i in[2]+[i*(not 0 in[i%j for j in r(3,int(i**0.5)+1,2)])for i in r(3,int(input()),2)]:print(i)

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.

0WJYxW9FMN
quelle
Ich glaube , Sie das setzen kann print(i)auf der gleichen Linie wie die for - Schleife und entfernen Sie die Räume an in [2], 0 if, 0 in [i%jund +1,2)] else.
Acrolith
@daHugLenny Wow, vielen Dank! Ich bearbeite meinen Beitrag in einer Sekunde. :-D
0WJYxW9FMN
@daHugLenny Würdest du zufällig wissen, wie die Effizienz berechnet wird?
0WJYxW9FMN
Nein Entschuldigung. (Kommentare müssen mindestens 15 Zeichen lang sein)
acrolith
Danke trotzdem. Sie haben mein Programm zum kürzesten hier gemacht!
0WJYxW9FMN
0

Haskell (52² = 2704)

52`take`Data.List.nubBy(((1<).).gcd)[2..]`forM_`print
Roman Czyborra
quelle
0

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.

my \N=+slurp;my \P=N*(N.log+N.log.log);my @a=1 xx P;for 2..P.sqrt ->$i {if @a[$i] {@a[$_*$i]=0 for $i..P/$i}};say $_[1] for (@a Z ^P).grep(*[0])[2..N+1]
bb94
quelle
qualifiziert sich nicht, machen Sie es in Wentel, um sich zu qualifizieren
noɥʇʎԀʎzɥʇʎԀʎ
Verzeihung, aber was meinst du?
BB94
für das Kopfgeld (fiiiiiiiiilerrrrr)
noɥʇʎԀʎzɐɹƆ
0

Groovy (50 Bytes) - O (n * sqrt (n)) - Ergebnis 353,553390593

{[1,2]+(1..it).findAll{x->(2..x**0.5).every{x%it}}​}​

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.

Magische Kraken-Urne
quelle
0

Schläger 155 Bytes

(let p((o'(2))(c 3))(cond[(>=(length o)n)(reverse o)][(ormap(λ(x)(= 0(modulo c x)))
(filter(λ(x)(<= x(sqrt c)))o))(p o(add1 c))][(p(cons c o)(add1 c))]))

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:

(define(nprimes n)
  (let loop ((outl '(2))                   ; outlist having primes being created
             (current 3))                  ; current number being tested
  (cond
    [(>= (length outl) n) (reverse outl)]  ; if n primes found, print outlist.
    [(ormap (λ(x) (= 0 (modulo current x))) ; test if divisible by any previously found prime
            (filter                         ; filter outlist till sqrt of current number
             (λ(x) (<= x (sqrt current)))
             outl))
     (loop outl (add1 current)) ]           ; goto next number without adding to prime list
    [else (loop (cons current outl) (add1 current))] ; add to prime list and go to next number
    )))

Testen:

(nprimes 35)

Ausgabe:

'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149)
rnso
quelle
0

awk 45 (Komplexität N ^ 2)

eine andere awkfür Primzahlen bis zu 100

awk '{for(i=2;i<=sqrt(NR);i++) if(!(NR%i)) next} NR>1' <(seq 100)

Code Golf gezählt Teil ist

{for(i=2;i<=sqrt(NR);i++)if(!(NR%i))next}NR>1

die kann in eine Skriptdatei gestellt und ausgeführt werden als awk -f prime.awk <(seq 100)

Karakfa
quelle
0

Javascript, 61 Zeichen

f=(n,p=2,i=2)=>p%i?f(n,p,++i):i==p&&n--&alert(p)||n&&f(n,++p)

Ein bisschen schlechter als O (n ^ 2), hat kein Stapelspeicher mehr für großes n.

SudoNhim
quelle