Finden Sie die größte Primzahl, deren Länge, Summe und Produkt die Primzahl ist

37

Die Zahl 113ist die erste Primzahl, deren Länge 3Primzahl, digitale Summe 5 = 1 + 1 + 3Primzahl und digitales Produkt 3 = 1 * 1 * 3Primzahl ist.

Eine Primzahl mit diesen drei Eigenschaften wird als höchste Primzahl bezeichnet . Die Primzahlen 11117und 1111151sind andere Beispiele.

Tor

Schreiben Sie ein Programm, das die größte findet höchst prime Zahl möglich in weniger als eine Stunde auf einem anständigen modernen Personal - Computer (wie die bevorzugte spec hier ).

Sie sollten uns nicht einfach eine große höchste Priorität geben. Sie müssen uns Ihren Suchvorgang mit tatsächlich funktionierendem Code zeigen. Sie können auf den Lösungen Ihrer Mitarbeiter oder anderer Personen aufbauen, aber Sie sollten ihnen unbedingt Anerkennung zollen. Wir versuchen gemeinsam, die höchste auf einem normalen Computer realisierbare Primzahl in einer Stunde zu finden.

Wertung

Die Einreichung, die die größte höchste Primzahl findet, gewinnt. Wenn sich herausstellt, dass es endlich viele höchste Primzahlen gibt, gewinnt die erste Einreichung, die die höchsten höchsten Primzahlen generiert.

(Wenn Sie mathematisch beweisen können, dass es unendlich viele höchste Primzahlen gibt oder nicht, gebe ich Ihnen 200 Kopfgeld-Wiederholungen, nur weil. :))

Einzelheiten

  • Sie können jede Quelle verwenden, um Ihre Primzahlen zu generieren (z. B. Internet).
  • Sie können probabilistische Primärtestmethoden anwenden.
  • Alles ist in der Basis 10.
  • Null und Eins werden NICHT als Primzahl betrachtet.
  • Primzahlen, die enthalten, 0haben ein digitales Produkt von 0so offensichtlich, dass sie nicht überlegen sein können.
  • Um die Seite übersichtlicher zu halten, setzen Sie große (über 100-stellige) oberste Primzahlen in die Form:

    {[number of 1's before the prime digit]}[prime digit]{[number of 1's after the prime digit]}
    

    So 1111151könnte ausgedrückt werden als {5}5{1}.

Calvins Hobbys
quelle
Können wir mit einer Liste von Primzahlen beginnen oder eine Liste aus dem Internet abrufen und die Stunde damit verbringen, Überlegenheitsprüfungen durchzuführen?
Sparr
2
Wenn Sie mit der höchsten bekannten höchsten Primzahl beginnen können, wird dies zu einer Herausforderung für diejenigen, die ein Programm schreiben können, das genau eine Stunde lang die größtmögliche Lücke zwischen zwei höchsten Primzahlen überspannt. :(
Sparr
8
Abgesehen davon, dass es keine 0 gibt, muss jede mögliche höchste Primzahl offensichtlich die Form 1 ^ n [3 | 5 | 7] 1 ^ m haben, dh einige 1s, alle Primzahlen unter 10 und einige weitere 1s. Es gibt weitere Einschränkungen, die Sie sofort anwenden können.
Ingo Bürk
3
Ryan hat eine verwandte Frage zu MSE in Bezug auf die Existenz unendlich vieler höchster Primzahlen gestellt. Wenn Sie irgendwelche Einsichten für diese Frage haben, wiegen Sie sich bitte ein!
Semiclassical
1
Ich kann leicht zeigen, dass es derzeit keinen Beweis für eine unendliche Anzahl höchster Primzahlen gibt (und dass ein erheblicher Arbeitsaufwand dafür aufgewendet wurde). Laut michaelnielsen.org/polymath1/… wissen wir, dass Primzahlen mit Lücken von nur 246 unendlich weiterkommen , aber für einen Beweis von unendlichen höchsten Primzahlen benötigen wir eine Lücke von 2, 4 oder 6 (entsprechend den Primzahlen mit eine 3, 5 oder 7 irgendwo in ihnen).
Tim S.

Antworten:

9

Perl, 15101 Ziffern, {83} 7 {15017}, 8 Minuten. Max gefunden: 72227 Stellen

Mit meinem Modul Math :: Prime :: Util und seinem GMP- Backend . Es verfügt über eine Reihe von Komposititätstests, darunter is_prob_prime () mit einem ES BPSW-Test (etwas strenger als Paris ispseudoprime), is_prime (), der einen MR auf Zufallsbasis hinzufügt, und is_provable_prime (), der BLS75 T5 oder ECPP ausführt. Bei diesen Größen und Typen wird das Erstellen eines Proofs viel Zeit in Anspruch nehmen. Ich habe einen weiteren MR-Test im Sub Pedantic Verifier durchgeführt. Mal auf einem Core2 E7500 was definitiv nicht mein schnellster Computer ist (es dauert 2,5 Minuten auf meinem i7-4770K).

Wie Tim S. betont, könnten wir weiter nach größeren Werten suchen, bis zu dem Punkt, an dem ein einzelner Test eine Stunde dauert. Bei ~ 15000 Stellen auf diesem E7500 dauert ein MR-Test etwa 26 Sekunden und der gesamte is_prime-Test 2 Minuten (Versuchsdivision plus Basis-2-MR plus ES Lucas plus ein Zufallsbasis-MR). Mein i7-4770K ist über 3x schneller. Ich habe ein paar Größen ausprobiert, hauptsächlich um zu sehen, wie sich das auf die Ergebnisse anderer auswirkt. Ich habe 8k, 20k und 16k ausprobiert und jeweils nach ~ 5 Minuten getötet. Ich habe dann 15k in Progression für jeweils ~ 10m ausprobiert und beim 4. Glück gehabt.

Die PRP-Tests von OpenPFGW sind mit Sicherheit nach etwa 4000 Stellen schneller und in der Tat viel schneller im Bereich von über 50.000. Der Test enthält jedoch eine ganze Reihe von Fehlalarmen, was ihn zu einem großartigen Vortest macht, aber man möchte die Ergebnisse trotzdem mit etwas anderem überprüfen.

Dies könnte mit Perl-Threads oder mit MCE parallelisiert werden, ähnlich den parallelen Fibonacci-Prime-Finder-Beispielen im Modul.

Timing und Ergebnisse auf einem inaktiven i7-4770K mit Single Core:

  • Eingabe 3000, 16 Sekunden, 3019 Ziffern, {318} 5 {2700}
  • Eingabe 4000, 47 Sekunden, 4001 Ziffern, {393} 7 {3607}
  • Eingabe 4100, 5 Sekunden, 4127 Ziffern, {29} 7 {4097}
  • Eingabe 6217, 5 Sekunden, 6217 Ziffern, {23} 5 {6193}
  • Eingabe 6500, 5 Minuten, 6547 Ziffern, {598} 5 {5948}
  • Eingabe 7000, 15 Minuten, 7013 Ziffern, {2411} 7 {4601}
  • Eingabe 9000, 11 Minuten, 9001 Ziffern, {952} 7 {8048}
  • Eingabe 12000, 10 Minuten, 12007 Ziffern, {652} 5 {11354}
  • Eingabe 15100, 2,5 Minuten, 15101 Ziffern, {83} 7 {15017}
  • Eingabe 24600, 47 Minuten, 24671 Ziffern, {621} 7 {24049}
  • Eingabe 32060, 18 Minuten, 32063 Ziffern, {83} 7 {31979}
  • Eingabe 57000, 39 Minuten, 57037 Ziffern, {112} 5 {56924}
  • Eingabe 72225, 42 Minuten, 72227 Ziffern, {16} 3 {72210}

Für das 32k-stellige Ergebnis habe ich 6 Skripte gestartet, die jeweils mit aufeinander folgenden Argumenten ab 32000 gleichzeitig ausgeführt wurden. Nach 26,5 Minuten war man mit dem angezeigten 32063-stelligen Ergebnis fertig. Für 57.000 ließ ich aufeinanderfolgende Skripte eine Stunde lang in 500er-Schritten jeweils 6 ausführen, bis das 57.000-Ergebnis in 57 Minuten zurückgegeben wurde. Das 72.000-stellige Ergebnis wurde durch Ausführen aufeinanderfolgender Primzahlen ab 70.000 gefunden, also definitiv nicht innerhalb einer Stunde (obwohl dies der Fall ist, sobald Sie wissen, wo Sie anfangen sollen).

Das Drehbuch:

#!/usr/bin/env perl
use warnings;
use strict;
use Math::Prime::Util qw/:all/;
use Math::Prime::Util::GMP;  # Just to ensure it is used.

my $l = shift || 1000;  $l--;

while (1) {
  $l = next_prime($l);
  my @D = grep { is_prime($l-1 + $_) } (3,5,7);
  next unless scalar @D > 0;
  for my $s (0 .. $l-1) {
    my $e = $l-$s-1;
    warn "   checking $l $s\n" unless $s % 100;
    for my $d (@D) {
      my $n = "1"x$s . $d . "1"x$e;
      die unless length($n) == $l;
      verify_supreme($n,$s,$d,$e) if is_prime($n);  # ES BPSW + 1 rand-base M-R
    }
  }
}
sub verify_supreme {  # Be pedantic and verify the result
  my($n,$s,$d,$e) = @_;
  die "Incorrect length" unless is_prime(length($n));
  die "Incorrect sum" unless is_prime(vecsum(split(//,$n)));
  my $prod = 1; $prod *= $_ for split(//,$n);
  die "Incorrect product" unless is_prime($prod);
  die "n is not a prime!" unless miller_rabin_random($n,1);  # One more M-R test
  die "{$s} $d {$e}\n";
}
DanaJ
quelle
+1 für die Einführung in diese Bibliothek! Timings auf meinem Computer, um Primzahlen von weniger als 10 ^ 7 (im Vergleich zu CPython mit gmpy2und PyPy mit my_math) zu iterieren : codepad.org/aSzc0esT
primo
Froh, dass Sie es mögen! Es gibt auch andere Möglichkeiten, forprimes { ...do stuff... } 1e7;die 10x oder schneller sind (ein Lob an Pari / GP für viele großartige Ideen). Ich freue mich immer über Feedback. Lassen Sie mich wissen, wenn etwas nicht so funktioniert, wie Sie es möchten.
DanaJ
21

Python 2.7 unter PyPy, {2404} 3 {1596} (~ 10 ^ 4000)

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Fand dieses etwa 50 Minuten nach dem Start von 4000. Daher würde ich schätzen, dass dies die Obergrenze dieses Code-Ansatzes ist.

Änderung: Ich habe festgestellt, dass einige Längen für die Erzeugung dieser Art von Primzahlen fruchtbarer zu sein scheinen als andere. Deshalb habe ich beschlossen, nur 50 zufällige Stellen der Ziffer, die nicht 1 ist, anstelle aller möglichen Stellen zu überprüfen, bevor ich mich bewege auf. Ich bin nicht ganz sicher, ob dies die Leistung verbessern wird oder ob 50 richtig ist, aber wir werden sehen.

Die Liste der Möglichkeiten wird basierend auf der Tatsache erstellt, dass für die Erfüllung der Produktanforderung nur eine einzige Zahl mit Ausnahme einer Primzahl erforderlich ist. Darüber hinaus darf die Primzahl aufgrund des Verhältnisses von Summe und Länge nicht 2 sein, und die digitale Summe darf nicht durch drei teilbar sein, da die% 3-Anforderungen erfüllt sind.

is_prime von http://codepad.org/KtXsydxK , geschrieben von @primo

Hinweis: Diese is_prime-Funktion ist eigentlich ein Baillie-PSW-Pseudoprime-Test, es sind jedoch keine Gegenbeispiele bekannt, sodass ich mich nicht um die Unterscheidung kümmern werde.

#http://codepad.org/KtXsydxK
from my_math import is_prime
import time,random
LLIMIT=2748
time.clock()
start_time=time.time()
checked=0
while time.time()-start_time<3600:
    small_primes = [a for a in range(LLIMIT,2*LLIMIT) if is_prime(a)]
    leng,dig=(0,0)
    for a in small_primes:
        if a+2 in small_primes:
            leng,dig=(a,3)
            break
        if a+4 in small_primes:
            leng,dig=(a,5)
            break
        if a+6 in small_primes:
            leng,dig=(a,7)
            break
    start=time.clock()
    print leng,dig,time.clock(),checked
    for loc in random.sample(range(leng),50):
        checked+=1
        if is_prime(int('1'*loc+str(dig)+'1'*(leng-loc-1))):
            print leng-1,loc,dig,time.clock(),time.clock()-start, \
                  int('1'*loc+str(dig)+'1'*(leng-loc-1))
            break
    LLIMIT=leng+1
isaacg
quelle
Ich weiß leider nichts mehr als den Link. Ich fand den Link hier: codegolf.stackexchange.com/questions/10739/… Erste Antwort
isaacg
Na dann. Ich werde dich gutschreiben.
Isaacg
10
Es ist wie ein ASCII, wo wally ist ...
Trichoplax
5
Vielleicht sollten Sie die Funktion umbenennen is_very_very_very_very_very_very_very_probably_prime()...
Trichoplax
2
Mathmatica und Maple verwenden beide die gleiche Methode, daher kann es nicht so schlimm sein.
Primo
13

PARI / GP, 4127 Stellen

(10 4127 & ndash; 1) / 9 + 2 × 10 515

Dies ist eine recht unkomplizierte Suche: Überprüfen Sie nur die Länge der Primzahlen, berechnen Sie dann die möglichen zu verwendenden Primzahlen und durchlaufen Sie dann alle Möglichkeiten. Ich habe die häufigsten Fälle, in denen 0 oder 1 geeignete Primzahlen zu verwenden sind, als Sonderfall behandelt.

supreme(lim,startAt=3)={
    forprime(d=startAt,lim,
        my(N=10^d\9, P=select(p->isprime(d+p),[1,2,4,6]), D, n=1);
        if(#P==0, next);
        if(#P==1,
            for(i=0,d-1,
                if (ispseudoprime(D=N+n*P[1]), print(D));
                n*=10
            );
            next
        );
        D=vector(#P-1,i,P[i+1]-P[i]);
        for(i=0,d-1,
            forstep(k=N+n*P[1],N+n*P[#P],n*D,
                if (ispseudoprime(k), print(k))
            );
            n*=10
        )
    )
};
supreme(4200, 4100)

Die Berechnung auf einem Kern einer ziemlich alten Maschine dauerte 36 Minuten. Ich bin mir sicher, dass es kein Problem sein würde, eine solche Primzahl mit mehr als 5000 Stellen in einer Stunde zu finden, aber ich bin auch ungeduldig.

Eine bessere Lösung wäre, eine beliebige vernünftige Sprache zu verwenden, um alles außer der innersten Schleife auszuführen , und dann eine abc-Datei für primeform zu erstellen, die für diese bestimmte Art der Berechnung optimiert ist. Dies sollte in der Lage sein, die Berechnung auf mindestens 10.000 Stellen zu erhöhen.

Bearbeiten : Ich habe die oben beschriebene Hybridlösung implementiert, aber auf meinem alten Computer kann ich den ersten Begriff mit> = 10.000 Stellen in weniger als einer Stunde nicht finden. Wenn ich es nicht schneller laufen lasse, muss ich zu einem weniger hohen Ziel wechseln.

Charles
quelle
Woher wusstest du, dass du bei 4100 anfängst?
Isaacg
@isaacg: Ich habe nur versucht, größer zu sein als die (falsche) Mathematica-Lösung, die etwas über 4000 war. Ich bin einfach zum nächsten Vielfachen von 100 als "Nichts-auf-den-Kopf" -Nummer übergegangen. Tatsächlich scheint es, dass dies ein unglücklicher Startplatz war, da ich länger als erwartet (und länger als Mathematica!) Musste, um eine Primzahl zu finden.
Charles
Nein, eigentlich hattest du unglaublich viel Glück. (4127,3) ist das erste Paar nach 4100 und zufällig hat es eine Primzahl. Viele Paare haben überhaupt keine Primzahl.
Isaacg
@isaacg: Vielleicht auch. Meine Heuristiken sind eindeutig falsch, da ich mit einer Wahrscheinlichkeit von ~ 80% gerechnet hätte, eine Primzahl in einem gegebenen Paar zu finden: 1 - exp (-15 / (4 * log 10)), aber sie scheinen seltener zu sein Verhalte dich nicht wie zufällige {2, 3, 5} -glatte Zahlen ihrer Größe (es sei denn, ich habe die Berechnung falsch gemacht).
Charles
@isaacg: Auf jeden Fall arbeite ich an der "besseren Lösung", die ich jetzt erwähnte: Die harte Arbeit nach pfgw treiben. Es wurden die ersten 20 Paare über 10 ^ 10000 durchsucht, ohne dass etwas gefunden wurde, aber das dauerte nur ~ 15 Minuten.
Charles
7

Mathematica 3181 Ziffern

Update: In meiner ersten Einsendung gab es einige schwerwiegende Fehler. Ich konnte einige Zeit aufwenden, um die Ergebnisse für dieses zu überprüfen. Die Ausgabe wird als Ziffernliste formatiert. Dies erleichtert die Überprüfung der einzelnen Bedingungen.

f[primeDigitLength_]:=
Module[{id=ConstantArray[1,primeDigitLength-1]},
permutations=Reverse@Sort@Flatten[Table[Insert[id,#,pos],{pos,primeDigitLength}]&/@{3,5,7},1];
Flatten[Select[permutations,PrimeQ[FromDigits[#]]\[And]PrimeQ[Plus@@#]&,1],1]]

Beispiel

Dies war mein erster Test, eine Suche nach einer Lösung mit 3181 Ziffern. Es fand den ersten Fall in 26 Sekunden.

Lassen Sie uns die Überlegungen durchgehen. Dann treten wir in das Programm selbst ein.

Beginnen wir wie ich: "Was ist die 450. Primzahl?" Können wir eine Lösung mit so vielen Ziffern finden (3181)?

primeDigits = Prime[450]

3181


Die Nummer wird durch Verknüpfen der Ziffern ermittelt.

number = FromDigits[digits];

Aber anstatt es anzuzeigen, können wir stattdessen fragen, was die Ziffern sind und wo sie liegen.

DigitCount[number]

{3180, 0, 0, 0, 0, 0, 1, 0, 0, 0}

Dies bedeutet, dass es 3180 Instanzen der Ziffer 1 und eine einzelne Instanz der Ziffer 7 gab.

An welcher Stelle steht die Ziffer 7?

Position[digits, 7][[1, 1]]

142

Die Ziffer 7 ist also die 142. Ziffer. Alle anderen sind Einsen.


Natürlich muss das Produkt der Ziffern eine Primzahl sein, nämlich 7.

digitProduct = Times @@ digits

7


Und die Summe der Ziffern ist auch eine Primzahl.

digitSum = Plus @@ digits
PrimeQ[digitSum]

3187
Richtig


Und wir wissen, dass die Anzahl der Ziffern eine Primzahl ist. Denken Sie daran, wir haben die 450. Primzahl ausgewählt, nämlich 3118.

Damit sind alle Voraussetzungen erfüllt.

DavidC
quelle
3
Wenn ich mich nicht irre, ist seine Summe 4009, was keine Primzahl ist.
Gerw
Eine Sache: Sollte es nicht die Summe aller Ziffern sein, die prim sind, und nicht die Anzahl der Ziffern? In deinem Fall 4002 * 1 + 7 = 4009müsstest du nicht 4003 testen und entsprechend der Spezifikation.
Johnride
2
@ Johnride: Beide sollten erstklassig sein.
Gerw
@gerw Ist richtig. Die Anzahl der Ziffern UND die Summe der Ziffern UND das Produkt der Ziffern müssen alle Primzahlen sein.
Calvins Hobbys
Sie waren alle richtig. In meinem vorherigen Beitrag habe ich vergessen, die Ziffernsumme auf Primalität zu überprüfen. Dies geschieht nun, indem geprüft wird, ob eine der folgenden Angaben (es spielt keine Rolle, welche) eine Primzahl ist: Ziffernlänge + 2, Ziffernlänge _4 oder Ziffernlänge +6.
DavidC
7

Python 2.7, 6217 Ziffern: {23} 5 {6193} 6 Minuten, 51 Sekunden

Ich arbeitete an meiner eigenen Version und war enttäuscht zu sehen, dass @issacg mich mit einem sehr ähnlichen Ansatz ins Schwarze getroffen hatte, wenn auch mit is_ (sehr wahrscheinlich) _prime (). Ich sehe jedoch, dass ich einige signifikante Unterschiede habe, die zu einer besseren Antwort in kürzerer Zeit führen (wenn ich auch is_prime verwende). Um dies zu verdeutlichen, erreiche ich ab 4000 in nur 26 Minuten und 37 Sekunden eine bessere 4001-stellige Antwort ({393} 7 {3607}) mit dem Standard- Python-Interpreter (ebenfalls in Version 2.7), nicht mit PyPy Ausführung. Außerdem überprüfe ich die Zahlen nicht vor Ort. Alle Kandidaten werden geprüft.

Hier sind die wichtigsten Verbesserungen:

  1. Verwenden Sie einen Primgenerator ( https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618 ), um eine Liste von Primzahlen zu erstellen, gegen die geprüft werden soll, und (seine Version von "kleinen Primzahlen") und zum Erzeugen geeigneter Nummernlängen.

  2. Wir wollen unsere Zeit damit verbringen, nach der größten höchsten Primzahl einer bestimmten Länge zu suchen, nicht nach der kleinsten. Deshalb konstruiere ich zuerst die größtmöglichen Zahlen, um sie zu überprüfen, und nicht nach der kleinsten. Sobald einer gefunden ist, können wir sofort zur nächsten Länge übergehen.

EDIT: Jetzt mit Multiprocessing

Dies ist eine wesentliche Änderung gegenüber früheren Versionen. Zuvor bemerkte ich, dass mein 8-Core-Rechner kaum funktionierte, und beschloss, mich in Python (zum ersten Mal) an der Mehrfachverarbeitung zu versuchen. Die Ergebnisse sind sehr schön!

In dieser Version werden 7 untergeordnete Prozesse erzeugt, die eine 'Aufgabe' aus einer Warteschlange potenzieller Möglichkeiten (num_length + zulässige Ziffern) abrufen. Sie probieren verschiedene [7,5,3] Positionen aus, bis sie eine finden. In diesem Fall wird der Master-Prozess über die neue längste gefundene Länge informiert. Wenn Kinder an einer kürzeren Anzahl_Längen arbeiten, müssen sie nur auf Kaution gehen und die nächste Länge abrufen.

Ich habe diesen Lauf mit 6000 begonnen und er läuft noch, aber bis jetzt bin ich sehr zufrieden mit dem Ergebnis.

Das Programm stoppt noch nicht richtig, aber für mich kein großes Problem.

Nun der Code:

#!/usr/bin/env python
from __future__ import print_function

import sys
from multiprocessing import Pool, cpu_count, Value
from datetime import datetime, timedelta

# is_prime() et al from: http://codepad.org/KtXsydxK - omitted for brevity
# gen_primes() from: https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618 - ommitted for brevity
from external_sources import is_prime, gen_primes


def gen_tasks(start_length):
    """
    A generator that produces a stream of eligible number lengths and digits
    """
    for num_length in gen_primes():
        if num_length < start_length:
            continue

        ns = [ n for n in [7,5,3] if num_length + n - 1 in prime_list ]
        if ns:
            yield (num_length, ns)


def hunt(num_length, ns):
    """
    Given the num_length and list of eligible digits to try, build combinations
    to try, and try them.
    """

    if datetime.now() > end_time or num_length <= largest.value:
        return

    print('Tasked with: {0}, {1}'.format(num_length, ns))
    sys.stdout.flush()
    template = list('1' * num_length)
    for offset in range(num_length):
        for n in ns:
            if datetime.now() > end_time or num_length <= largest.value:
                return

            num_list = template[:]
            num_list[offset] = str(n)
            num = int(''.join(num_list))

            if is_prime(num):
                elapsed = datetime.now() - start_time
                largest.value = num_length
                print('\n{0} - "{1}"\a'.format(elapsed, num))


if __name__ == '__main__':
    start_time = datetime.now()
    end_time = start_time + timedelta(seconds=3600)

    print('Starting @ {0}, will stop @ {1}'.format(start_time, end_time))

    start_length = int(sys.argv[1])

    #
    # Just create a list of primes for checking. Up to 20006 will cover the first
    # 20,000 digits of solutions
    #
    prime_list = []
    for prime in gen_primes():
        prime_list.append(prime)
        if prime > 20006:
            break;
    print('prime_list is primed.')

    largest = Value('d', 0)

    task_generator = gen_tasks(start_length)

    cores = cpu_count()
    print('Number of cores: {0}'.format(cores))


    #
    # We reduce the number of cores by 1 because __main__ is another process
    #
    pool = Pool(processes=cores - 1)

    while datetime.now() < end_time:
        pool.apply_async(hunt, next(task_generator))
mkoistinen
quelle
Es würde sauberer lesen, wenn Sie den Codepad-Link als [defekt, falls erforderlich] -Import darstellen
Sparr
Ich denke, das wäre verwirrend, da der Code am anderen Ende so nicht wirklich importierbar ist.
mkoistinen
benutze die Syntax von isaacg. Kommentieren Sie die URL, und importieren Sie sie aus einem nicht vorhandenen Paket (in seinem Fall my_math)
Sparr
1
Eigentlich generiere ich die Zahlen auch vom größten zum kleinsten. Ich denke nicht, dass unsere Codeunterschiede sehr bedeutend sind. Ich würde erwarten, dass der Unterschied mehr in unseren Computern liegt als in unserem Code. Trotzdem gut gemacht und herzlich willkommen auf der Seite.
isaacg
my_mathkann auch verwendet werden, um eine Liste von Primzahlen zu generieren, à la while prime < 20006: prime = next_prime(prime). Scheint ungefähr dreimal so schnell gen_primesund wesentlich speichereffizienter zu sein.
Primo
6

C, GMP - {7224} 5 {564} = 7789

Ein großes Lob an @issacg und euch alle für die Inspirationen und Tricks.
Und auch der meisterhafte Fragesteller @ Calvins Hobbys zu dieser Frage.

Kompilieren: gcc -I/usr/local/include -o p_out p.c -pthread -L/usr/local/lib -lgmp

Wenn Sie Ihre Rechenleistung spenden möchten oder neugierig auf die Leistung sind, können Sie den Code kopieren und kompilieren. ;) Du musst GMP installiert haben.

#include<stdio.h>
#include<stdlib.h>
#include<sys/time.h>
#include<gmp.h>
#include<pthread.h>

#define THREAD_COUNT 1
#define MAX_DIGITS   7800
#define MIN_DIGITS   1000

static void huntSupremePrime(int startIndex) {

    char digits[MAX_DIGITS + 1];

    for (int i = 0; i < MAX_DIGITS; digits[i++] = '1');

    digits[MAX_DIGITS] = '\0';
    mpz_t testPrime, digitSum, digitCount, increment;

    for (int j = 0; j < MAX_DIGITS - startIndex; digits[j++] = '0');

    int step = THREAD_COUNT * 2;

    for (int i = startIndex, l = MAX_DIGITS - startIndex; i > MIN_DIGITS - 1; 
        i -= step, l += step) {
        fprintf(stderr, "Testing for %d digits.\n", i);
        mpz_init_set_ui(digitCount, i);
        if (mpz_millerrabin(digitCount, 10)) {
            for (int j = 3; j < 8; j += 2) {
                mpz_init_set_ui(digitSum, i - 1 + j);
                if (mpz_millerrabin(digitSum, 10)) {
                    gmp_printf("%Zd \n", digitSum);
                    digits[MAX_DIGITS - 1] = j + 48;
                    mpz_init_set_str(testPrime, digits, 10);
                    mpz_init_set_ui(increment, (j - 1) * 99);
                    for (int k = 0; k < i/20; ++k) {
                        if (mpz_millerrabin(testPrime, 25)) {
                            i = 0;
                            j = 9;
                            k = l;
                            gmp_printf("%Zd\n", testPrime);
                            break;
                        }
                        mpz_add(testPrime, testPrime, increment);
                        mpz_mul_ui(increment, increment, 100);
                        fprintf(stderr, "TICK %d\n", k);
                    }

                }
            }
        }
        for (int j = 0; j < step; digits[l + j++] = '0');

    }
}

static void *huntSupremePrimeThread(void *p) {
    int* startIndex = (int*) p;
    huntSupremePrime(*startIndex);
    pthread_exit(NULL);
}

int main(int argc, char *argv[]) {

    int  startIndexes[THREAD_COUNT];
    pthread_t threads[THREAD_COUNT];

    int startIndex = MAX_DIGITS;
    for (int i = 0; i < THREAD_COUNT; ++i) {
        for (;startIndex % 2 == 0; --startIndex);
        startIndexes[i] = startIndex;
        int rc = pthread_create(&threads[i], NULL, huntSupremePrimeThread, (void*)&startIndexes[i]); 
        if (rc) { 
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
        --startIndex;
    }

    for (int i = 0; i < THREAD_COUNT; ++i) {
        void * status;
        int rc = pthread_join(threads[i], &status);
        if (rc) {
            printf("ERROR: return code from pthread_join() is %d\n", rc);
            exit(-1);
        }
    }

    pthread_exit(NULL);
    return 0;
}
Vektorisiert
quelle
5

PFGW, 6067 Ziffern, {5956} 7 {110}

Führen Sie PFGW mit der folgenden Eingabedatei aus und stellen Sie -f100die Zahlen vor. In ca. 2-3 CPU-Minuten auf meinem Computer (i5 Haswell) wird PRP (10 ^ (6073-6) -1) / 9 + 6 * 10 ^ 110 oder {5956} 7 {110} gefunden . Ich habe 6000 Stellen als Ausgangspunkt gewählt, um eine Nummer zu erhalten, die ein wenig höher ist als alle vorherigen Einreichungen.

ABC2 $a-$b & (10^($a-$b)-1)/9+$b*10^$c
a: primes from 6000 to 6200
b: in { 2 4 6 }
c: from 0 to 5990

Anhand der Geschwindigkeit, mit der ich diese gefunden habe, konnte ich die Anzahl der Stellen leicht erhöhen und innerhalb einer Stunde immer noch einen PRP finden. Mit der Schreibweise der Regeln kann ich sogar feststellen, wie groß meine CPU ist, die auf allen vier Kernen läuft, einen PRP-Test in einer Stunde abschließt, lange Zeit für die Suche nach einem PRP benötigt und nur aus meiner "Suche" besteht des einen PRP.

PS In gewisser Hinsicht ist dies keine "Code" -Lösung, da ich nichts anderes als die Eingabedatei geschrieben habe ... Aber dann könnten viele einzeilige Mathematica-Lösungen für mathematische Probleme genauso beschrieben werden wie möglich mit einer Bibliothek, die die harte Arbeit für Sie erledigt. In Wirklichkeit finde ich es schwierig, eine gute Grenze zwischen den beiden zu ziehen. Wenn Sie möchten, könnte ich ein Skript schreiben, das die PFGW-Eingabedatei erstellt und PFGW aufruft. Das Skript könnte sogar parallel suchen, um alle 4 Kerne zu nutzen und die Suche um das ~ 4-fache zu beschleunigen (auf meiner CPU).

PPS Ich denke, LLR kann die PRP-Tests für diese Zahlen durchführen, und ich würde erwarten, dass es viel schneller als PFGW ist . Ein spezielles Siebprogramm könnte diese Zahlen auch besser berücksichtigen als das von PFGW nacheinander. Wenn Sie diese kombinieren, könnten Sie die Grenzen sicherlich noch viel höher setzen als bei den aktuellen Lösungen.

Tim S.
quelle
4

Python 2.7, 17-19 Ziffern

11111111171111111

Gefunden 5111111111111 (13 Ziffern) in 3 Sekunden und diese 17 Ziffern höchste Primzahl in 3 Minuten. Ich vermute, dass der Zielcomputer dies ausführen und in weniger als einer Stunde eine 19-stellige höchste Primzahl erhalten könnte. Dieser Ansatz lässt sich nicht gut skalieren, da Primzahlen bis zur Hälfte der Anzahl der Zielziffern im Speicher bleiben. 17-stellige Suche erfordert das Speichern eines Arrays von 100 Millionen Booleschen Werten. 19 Stellen würden ein 1B-Elementarray erfordern, und der Speicher wäre erschöpft, bevor 23 Stellen erreicht würden. Laufzeit wäre wahrscheinlich auch.

Primalitätstest-Ansätze, die keine lächerlich große Anzahl von Divisor-Primzahlen beinhalten, schneiden viel besser ab.

#!/usr/bin/env python
import math
import numpy as np
import sys

max_digits = int(sys.argv[1])
max_num = 10**max_digits

print "largest supreme prime of " + str(max_digits) + " or fewer digits"

def sum_product_digits(num):
    add = 0
    mul = 1
    while num:
         add, mul, num = add + num % 10, mul * (num % 10), num / 10
    return add, mul

def primesfrom2to(n):
    # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Input n>=6, Returns a array of primes, 2 <= p < n """
    sieve = np.ones(n/3 + (n%6==2), dtype=np.bool)
    sieve[0] = False
    for i in xrange(int(n**0.5)/3+1):
        if sieve[i]:
            k=3*i+1|1
            sieve[      ((k*k)/3)      ::2*k] = False
            sieve[(k*k+4*k-2*k*(i&1))/3::2*k] = False
    return np.r_[2,3,((3*np.nonzero(sieve)[0]+1)|1)]

def checkprime(n):
    for divisor in primes:
        if (divisor>math.sqrt(n)):
            break
        if n%divisor==0:
            return False
    return True

# make an array of all primes we need to check as divisors of our max_num
primes = primesfrom2to(math.sqrt(max_num))
# only consider digit counts that are prime
for num_digits in primes:
    if num_digits > max_digits:
        break
    for ones_on_right in range(0,num_digits):
        for mid_prime in ['3','5','7']:
            # assemble a number of the form /1*[357]1*/
            candidate = int('1'*(num_digits-ones_on_right-1)+mid_prime+'1'*ones_on_right)
            # check for primeness of digit sum first digit product first
            add, mul = sum_product_digits(candidate)
            if add in primes and mul in primes:
                # check for primality next
                if checkprime(candidate):
                    # supreme prime!
                    print candidate
Sparr
quelle
3

Mathematica 4211 4259 Ziffern

Mit der Nummer: {1042} 7 {3168} {388} 3 {3870}

Welches wurde durch den folgenden Code generiert:

TimeConstrained[
 Do[
  p = Prime[n];
  curlargest = Catch[
    If[PrimeQ[p + 6],
     list = ConstantArray[1, p];
     Do[
      temp = FromDigits[ReplacePart[list, i -> 7]];
      If[PrimeQ[temp],
       Throw[temp]
       ], {i, p}]
     ];

    If[PrimeQ[p + 4],
     list = ConstantArray[1, p];
     Do[
      temp = FromDigits[ReplacePart[list, i -> 5]];
      If[PrimeQ[temp],
       Throw[temp]
       ], {i, p}]
     ];
    If[PrimeQ[p + 2],
     list = ConstantArray[1, p];
     Do[
      temp = FromDigits[ReplacePart[list, i -> 3]];
      If[PrimeQ[temp],
       Throw[temp]
       ], {i, p}]
     ];
    Throw[curlargest];
    ]

  , {n, 565, 10000}]
 , 60*60]

Die Würfe führen dazu, dass der Test auf andere Zahlen mit denselben Ziffern wie den aktuell gefundenen abgebrochen wird. Da der Test bei der höchstwertigen Ziffer beginnt, wird immer die größte Zahl zurückgegeben, es sei denn, die Anzahl der Ziffern ist Mitglied eines Primtripletts.

Einfach angefangen zu testen knapp unter dem Wert einer der vorhergehenden Antworten :)

Sobald dies abgeschlossen ist, wird die Nummer in der Variablen curlargest gespeichert

Übereinstimmen
quelle
2

JavaScript, 3019 Ziffern, {2.273} 5 {745}

Hierfür wird der in BigInteger.js enthaltene MillerRabin-Test von Tom Wu verwendet.

Ausgehend von 0 => 2.046 Ziffern = {1799} 7 {263} in einer Stunde .

Ab 3000 => 3.019 Stellen = {2.273} 5 {745} in einer Stunde, weniger als 3 Sekunden .

Beim Start von 0 sprang das Programm vor und suchte erneut mit einer Länge von 1,5X der Länge des zuletzt gefundenen S-Prims. Als ich dann sah, wie schnell es lief, schätzte ich, dass es eines ab 3000 in einer Stunde finden würde - und das mit nur 3 Sekunden Zeitersparnis.

Sie können es hier ausprobieren: http://goo.gl/t3TmTk
(Zum Berechnen aller S-Primzahlen oder zum Überspringen.)

Bildbeschreibung hier eingeben Bildbeschreibung hier eingeben
Bildbeschreibung hier eingeben

Das Programm erstellt Zeichenfolgen aller "1", jedoch mit einer "3", "5" oder "7". Ich habe einen schnellen Check in der IsStrPrime-Funktion hinzugefügt, um Zahlen mit der Endung "5" abzulehnen.

if (IsIntPrime(length)) {

    var do3s = IsIntPrime(length + 2);
    var do5s = IsIntPrime(length + 4);
    var do7s = IsIntPrime(length + 6);

    if (do3s || do5s || do7s) {

        // loop through length of number
        var before, digit, after;

        for (var after = 0; after <= length - 1; after++) {

            before = length - after - 1;
            beforeStr = Ones(before);
            afterStr = Ones(after);

            if (do3s && IsStrPrime(beforeStr + (digit = "3") + afterStr)) { RecordAnswer(); if (brk) break; }
            if (AreDone()) break;

            if (do5s && IsStrPrime(beforeStr + (digit = "5") + afterStr)) { RecordAnswer(); if (brk) break; }
            if (AreDone()) break;

            if (do7s && IsStrPrime(beforeStr + (digit = "7") + afterStr)) { RecordAnswer(); if (brk) break; }
            if (AreDone()) break;

            if (after % 10 == 0) document.title = "b=" + bestLength + ", testing=" + length + "-" + after;
        }
    }
}

Das war ziemlich lustig. Erinnert mich an ein Rätsel, das ich vor vielen Jahren gemacht habe, um die sogenannte Ziffer ohne Primzahl zu berechnen . Dies ist eine Primzahl. Wenn Sie eine Ziffer entfernen, ist die verbleibende Zahl immer noch eine Primzahl. Beispielsweise ist 1037 eine Ziffer ohne Primzahl, da 1037, 037, 137, 107 und 103 Primzahlen sind. Ich habe eine 84-stellige gefunden und die längste, die ich kenne, ist 332-stellig. Ich bin sicher, dass wir mit den Techniken, die für dieses Rätsel verwendet wurden, noch viel länger fündig werden können. (Aber die Auswahl der Testnummern ist etwas schwieriger - vielleicht?)

JeffSB
quelle
RE: Ziffer entfernt, wir hatten diese hier . 332 Stellen hätten auch gewonnen.
Primo
0

Axiom, 3019 Ziffern {318} 5 {2700}

)time on

-- Return true if n is pseudo prime else return false
-- **Can Fail**
prime1(n:PI):Boolean==
     n=1=>false
     n<4=>true
     i:=5;sq:=sqrt(1.*n)
     repeat
       if i>sq or i>50000 then break
       if n rem i=0       then return false
       i:=i+2
     if i~=50001        then return true
     --output("i")
     if powmod(3,n,n)=3 then return true
     --output("e")
     false

-- input  'n': must be n>1 prime
-- output [0] if not find any number, else return 
-- [n,a,b,c,z] 'n' digits of solution, 
-- 'a' number of '1', 'b' central digit, 'b' number of final digit '1'
-- 'z' the number found
g(n:PI):List NNI==
    x:=b:=z:=1
    for i in 1..n-1 repeat
        z:=z*10+1
        b:=b*10
    repeat
       --output b
       k:=0    -- 3 5 7 <-> 2 4 6
       for i in [2,4,6] repeat
           ~prime?(n+i)=>0 --somma
           k:=k+1
           t:=z+b*i
           if prime1(t) then return [n,x-1,i+1,n-x,t]
       --if x=1 then output ["k=", k] 
       if k=0  then break
       x:=x+1
       b:=b quo 10
       if b<=0 then break
    [0]

-- start from number of digits n
-- and return g(i) with i prime i>=n 
find(n:PI):List NNI==
    i:=n
    if i rem 2=0 then i:=i+1 
    repeat
        if prime?(i) then --solo le lunghezze prime sono accettate
             output i 
             a:=g(i)
             if a~=[0] then return a
        i:=i+2

ergebnis aus dem startwert 3000 in 529 sek

(4) -> find(3000)
   3001
   3011
   3019

   (4)
   [3019, 318, 5, 2700, Omissis]
                                            Type: List NonNegativeInteger
       Time: 0.02 (IN) + 525.50 (EV) + 0.02 (OT) + 3.53 (GC) = 529.07 sec
RosLuP
quelle