Trova il primo più grande la cui lunghezza, somma e prodotto sono primi


37

Il numero 113è il primo numero primo la cui lunghezza 3è numero primo, la somma digitale 5 = 1 + 1 + 3è numero primo e il prodotto digitale 3 = 1 * 1 * 3è numero primo.

Un numero primo che ha queste 3 proprietà verrà chiamato supremamente primo . I numeri primi 11117e 1111151sono altri esempi.

Obbiettivo

Scrivi un programma in grado di trovare il più grande numero primo possibile in meno di un'ora su un personal computer moderno decente (come le specifiche preferite qui ).

Non dovresti semplicemente darci un grande numero supremo. Devi mostrarci il tuo processo di ricerca con il codice che funziona davvero. Puoi basarti sulle soluzioni della tua o di altre persone ma assicurati di dar loro credito. In un certo senso stiamo cercando in comune di trovare il massimo supremo più grande realizzabile su un normale computer in un'ora.

punteggio

La sottomissione che trova il più grande numero primo supremo vince. Se si scopre che ci sono finiti molti numeri primi supremi, vince la prima sottomissione che genera il primo supremo più alto.

(Se riesci a dimostrare matematicamente che ci sono o non ci sono infiniti numeri primi supremi, ti darò 200 rappresentanti di taglie solo perché. :))

Dettagli

  • È possibile utilizzare qualsiasi fonte per generare i numeri primi (ad esempio Internet).
  • È possibile utilizzare metodi probabilistici di test primi.
  • Tutto è nella base 10.
  • Zero e uno NON sono considerati primi.
  • I primi che contengono 0hanno un prodotto digitale, 0quindi ovviamente non possono essere supremi.
  • Per mantenere la pagina meno ingombra, inserisci i numeri primi supremi (100+ cifre) nella forma:

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

    Quindi 1111151potrebbe essere espresso come {5}5{1}.


Possiamo iniziare con un elenco di numeri primi o recuperare un elenco da Internet e trascorrere l'ora facendo i controlli di supremeness?
Sparr,

2
Se puoi iniziare con il massimo supremo conosciuto più alto, allora questo diventa una sfida per chi può scrivere un programma che trascorre esattamente un'ora che copra il più grande divario possibile tra due numeri primi supremi. :(
Sparr,

8
Oltre a non contenere uno 0, qualsiasi potenziale primo supremo deve ovviamente avere la forma 1 ^ n [3 | 5 | 7] 1 ^ m, cioè alcuni 1s, qualsiasi numero primo inferiore a 10 e alcuni altri 1s. Ci sono più vincoli che puoi applicare subito.
Ingo Bürk,

3
Ryan ha posto una domanda correlata al MSE sull'esistenza di infiniti numeri primi supremi. Se hai qualche idea per quella domanda, ti preghiamo di ponderare!
Semiclassico

1
Posso facilmente dimostrare che al momento non esiste una prova di un numero infinito di numeri primi supremi (e che una notevole quantità di lavoro è andata verso di esso). Secondo michaelnielsen.org/polymath1/… , sappiamo che i numeri primi arrivano all'infinito con spazi piccoli fino a 246, ma per una prova di infiniti numeri primi supremi, abbiamo bisogno di uno spazio di 2, 4 o 6 (corrispondente ai numeri primi con un 3, 5 o 7 da qualche parte in loro).
Tim S.

Risposte:


9

Perl, 15101 cifre, {83} 7 {15017}, 8 minuti. Numero massimo trovato: 72227 cifre

Utilizzando il mio modulo Math :: Prime :: Util e il suo back-end GMP . Ha una serie di test di composizione tra cui is_prob_prime () con un test ES BPSW (leggermente più rigoroso dell'ispseudoprime di Pari), is_prime () che aggiunge un MR a base casuale e is_provable_prime () che eseguirà BLS75 T5 o ECPP. A queste dimensioni e tipi, fare una prova richiederà molto tempo. Ho lanciato un altro test MR nel sottotitolo del verificatore pedante. Tempi su un Core2 E7500 che sicuramente non è il mio computer più veloce (ci vogliono 2,5 minuti sul mio i7-4770K).

Come sottolinea Tim S., potremmo continuare a cercare valori più grandi, fino al punto in cui un singolo test dura un'ora. A ~ 15000 cifre su questo E7500 ci vogliono circa 26 secondi per un test MR e 2 minuti per l'intero is_prime (divisione di prova più MR base-2 più ES Lucas più un MR base casuale). Il mio i7-4770K è oltre 3 volte più veloce. Ho provato alcune dimensioni, principalmente vedendo come ha fatto sui risultati di altre persone. Ho provato 8k, 20k e 16k, uccidendo ciascuno dopo ~ 5 minuti. Ho quindi provato 15k in progressione per ~ 10m ciascuno e sono stato fortunato sul 4 °.

I test PRP di OpenPFGW sono certamente più veloci dopo circa 4000 cifre e molto più veloci nel range di 50k +. Il suo test ha comunque una buona quantità di falsi positivi, il che lo rende un ottimo pre-test, ma si vorrebbe comunque verificare i risultati con qualcos'altro.

Questo potrebbe essere parallelizzato con thread perl o usando MCE simile agli esempi di finder di Fibonacci paralleli nel modulo.

Tempi e risultati su un i7-4770K inattivo con core singolo:

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

Per il risultato di 32k cifre, ho avviato 6 script in esecuzione contemporaneamente con argomenti successivi a partire da 32000. Dopo 26,5 minuti uno ha terminato con il risultato di 32063 cifre mostrato. Per 57k lascio che gli script successivi vengano eseguiti 6 alla volta per un'ora con incrementi di input di 500 fino a quando il risultato 57k non viene restituito in 57 minuti. Il risultato di 72k cifre è stato trovato eseguendo numeri primi successivi da 70k in su, quindi sicuramente non trovato in un'ora (anche se una volta che sai da dove cominciare, lo è).

Il copione:

#!/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";
}

+1 per avermi fatto conoscere questa biblioteca! Tempi sulla mia macchina per iterare i numeri primi inferiori a 10 ^ 7 (rispetto a CPython con gmpy2e PyPy con my_math): codepad.org/aSzc0esT
primo

Contento che ti piaccia! Ci sono altri modi tra forprimes { ...do stuff... } 1e7;cui 10 volte o più veloce (complimenti a Pari / GP per molte idee fantastiche). Apprezzo sempre il feedback, quindi fammi sapere se qualcosa non funziona come desideri.
DanaJ,

21

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

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Ho trovato questo circa 50 minuti dopo aver iniziato dal 4000. Pertanto, stimerei che questo sia il limite superiore di questo approccio al codice.

Modifica: ho notato che alcune lunghezze sembrano essere più fruttuose per generare questo tipo di numeri primi rispetto ad altre, quindi ho deciso di controllare solo 50 posizioni casuali della cifra che non sono 1 anziché tutte le posizioni possibili, prima di spostare su. Non sono del tutto sicuro che questo migliorerà le prestazioni o che 50 sia corretto, ma vedremo.

L'elenco delle possibilità viene generato in base al fatto che per soddisfare i requisiti dei prodotti, il numero deve essere tutti tranne un numero primo. Inoltre, il numero primo non può essere 2 a causa della relazione somma e lunghezza e la somma digitale non deve essere divisibile per tre, fornendo i requisiti% 3.

is_prime tratto da http://codepad.org/KtXsydxK , scritto da @primo

Nota: questa funzione is_prime è in realtà un test pseudoprime di Baillie-PSW, ma non ci sono contro-esempi noti, quindi non mi preoccuperò della distinzione.

#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

Purtroppo non so altro che il link. Ho trovato il link qui: codegolf.stackexchange.com/questions/10739/… Prima risposta
isaacg

Bene allora. Ti darò credito.
Isaacg,

10
È come un ASCII dove sta bene ...
trichoplax

5
Forse dovresti rinominare la funzione is_very_very_very_very_very_very_very_probably_prime()...
trichoplax

2
Mathmatica e Maple usano entrambi lo stesso metodo, quindi non può essere poi così male.
primo

13

PARI / GP, 4127 cifre

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

Questa è una ricerca abbastanza semplice: controlla solo le lunghezze delle cifre primi, quindi calcola i numeri primi possibili da usare, quindi passa in rassegna tutte le possibilità. Ho inserito in casi speciali i casi comuni in cui vi sono 0 o 1 numeri primi adatti da utilizzare.

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)

Ci sono voluti 36 minuti per calcolare su un nucleo di una macchina abbastanza vecchia. Non avrei problemi a trovare un numero così alto di oltre 5000 cifre in un'ora, ne sono certo, ma sono anche impaziente.

Una soluzione migliore sarebbe quella di usare qualsiasi linguaggio ragionevole per fare tutto tranne il ciclo più interno, quindi costruire un file abc per primeform che è ottimizzato per quel particolare tipo di calcolo. Questo dovrebbe essere in grado di spingere il calcolo fino ad almeno 10.000 cifre.

Modifica : ho implementato la soluzione ibrida sopra descritta, ma sulla mia vecchia macchina non riesco a trovare il primo termine con> = 10.000 cifre in meno di un'ora. A meno che non lo esegua su qualcosa di più veloce, dovrò passare a un obiettivo meno elevato.


Come hai saputo iniziare a 4100?
isaacg

@isaacg: stavo solo cercando di essere più grande della (non corretta) soluzione Mathematica, che era poco più di 4000. Sono appena passato al multiplo successivo di 100 come un numero "niente-in-tasca". In realtà sembra che questo sia stato uno sfortunato punto di partenza, poiché ho dovuto andare più a lungo di quanto mi aspettassi (e più a lungo di Mathematica!) Per trovare un numero primo.
Charles,

No, in realtà, sei stato incredibilmente fortunato. (4127,3) è la prima coppia dopo 4100, e per puro caso sembra avere un numero primo. Molte coppie non hanno alcun numero primo.
isaacg

@isaacg: forse è così. La mia euristica è chiaramente disattivata, dal momento che mi sarei aspettato una probabilità dell'80% di trovare un numero primo in una data coppia: 1 - exp (-15 / (4 * log 10)), ma sembrano essere più rari di così, quindi hanno non comportarti come numeri casuali {2, 3, 5} delle loro dimensioni (a meno che non abbia preso in giro il calcolo).
Charles,

@isaacg: In ogni caso sto lavorando alla "soluzione migliore" di cui ho parlato ora: spingere il duro lavoro a pfgw. Ha cercato le prime 20 coppie sopra 10 ^ 10000 senza trovare nulla, ma ci sono voluti solo ~ 15 minuti.
Charles,

7

Mathematica 3181 cifre

Aggiornamento: ci sono stati alcuni errori gravi nella mia prima presentazione. Sono stato in grado di dedicare un po 'di tempo al controllo dei risultati per questo. L'output è formattato come un elenco di cifre. Ciò consente un facile controllo di ciascuna delle condizioni.

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

Esempio

Questo è stato il mio primo test, una ricerca di una soluzione con 3181 cifre. Ha trovato il primo caso in 26 secondi.

Analizziamo il ragionamento. Quindi entreremo nel programma stesso.

Cominciamo, come ho fatto, "Qual è il 450 ° primo?" Possiamo trovare una soluzione con così tante cifre (3181)?

primeDigits = Prime[450]

3181


Il numero viene trovato unendo le cifre.

number = FromDigits[digits];

Ma piuttosto che mostrarlo, possiamo chiedere invece quali sono le cifre e dove si trovano.

DigitCount[number]

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

Ciò significa che c'erano 3180 istanze della cifra 1 e una singola istanza della cifra 7.

In quale posizione è la cifra 7?

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

142

Quindi la cifra 7 è la 142a cifra. Tutti gli altri sono 1.


Naturalmente, il prodotto delle cifre deve essere un numero primo, vale a dire 7.

digitProduct = Times @@ digits

7


E anche la somma delle cifre è un numero primo.

digitSum = Plus @@ digits
PrimeQ[digitSum]

3187
True


E sappiamo che il numero di cifre è un numero primo. Ricorda, abbiamo selezionato il 450 ° numero primo, ovvero 3118.

Quindi tutte le condizioni sono state soddisfatte.


3
Se non sbaglio, la sua somma è 4009 che non è un numero primo.
Gerw,

Una cosa: non dovrebbe essere la somma di tutte le cifre prime e non il numero di cifre? Nel tuo caso dovresti testare 4002 * 1 + 7 = 4009e non 4003 secondo le specifiche.
Johnride,

2
@Johnride: entrambi dovrebbero essere primi.
Gerw,

@gerw ha ragione. Il numero di cifre E la somma delle cifre E il prodotto delle cifre devono essere tutti primi.
Calvin's Hobbies,

Avevi tutti ragione. Nella mia precedente presentazione ho dimenticato di controllare la somma delle cifre per la primalità. Questo ora viene fatto verificando se uno dei seguenti (non importa quale) è primo: lunghezza cifre + 2, lunghezza cifre _4 o lunghezza cifre +6.
David C

7

Python 2.7, 6217 cifre: {23} 5 {6193} 6 minuti 51 secondi

Stavo lavorando sulla mia versione e sono rimasto deluso nel vedere che @issacg mi ha battuto sul pugno con un approccio molto simile, sebbene con is_ (molto_probabilmente) _prime (). Tuttavia, vedo che ho alcune differenze significative che si traducono in una risposta migliore in meno tempo (quando utilizzo anche is_prime). Per chiarire questo, anche a partire dal 4000, arrivo a una risposta migliore di 4001 cifre ({393} 7 {3607}) in soli 26 minuti, 37 secondi usando l' interprete Python standard (anche alla versione 2.7), non il PyPy versione. Inoltre, non sto "controllando" i numeri. Tutti i candidati sono controllati.

Ecco i principali miglioramenti:

  1. Utilizzare un generatore di numeri primi ( https://stackoverflow.com/questions/567222/simple-prime-generator-in-python/568618#568618 ) per creare un elenco di numeri primi da verificare e (la sua versione di "piccoli numeri primi") e per generare lunghezze di numero ammissibili.

  2. Vogliamo passare il nostro tempo a cercare il massimo supremo più grande di una determinata lunghezza, non il più piccolo, quindi costruisco prima i numeri più grandi possibili per il controllo, non il più piccolo. Quindi, una volta trovato, possiamo passare immediatamente alla lunghezza successiva.

EDIT: ora con multiprocessing

Questa è una modifica significativa rispetto alle versioni precedenti. In precedenza, ho notato che la mia macchina a 8 core funzionava a malapena, quindi ho deciso di cimentarmi con il multiprocessing in Python (la prima volta). I risultati sono molto belli!

In questa versione, vengono generati 7 processi figlio, che afferrano un 'task' da una coda di potenziali possibilità (num_length + cifre idonee). Sfornano provando diverse posizioni [7,5,3] fino a quando non ne trova una. In tal caso, informa il processo principale della nuova lunghezza più lunga trovata. Se i bambini stanno lavorando su un num_length più corto, eseguono semplicemente la cauzione e ottengono la lunghezza successiva.

Ho iniziato questa corsa con 6000, ed è ancora in esecuzione, ma finora sono molto soddisfatto dei risultati.

Il programma non si ferma ancora correttamente, ma non è un grosso problema per me.

Ora il codice:

#!/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))

leggerebbe più chiaramente se rappresenti il ​​collegamento del codepad come importazione [rotta, se necessario]
Sparr

Penso che sarebbe confuso, dal momento che il codice all'altra estremità non è davvero improprio come quello.
mkoistinen,

usa la sintassi di isaacg. commentare l'URL, quindi importare da un pacchetto inesistente (my_math, nel suo caso)
Sparr

1
In realtà, anche io generi i numeri dal più grande al più piccolo. Non penso che le nostre differenze di codice siano molto significative. Mi aspetto che la differenza risieda più nei nostri computer che nel nostro codice. Tuttavia, ben fatto e benvenuto nel sito.
isaacg,

my_mathpuò anche essere usato per generare un elenco di numeri primi, à la while prime < 20006: prime = next_prime(prime). Sembra essere circa 3 volte più veloce digen_primes e molto più efficiente della memoria.
primo

6

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

Complimenti a @issacg e a tutti voi ragazzi per le ispirazioni e i trucchi.
E anche la domanda magistrale asker @ Calvin's Hobbies per questa domanda.

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

Se hai voglia di donare il tuo potere di calcolo o sei curioso della performance, copia gratuitamente il codice e compila. ;) Avrai bisogno di GMP installato.

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

5

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

Eseguire PFGW con il seguente file di input e -f100prefattorizzare i numeri. In circa 2-3 minuti di CPU sul mio computer (i5 Haswell), trova il PRP (10 ^ (6073-6) -1) / 9 + 6 * 10 ^ 110 o {5956} 7 {110} . Ho scelto 6000 cifre come punto di partenza come un numero a portata di mano che è un po 'più alto di tutti i precedenti invii.

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

In base alla velocità con cui sono riuscito a trovarlo, ho potuto facilmente aumentare il numero di cifre e trovare ancora un PRP entro un'ora. Con come sono scritte le regole, potrei anche solo trovare la dimensione in cui la mia CPU, in esecuzione su tutti e 4 i core, può finire un test PRP in un'ora, fare un molto tempo tempo a trovare un PRP e avere la mia "ricerca" dell'unico PRP.

PS In alcuni sensi, questa non è una soluzione "di codice" perché non ho scritto nulla oltre al file di input ... ma poi, molte soluzioni Mathematica a una riga per problemi matematici potrebbero essere descritte allo stesso modo, come potrebbe usando una libreria che fa il duro lavoro per te. In realtà, penso che sia difficile tracciare una buona linea tra i due. Se vuoi, potrei scrivere uno script che crea il file di input PFGW e chiama PFGW. Lo script potrebbe anche cercare in parallelo, per utilizzare tutti e 4 i core e velocizzare la ricerca di ~ 4 volte (sulla mia CPU).

PPS Penso che LLR possa fare i test PRP per questi numeri, e mi aspetto che sia molto più veloce di PFGW . Un programma di setacciatura dedicato potrebbe anche essere migliore nel fattorizzare questi numeri rispetto a quello di PFGW uno alla volta. Se li combinassi, sono sicuro che potresti spingere i limiti molto più in alto rispetto alle soluzioni attuali.


4

Python 2.7, 17-19 cifre

11111111171111111

Trovato 5111111111111 (13 cifre) in 3 secondi e questo primo supremo a 17 cifre in 3 minuti. Immagino che la macchina bersaglio potrebbe farcela e ottenere un massimo supremo di 19 cifre in meno di un'ora. Questo approccio non si adatta bene perché mantiene in memoria i numeri primi fino alla metà del numero di cifre target. La ricerca a 17 cifre richiede l'archiviazione di un array di 100 milioni di booleani. 19 cifre richiederebbero un array di elementi 1B e la memoria si esaurirebbe prima di arrivare a 23 cifre. Probabilmente lo sarebbe anche il runtime.

Gli approcci ai test di primalità che non implicano una gamma ridicolmente ampia di numeri primi divisori andranno molto meglio.

#!/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

3

Mathematica 4211 4259 cifre

Con il numero: {1042} 7 {3168} {388} 3 {3870}

Che è stato generato dal seguente codice:

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]

I tiri causano l'interruzione del test per altri numeri con le stesse cifre di quello attualmente trovato. poiché inizia il test sulla cifra più significativa, ciò significa che restituisce sempre il numero più grande a meno che il numero di cifre non sia un membro di una tripletta principale.

Ho semplicemente iniziato i test appena al di sotto del valore di una delle risposte precedenti :)

Una volta terminato, il numero viene memorizzato nella variabile più curva


2

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

Questo utilizza il test MillerRabin incluso in BigInteger.js di Tom Wu.

Partendo da 0 => 2.046 cifre = {1799} 7 {263} in un'ora .

Partendo da 3000 => 3.019 cifre = {2.273} 5 {745} in un'ora, meno 3 secondi .

Quando è iniziato da 0, il programma è saltato avanti e ha ricominciato a cercare una lunghezza di 1,5 volte la lunghezza dell'ultimo s-prime trovato. Poi, quando ho visto la sua velocità, ho immaginato che avrebbe trovato uno a partire da 3000 in un'ora - cosa che ha fatto con solo 3 secondi di riserva.

Puoi provarlo qui: http://goo.gl/t3TmTk
(Imposta per calcolare tutti gli s-primes o salta avanti.)

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine
inserisci qui la descrizione dell'immagine

Il programma funziona costruendo stringhe di tutti gli "1", ma con un "3", "5" o "7". Ho aggiunto un rapido controllo nella funzione IsStrPrime per rifiutare i numeri che terminano con "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;
        }
    }
}

Questo è stato abbastanza divertente. Mi ricorda un enigma che ho fatto molti anni fa per calcolare quella che viene chiamata una cifra rimossa in numero primo . Questo è un numero primo che se si rimuove qualsiasi cifra, il numero rimanente è ancora primo. Ad esempio 1037 è una cifra rimossa per primo perché 1037, 037, 137, 107 e 103 sono primi. Ho trovato una lunghezza di 84 cifre e la più lunga che conosco è lunga 332 cifre. Sono sicuro che potremmo trovarne uno molto più a lungo con le tecniche utilizzate per questo puzzle. (Ma scegliere i numeri di prova è un po 'più complicato - forse?)


RE: cifra rimossa per prime, qui l'abbiamo qui . Anche 332 cifre avrebbero vinto.
primo

0

Axiom, 3019 cifre {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

risultato dal valore iniziale 3000 in 529 sec

(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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.