Trouvez le plus grand nombre premier dont la longueur, la somme et le produit sont premiers

37

Le nombre 113est le premier nombre premier dont la longueur 3est le nombre premier, la somme numérique 5 = 1 + 1 + 3est le nombre premier et le produit numérique 3 = 1 * 1 * 3est le nombre premier.

Un premier qui a ces 3 propriétés sera appelé suprêmement premier . Les nombres premiers 11117et 1111151sont d'autres exemples.

Objectif

Ecrivez un programme capable de trouver le plus grand nombre suprêmement premier possible en moins d’une heure sur un ordinateur personnel moderne décent (comme la spécification recommandée ici ).

Vous ne devriez pas simplement nous donner un grand nombre premier suprême. Vous devez nous montrer votre processus de recherche avec un code qui fonctionne réellement. Vous pouvez tirer parti de vos solutions ou de celles des autres, mais assurez-vous de leur donner du crédit. Nous essayons en quelque sorte en communauté de trouver le plus grand nombre premier suprême réalisable sur un ordinateur normal en une heure.

Notation

La soumission qui trouve le plus grand prime suprême gagne. S'il s'avère qu'il y a un nombre fini de nombres premiers suprêmes, la première soumission qui génère le nombre premier suprême le plus élevé l'emporte.

(Si vous pouvez prouver mathématiquement qu'il existe ou qu'il n'y a pas une infinité de nombres premiers suprêmes, je vous donnerai 200 représentants de primes simplement parce que. :))

Détails

  • Vous pouvez utiliser n’importe quelle source pour générer vos nombres premiers (par exemple, Internet).
  • Vous pouvez utiliser des méthodes de test probabilistes principales.
  • Tout est en base 10.
  • Zéro et un ne sont pas considérés comme premiers.
  • Les primes qui contiennent 0un produit numérique 0ne peuvent évidemment pas être suprêmes.
  • Pour que la page reste moins encombrée, définissez les nombres premiers premiers (plus de 100 chiffres) comme suit:

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

    Donc, 1111151pourrait être exprimé comme {5}5{1}.

Les passe-temps de Calvin
la source
Pouvons-nous commencer avec une liste de nombres premiers ou aller chercher une liste sur Internet et passer l'heure à faire des vérifications de suprématie?
Sparr
2
Si vous pouvez commencer avec le nombre premier suprême le plus élevé connu, le défi consiste à écrire un programme qui passe exactement une heure sur le plus grand intervalle possible entre deux nombres premiers suprêmes. :(
Sparr le
8
En plus de ne pas contenir de 0, tout nombre premier primordial potentiel doit évidemment être de la forme 1 ^ n [3 | 5 | 7] 1 ^ m, c'est-à-dire certains 1, tout nombre premier inférieur à 10 et quelques autres. Il y a plus de contraintes que vous pouvez mettre tout de suite.
Ingo Bürk
3
Ryan a lancé une question connexe sur le MSE concernant l'existence d'un nombre infini de premiers premiers. Si vous avez des idées pour cette question, pesez-vous!
Semi
1
Je peux facilement montrer qu’il n’existe actuellement aucune preuve d’un nombre infini de nombres premiers suprêmes (et qu’un travail considérable a été accompli dans ce sens). Selon michaelnielsen.org/polymath1/… , nous savons que les nombres premiers sont infinis avec des espaces aussi petits que 246, mais pour prouver le nombre suprême suprême infini, nous avons besoin d’un espace de 2, 4 ou 6 (correspondant aux nombres premiers avec 3, 5 ou 7 quelque part en eux).
Tim S.

Réponses:

9

Perl, 15101 chiffres, {83} 7 {15017}, 8 minutes. Max trouvé: 72227 chiffres

Utiliser mon module Math :: Prime :: Util et son back-end GMP . Il comporte un certain nombre de tests de composition, notamment is_prob_prime () avec un test ES BPSW (légèrement plus strict que l'ispseudoprime de Pari), is_prime () qui ajoute un MR à base aléatoire et is_provable_prime (), qui exécutera BLS75 T5 ou ECPP. À ces tailles et types, faire une épreuve prendra beaucoup de temps. J'ai jeté dans un autre test MR dans le sous-vérificateur pédant. Fois sur un Core2 E7500 qui n’est certainement pas mon ordinateur le plus rapide (cela prend 2,5 minutes sur mon i7-4770K).

Comme Tim S. le fait remarquer, nous pourrions continuer à rechercher des valeurs plus grandes, jusqu'au point où un seul test prend une heure. À environ 15 000 chiffres sur cet E7500, il faut environ 26 secondes pour un test de résonance magnétique et 2 minutes pour le test complet is_prime (division d’essai plus MR de base 2, plus ES Lucas et un MR de base aléatoire). Mon i7-4770K est plus de 3 fois plus rapide. J'ai essayé quelques tailles, principalement en constatant les résultats obtenus par d'autres personnes. J'ai essayé 8, 20 et 16 km, tuant chacun après environ 5 minutes. J'ai ensuite essayé 15k en progression sur environ 10m et j'ai eu de la chance avec le 4ème.

Les tests PRP d’OpenPFGW sont certainement plus rapides au-delà de 4000 chiffres environ, et bien plus rapides dans la plage des 50 000+. Son test comporte cependant une bonne quantité de faux positifs, ce qui en fait un excellent pré-test, mais on aimerait quand même vérifier les résultats avec autre chose.

Cela pourrait être mis en parallèle avec des threads en perl ou en utilisant MCE, comme le montrent les exemples parallèles de Fibonacci Prime Finder du module.

Synchronisation et résultats sur un i7-4770K inactif utilisant un seul cœur:

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

Pour le résultat de 32 000 chiffres, j'ai démarré 6 scripts s'exécutant en même temps, chacun avec des arguments successifs commençant à 32 000. Après 26,5 minutes, l'un d'entre eux s'est terminé avec le résultat de 32063 chiffres affiché. Pour 57k, j'ai laissé les scripts successifs exécuter 6 à la fois pendant une heure par incréments de 500 jusqu'à ce que le résultat de 57k soit renvoyé dans un délai de 57 minutes. Le résultat de 72 000 chiffres a été trouvé en effectuant des nombres premiers successifs à partir de 70 000, donc impossible à trouver en une heure (bien que, une fois que vous sachiez par où commencer, c'est le cas).

Le script:

#!/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
la source
+1 pour me présenter à cette bibliothèque! Les temps sur ma machine pour itérer les nombres premiers inférieurs à 10 ^ 7 (par rapport à CPython avec gmpy2, et PyPy avec my_math): codepad.org/aSzc0esT
primo
Content que tu aimes ça! Il y a d'autres moyens, y compris forprimes { ...do stuff... } 1e7;ce qui est 10 fois ou plus rapide (bravo à Pari / GP pour beaucoup de bonnes idées). J'apprécie toujours vos commentaires, alors laissez-moi savoir si quelque chose ne fonctionne pas comme vous le souhaitez.
DanaJ
21

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

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

J'ai trouvé celui-ci environ 50 minutes après le départ à partir de 4 000. Par conséquent, j'estime qu'il s'agit de la limite supérieure de cette approche de code.

Changement: j'ai remarqué que certaines longueurs semblent être plus productives que d'autres pour générer ce type de prime, alors j'ai décidé de ne vérifier que 50 emplacements aléatoires du chiffre qui ne sont pas 1 au lieu de tous les emplacements possibles, avant de passer à autre chose. sur. Je ne suis pas tout à fait sûr que cela améliorera les performances, ou que 50 soit correct, mais nous verrons.

La liste des possibilités est générée sur la base du fait que pour que l'exigence relative aux produits soit remplie, le nombre doit être égal à tous, sauf un nombre premier. De plus, le nombre premier ne peut pas être 2 en raison de la relation somme et longueur, et la somme numérique ne doit pas être divisible par trois, ce qui donne les exigences en% 3.

is_prime tiré de http://codepad.org/KtXsydxK , écrit par @primo

Remarque: cette fonction is_prime est en fait un test pseudoprime de Baillie-PSW, mais il n’existe aucun contre-exemple connu, je ne vais donc pas me soucier de la distinction.

#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
la source
Je ne connais rien d'autre que le lien, malheureusement. J'ai trouvé le lien ici: codegolf.stackexchange.com/questions/10739/… Première réponse
isaacg le
Eh bien. Je te créditerai.
isaacg
10
C'est comme un ASCII où est wally ...
trichoplax
5
Peut-être devriez-vous renommer la fonction is_very_very_very_very_very_very_very_probably_prime()...
trichoplax
2
Mathmatica et Maple utilisent la même méthode, ce qui ne peut donc pas être si mauvais.
dimanche
13

PARI / GP, 4127 chiffres

(10 4127 -1) / 9 + 2 * 10 515

Il s'agit d'une recherche assez simple: vérifiez uniquement les longueurs des nombres premiers, puis calculez les nombres premiers possibles à utiliser, puis parcourez toutes les possibilités. Je cas spécial les cas communs où il y a 0 ou 1 chiffres premiers appropriés à utiliser.

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)

Cela a pris 36 minutes pour calculer sur un noyau d'une machine assez ancienne. Je suis sûr que nous n'aurions aucun mal à trouver un nombre si élevé de plus de 5 000 chiffres en une heure, mais je suis aussi impatient.

Une meilleure solution consisterait à utiliser tout langage raisonnable pour tout faire sauf la boucle la plus interne, puis à construire un fichier abc pour primeform optimisé pour ce type de calcul particulier. Cela devrait pouvoir pousser le calcul à au moins 10 000 chiffres.

Edit : J'ai implémenté la solution hybride décrite ci-dessus, mais sur mon ancienne machine, je ne trouve pas le premier terme avec> = 10 000 chiffres en moins d'une heure. À moins que je ne me précipite sur quelque chose de plus rapide, je vais devoir passer à une cible moins noble.

Charles
la source
Comment avez-vous su pour commencer à 4100?
isaacg
@isaacg: J'essayais simplement d'être plus volumineux que la solution (incorrecte) de Mathematica, qui comptait un peu plus de 4 000. Je viens de passer au multiple suivant de 100 en tant que nombre "rien à redire". En fait, il semble que ce fût un lieu de départ malheureux, car je devais partir plus longtemps que prévu (et plus longtemps que Mathematica!) Pour trouver un bon premier.
Charles le
Non, en fait, vous avez été incroyablement chanceux. (4127,3) est la première paire après 4100, et par chance, il a une prime. Beaucoup de paires n'ont pas de prime.
isaacg
@isaacg: Peut-être. Mes heuristiques sont clairement désactivées, car j'aurais prévu une probabilité d'environ 80% de trouver un nombre premier dans une paire donnée: 1 - exp (-15 / (4 * log 10)), mais elles semblent être plus rares que cela. n'agissez pas comme des nombres aléatoires {2, 3, 5} de leur taille (à moins que je n'ai gaffé le calcul)
Charles
@isaacg: En tout cas, je travaille sur la "meilleure solution" que j'ai mentionnée maintenant: pousser le dur travail à Pfgw. Il a recherché les 20 premières paires supérieures à 10 ^ 10 000 sans rien trouver mais cela n'a pris que 15 minutes environ.
Charles
7

Mathematica 3181 chiffres

Mise à jour: Il y avait quelques erreurs graves dans ma première soumission. J'ai pu consacrer du temps à vérifier les résultats de celui-ci. La sortie est formatée sous forme de liste de chiffres. Cela facilite la vérification de chacune des conditions.

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]]

Exemple

C'était mon premier test, une recherche d'une solution avec 3181 chiffres. Il a trouvé le premier cas en 26 secondes.

Passons en revue le raisonnement. Ensuite, nous entrerons dans le programme lui-même.

Commençons, comme je le faisais, "Quel est le 450ème nombre premier?" Pouvons-nous trouver une solution avec autant de chiffres (3181)?

primeDigits = Prime[450]

3181


Le numéro est trouvé en joignant les chiffres.

number = FromDigits[digits];

Mais plutôt que de l'afficher, nous pouvons demander à la place quels sont les chiffres et où ils se trouvent.

DigitCount[number]

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

Cela signifie qu'il y avait 3180 instances du chiffre 1 et une seule instance du chiffre 7.

A quelle position se trouve le chiffre 7?

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

142

Donc, le chiffre 7 est le 142ème chiffre. Tous les autres sont des 1.


Bien entendu, le produit des chiffres doit être un nombre premier, à savoir 7.

digitProduct = Times @@ digits

7


Et la somme des chiffres est également un nombre premier.

digitSum = Plus @@ digits
PrimeQ[digitSum]

3187
True


Et nous savons que le nombre de chiffres est un nombre premier. Rappelez-vous, nous avons sélectionné le 450ème prime, à savoir 3118.

Donc, toutes les conditions sont remplies.

DavidC
la source
3
Si je ne me trompe pas, sa somme est 4009 qui n’est pas primordiale.
Ger
Une chose: ne devrait-il pas s'agir de la somme de tous les chiffres premiers et non de leur nombre? Dans votre cas, vous devez tester 4002 * 1 + 7 = 4009et non 4003 selon les spécifications.
Johnride
2
@Johnride: les deux devraient être premiers.
Ger
@gerw a raison. Le nombre de chiffres ET la somme des chiffres ET le produit des chiffres doivent tous être des nombres premiers.
Les passe-temps de Calvin
Vous avez tous eu raison. Dans ma soumission précédente, j'avais oublié de vérifier la somme des chiffres pour la primalité. Ceci est maintenant effectué en vérifiant si l'un des éléments suivants (peu importe) est premier: longueur de chiffres + 2, longueur de chiffres _4 ou longueur de chiffres +6.
DavidC
7

Python 2.7, 6217 chiffres: {23} 5 {6193} 6 minutes 51 secondes

Je travaillais sur ma propre version et j'ai été déçu de voir que @issacg m'avait battu au poinçon avec une approche très similaire, bien qu'avec is_ (très_probablement) _prime (). Cependant, je constate quelques différences significatives qui permettent d’obtenir une meilleure réponse en moins de temps (lorsque j’utilise également is_prime). Pour que ce soit clair, à partir de 4000 également, j'arrive à une meilleure réponse à 4001 chiffres ({393} 7 {3607}) en seulement 26 minutes, 37 secondes en utilisant l' interpréteur Python standard (également en version 2.7), pas le PyPy. version. De plus, je ne vérifie pas les chiffres sur place. Tous les candidats sont vérifiés.

Voici les principales améliorations:

  1. Utilisez un générateur de nombres premiers ( https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618 ) pour créer une liste de nombres premiers à vérifier et (sa version de "petits nombres premiers") et pour générer des longueurs de numéros éligibles.

  2. Nous voulons passer notre temps à chercher le plus grand nombre premier d'une longueur donnée, et non le plus petit. Je construis donc d'abord le plus grand nombre possible à vérifier, et non le plus petit. Ensuite, une fois trouvé, nous pouvons passer immédiatement à la longueur suivante.

EDIT: Maintenant avec le multitraitement

C'est un changement significatif par rapport aux versions précédentes. Auparavant, j’avais remarqué que ma machine à 8 cœurs fonctionnait à peine, j’ai donc décidé de tenter le multitraitement en Python (première fois). Les résultats sont très sympas!

Dans cette version, 7 processus enfants sont générés, lesquels saisissent une "tâche" dans une file d'attente de possibilités potentielles (num_length + chiffres éligibles). Ils essaient différentes positions [7,5,3] jusqu'à ce qu'il en trouve une. Si tel est le cas, informe le processus maître de la nouvelle longueur la plus longue trouvée. Si les enfants travaillent sur une longueur de num_ntre plus courte, ils se contentent de renflouer et d'aller chercher la longueur suivante.

J'ai commencé cette course avec 6000 et elle fonctionne toujours, mais jusqu'à présent, je suis très satisfaite des résultats.

Le programme ne s’arrête pas encore correctement, mais ce n’est pas un problème pour moi.

Maintenant le 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
la source
la lecture serait plus nette si vous représentiez le lien du codepad comme une importation [interrompue, si nécessaire]
Sparr
Je pense que cela serait déroutant, car le code à l'autre bout n'est pas vraiment importable comme ça.
Mkoistinen
utilisez la syntaxe de isaacg. commentez l'URL, puis importez-le à partir d'un paquet inexistant (my_math, dans son cas)
Sparr
1
En fait, je génère aussi les nombres du plus grand au plus petit. Je ne pense pas que nos différences de code soient très significatives. Je m'attendrais à ce que la différence réside davantage dans nos ordinateurs que dans notre code. Néanmoins, bravo et bienvenue sur le site.
isaacg
my_mathpeut également être utilisé pour générer une liste de nombres premiers, à la while prime < 20006: prime = next_prime(prime). Cela semble être environ 3 fois plus rapide gen_primeset une mémoire beaucoup plus efficace.
Primo
6

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

Félicitations à @issacg et à vous tous pour vos inspirations et astuces.
Et aussi le poseur de questions magistral @ Calvin's Hobbies pour cette question.

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

Si vous souhaitez donner votre puissance de calcul ou être curieux de la performance, n'hésitez pas à copier le code et à le compiler. ;) Vous aurez besoin de GMP installé.

#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;
}
Vectorisé
la source
5

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

Exécutez PFGW avec le fichier d’entrée suivant et -f100préfactorez les nombres. Dans environ 2-3 minutes de temps processeur sur mon ordinateur (i5 Haswell), il trouve le PRP (10 ^ (6073-6) -1) / 9 + 6 * 10 ^ 110, ou {5956} 7 {110} . J'ai choisi 6 000 chiffres comme point de départ, car il s'agit d'un nombre un peu plus élevé que celui de toutes les soumissions précédentes.

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

En fonction de la rapidité avec laquelle j'ai pu trouver celui-ci, je pouvais facilement augmenter le nombre de chiffres tout en trouvant un PRP en moins d'une heure. Avec la façon dont les règles sont écrites, je pourrais même trouver juste la taille où mon processeur, fonctionnant sur les 4 cœurs, peut terminer un test PRP en une heure, prendre beaucoup de temps pour trouver un PRP et avoir uniquement ma "recherche". de l'un PRP.

PS En un sens, ce n’est pas une solution de "code" car je n’ai rien écrit à part le fichier d’entrée ... mais de nombreuses solutions Mathematica à une ligne pourraient être décrites de la même manière, tout comme en utilisant une bibliothèque qui fait le travail difficile pour vous. En réalité, je pense qu'il est difficile de tracer une bonne ligne de démarcation entre les deux. Si vous le souhaitez, je pourrais écrire un script qui crée le fichier d’entrée PFGW et appelle PFGW. Le script pourrait même chercher en parallèle, utiliser les 4 cœurs et accélérer la recherche d'environ 4 fois (sur mon processeur).

PPS Je pense que LLR peut effectuer les tests PRP pour ces chiffres et je m'attendrais à ce que ce soit beaucoup plus rapide que PFGW . Un programme de tamisage dédié pourrait également être plus efficace pour factoriser ces chiffres que l'un après l'autre. Si vous les combinez, je suis sûr que vous pourrez pousser les limites beaucoup plus haut que les solutions actuelles.

Tim S.
la source
4

Python 2.7, 17-19 chiffres

11111111171111111

Trouvé 5111111111111 (13 chiffres) en 3 secondes et ce nombre primordial de 17 chiffres en 3 minutes. Je devine que la machine cible pourrait exécuter ceci et obtenir un nombre premier suprême à 19 chiffres en moins d'une heure. Cette approche échoue car elle garde les nombres premiers jusqu'à la moitié du nombre de chiffres cibles en mémoire. La recherche à 17 chiffres nécessite de stocker un tableau de 100 millions de booléens. 19 chiffres nécessiteraient un tableau d’éléments 1B et la mémoire serait épuisée avant d’obtenir 23 chiffres. Le temps d'exécution le serait probablement aussi.

Les approches de test de primalité qui n'impliquent pas un nombre ridiculement grand de nombres premiers diviseurs se porteront beaucoup mieux.

#!/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
la source
3

Mathematica 4211 4259 chiffres

Avec le numéro: {1042} 7 {3168} {388} 3 {3870}

Qui a été généré par le code suivant:

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]

Les lancers font qu’il arrête de tester d’autres numéros avec les mêmes chiffres que celui actuellement trouvé. dans la mesure où il commence à tester le chiffre le plus significatif, cela signifie qu'il renvoie toujours le nombre le plus grand, à moins que le nombre de chiffres ne soit membre d'un triplet principal.

Tout simplement commencé à tester juste en dessous de la valeur d'une des réponses précédentes :)

Une fois terminé, le nombre est stocké dans la variable curlargest

Pointage
la source
2

JavaScript, 3019 chiffres, {2 273} 5 {745}

Ceci utilise le test MillerRabin inclus dans BigInteger.js de Tom Wu.

À partir de 0 => 2 046 chiffres = {1799} 7 {263} en une heure .

À partir de 3000 => 3 019 chiffres = {2 273} 5 {745} en une heure, moins de 3 secondes .

Quand il est parti de 0, le programme a sauté et a recommencé la recherche à une longueur de 1,5 fois la longueur du dernier s-prime trouvé. Puis, quand j’ai vu à quelle vitesse cela fonctionnait, j’ai pensé qu’il en trouverait un à partir de 3 000 en une heure - ce qu’il a fait avec seulement 3 secondes à perdre.

Vous pouvez l'essayer ici: http://goo.gl/t3TmTk
(paramétré pour calculer tous les nombres s-premiers, ou passer au suivant.)

entrez la description de l'image ici entrez la description de l'image ici
entrez la description de l'image ici

Le programme fonctionne en construisant des chaînes de tous les "1", mais avec un "3", "5" ou "7". J'ai ajouté une vérification rapide dans la fonction IsStrPrime pour rejeter les nombres se terminant par "5".

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;
        }
    }
}

C'était très amusant. Cela me rappelle un casse-tête que j'avais créé il y a de nombreuses années pour calculer ce que l'on appelle un nombre premier supprimé . C'est un nombre premier qui, si vous supprimez un chiffre, le nombre restant est toujours premier. Par exemple, 1037 est un nombre supprimé car les nombres 1037, 037, 137, 107 et 103 sont des nombres premiers. J'en ai trouvé un de 84 chiffres, et le plus long que je connaisse est de 332 chiffres. Je suis sûr que nous pourrions en trouver beaucoup plus longtemps avec les techniques utilisées pour ce puzzle. (Mais choisir les numéros d'essai est un peu plus compliqué - peut-être?)

JeffSB
la source
RE: chiffre supprimé premier, nous avons eu celui-là ici . 332 chiffres auraient également gagné.
primo
0

Axiome, 3019 chiffres {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

résultat de la valeur de départ 3000 en 529 secondes

(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
la source