Il programma che troverà il prossimo numero primo


15

Intro:


Hai corrotto accidentalmente il flusso del tempo con un dispositivo creato per divertimento, che si è rivelato essere una macchina del tempo. Di conseguenza, sei stato spinto nel lontano futuro. Ti sei reso conto che il calcolo, la potenza di elaborazione e i computer in generale si sono evoluti di una quantità enorme, una quantità infinita per essere precisi . Quindi ti prendi un computer con memoria infinita e potenza di elaborazione. Non hai idea di come possa avere memoria infinita e potenza di elaborazione infinita, ma la accetti e torni al presente.

Sfida:


Hai sentito che la persona che ha scoperto il primo più grande attualmente è 2^74,207,281 − 1stato pagato $ 100.000. Decidi di creare un programma che trova il prossimo primo, poiché vuoi recuperare i soldi spesi per il computer. Ne fai uno che accetta l'input di un numero e trova il primo numero primo successivo, mediante bruteforcing o qualsiasi altro metodo.

Chiarimenti: hai una macchina ipotetica con memoria infinita e potenza di elaborazione. Il tuo programma NON DEVE essere limitato (ad esempio: gli int di C # possono memorizzare da -2,147,483,648a 2,147,483,647), bene il tuo programma deve essere in grado di memorizzare e funzionare con qualsiasi numero di qualsiasi dimensione. Hai risorse infinite, quindi non dovresti preoccuparti di rimanere senza memoria se lo permettessi.

Esempio di I / O:
input: il primo più grande attualmente scoperto con 22.338.618 cifre.
Output: esattamente il prossimo primo

Ovviamente, non devi dimostrare che funziona, poiché ci vorrebbe un sacco di tempo per calcolare in una macchina fisica. Ma se hai spostato il tuo programma su una macchina ipotetica con una potenza / memoria di elaborazione infinita, dovrebbe essere calcolato immediatamente.


Trovare il primo primo e verificare se un numero è un primo, sono due cose completamente diverse


1
Deve essere specificamente il prossimo primo ? Molti algoritmi di ricerca di numeri primi grandi cercano solo determinati tipi di numeri e quindi a volte mancano numeri primi ...
FlipTack

10
Penso che dovresti aggiungere alcuni casi di test seri.
FlipTack

3
" Il tuo programma NON DEVE essere limitato ", ma sulla base dell'esempio sospetto che ogni singola lingua esistente sia considerata limitata se non adatta a nessun altro motivo se non l'uso di un tipo finito per indirizzare la memoria.
Peter Taylor,


2
@ mbomb007 perché? Tutte le risposte tranne quelle integrate viste per aggiungere solo un wrapper aggiuntivo.
Post Rock Garf Hunter,

Risposte:



8

Python 3 , 45 byte

f=lambda n,k=1,m=1:m%k*k>n or-~f(n,k+1,m*k*k)

Provalo online!


3
Credo che questo sia il teorema di Wilson sotto mentite spoglie. kè uguale al risultato finale, mcontiene (k-1)!^2. Da (k-1)! = -1 mod k vale solo quando k è primo, abbiamo (k-1)! (K-1)! = 1 mod k, che quando moltiplicato per k sarà k stesso. Calcoli il quadrato per sbarazzarti dell'unica eccezione di (k-1)! = 0 mod k per k composito, che si verifica per k = 4. Corretto?
orlp

Si, è corretto.
Dennis,

Questo vale RecursionError: maximum recursion depth exceeded in comparisonperf(1000)
ovs

5
@ovs La domanda dice che abbiamo una memoria infinita. Pertanto, possiamo assumere un limite di profondità di ricorsione infinitamente elevato, e quindi non preoccuparci RecursionError.
FlipTack

6

Python 2, 78 77 76 74 byte

def f(n):
 while 1:
    n+=1
    if[i for i in range(1,n)if n%i<1]==[1]:return n

-1 byte grazie a @KritixiLithos
-1 byte grazie a @FlipTack
-2 byte grazie a @ElPedro


n%i<1è più corto din%i==0
Kritixi Lithos il

Non è necessario spazio dopo if.
FlipTack

Penso che intendi<1
Jonathan Allan il

Penso che puoi usare una scheda invece di 2 spazi per i rientri di secondo livello, ma al momento non posso testare.
ElPedro,

1
@ElPedro ha ragione. È possibile modificare i 2 spazi davanti n+=1e ifin schede e salvare 2 byte



4

Bash + coreutils, 52 byte

for((n=$1,n++;`factor $n|wc -w`-2;n++)){ :;};echo $n

Provalo online!

La documentazione per bash e factor non specifica un valore intero massimo che può gestire (sebbene, in pratica, ogni implementazione abbia un valore intero massimo). Presumibilmente, nella GNU del futuro sulle tue macchine infinitamente grandi, bash e factor avranno numeri interi di dimensioni illimitate.


In realtà i documenti specificano per fattore che se costruito senza gnu mp è supportata solo la precisione singola.
Dani_l

1
@Dani_l Bene, la voce man per bash dice solo: "La valutazione è fatta in numeri interi a larghezza fissa senza controllo per overflow, sebbene la divisione per 0 sia intrappolata e contrassegnata come un errore." Non specifica la larghezza. (Come ricordo, le implementazioni di stock di bash sulle mie macchine usano numeri interi con segno a 64 bit, ma non posso controllare ora.) Per quanto riguarda il fattore, sarà sicuramente aggiornato: i futuri computer del PO con risorse infinite avranno un fattore compilato con gnu_up per ottenere una precisione illimitata :).
Mitchell Spector,

3

Maxima, 10 byte

next_prime

Una funzione restituisce il primo più piccolo più grande del suo argomento.



3

Python con sympy, 28 byte

import sympy
sympy.nextprime

sympy.nextprimeè una funzione che fa ciò che dice sulla scatola. Funziona con tutti i galleggianti.

repl.it


Python, 66 59 byte

-4 byte grazie a Lynn (uso -~)
-3 byte grazie a FlipTack (uso ande or, consentendo ...==1di passare a una ...-1condizione).

f=lambda n:sum(-~n%-~i<1for i in range(n))-1and f(n+1)or-~n

repl.it

Una funzione ricorsiva che conta fino a nquando non viene trovato un numero primo verificando che esiste un solo numero n-1che lo divide (ovvero 1). Funziona per tutti i numeri interi, genera un errore per i float.

Funziona su 2.7.8 e 3.5.2, non funziona su 3.3.3 (errore di sintassi a causa della mancanza di spazio tra ==1e else)


(n+1)%(i+1)è -~n%-~i, penso.
Lynn,

Grazie, stavo provando a farne uno più breve usando il teorema di Wilson.
Jonathan Allan,

Il corto circuito and/ orfunziona, come f=lambda n:sum(-~n%-~i<1for i in range(n))==1and-~n or f(n+1)?
FlipTack

In effetti, ^ può essere giocato af=lambda n:sum(-~n%-~i<1for i in range(n))-1and f(n+1)or-~n
FlipTack il

@FlipTack Inizialmente li avevo evitati in modo che potesse passare attraverso zero, ma funzionerà - è un salvataggio di tre byte!
Jonathan Allan,

2

Python, 114 83 byte

def g(b):
 while 1:
  b+=1
  for i in range(2,b):
   if b%i<1:break
  else:return b

Senza builtin, se ce ne sono.

-30 rimuovendo gli spazi bianchi e -1 cambiando b%i==0inb%i<1


3
Questo non troverà il prossimo primo se lo metti1
FlipTack

Si assume ora che b> 2
sagiksp, il

Non puoi semplicemente inventare le tue regole ... devi seguire le specifiche della sfida. Da nessuna parte si dice che puoi assumere i limiti dell'input.
FlipTack

Anche con questo presupposto, ciò fallisce per tutti gli input anche valutati.
FlipTack

Sono un idiota, l'ho letto male. Aggiustato. @FlipTack
sagiksp,

2

Perl 6 , 25 byte

{first *.is-prime,$_^..*}

Come funziona

{                       }  # A lambda.
                  $_ ..*   # Range from the lambda argument to infinity,
                    ^      # not including the start point.
 first           ,         # Iterate the range and return the first number which
       *.is-prime          # is prime.

Perl 6 , 32 byte

{first {all $_ X%2..^$_},$_^..*}

Con inefficienti test di primalità personalizzati.

Come funziona

La struttura esterna è la stessa di sopra, ma il predicato passato a first(per decidere se un determinato numero è primo), ora è:

{               }  # A lambda.
     $_            # Lambda argument (number to be tested).
          2..^$_   # Range from 2 to the argument, excluding the end-point.
        X          # Cartesian product of the two,
         %         # with the modulo operator applied to each pair.
 all               # Return True if all the modulo results are truthy (i.e. non-0).

Speravo di ottenere qualcosa di più corto con Perl 5 ma è difficile battere un built-in .is-prime;)
Zaid

2

Pyke, 8 7 byte

~p#Q>)h

Provalo qui!

4 byte, non competitivi

(Interprete aggiornato dalla pubblicazione della sfida)

~p<h

Provalo qui!

~p   -   primes_iterator()
  <  -  filter(^, input() < i)
   h - ^[0]

Perché la seconda non competitiva? Non capisco abbastanza
theonlygusti,

@theonlygusti: in genere, l'unico motivo legittimo per contrassegnare una presentazione non competitiva qui (invece di non inviarla affatto) è perché hai corretto un bug o aggiunto una funzione nella lingua in cui è scritto il programma e che ti ha aiutato nella sfida . (Tendo a scriverlo come "sfida postdatati in lingua" per essere più chiari.)

Chiarito @theonlygusti
Blue


1

05AB1E , 16 13 byte (Emigna @ -3 byte)

2•7£?ÿ•o[>Dp#

Provalo online!

2•7£?ÿ•o        # Push current largest prime.
        [   #    # Until true..
         >Dp    # Increment by 1, store, check primality.
                # After infinite loop, implicitly return next prime.

Non [>Dp#funzionerebbe?
Emigna,

Puoi ancora tagliare altri 8 byte poiché il programma dovrebbe prendere un numero primo come input e produrre il primo successivo.
Emigna,

@Emigna allora questa domanda è un duplicato.
Magic Octopus Urn

Questo è probabile sì.
Emigna,

1

Perl, 30 byte (29 +1 per -p ):

(1x++$_)=~/^(11+?)\1+$/&&redo

uso

Immettere il numero dopo aver premuto Invio (input 12345 nell'esempio seguente, uscite 12347):

$ perl -pe '(1x++$_)=~/^(11+?)\1+$/&&redo'
12345
12347

Come funziona

  • Definire una stringa di 1's che ha lunghezza++$_ , dove $_inizialmente è il valore di input
  • Il regex controlla se la stringa di 1s è di lunghezza non primaria (spiegato qui ).
  • Se la lunghezza della stringa non è primaria, il controllo viene rivalutato per il numero intero successivo (++$_ )
  • Se la lunghezza della stringa è primaria, il whileciclo implicito esce e -pstampa il valore di$_
  • Nota: non è necessario gestire la custodia "1"del bordo di lunghezza 1 perché non verrà mai utilizzata per valori inferiori a 1, secondo le specifiche.

1

Java 7, 373 343 334 303 268 byte

import java.math.*;class M{public static void main(String[]a){BigInteger n,i,o,r=new BigInteger(a[0]);for(r=r.add(o=r.ONE);;r=r.add(o)){for(n=r,i=o.add(o);i.compareTo(n)<0;n=n.mod(i).compareTo(o)<0?r.ZERO:n,i=i.add(o));if(n.compareTo(o)>0)break;}System.out.print(r);}}

-75 byte grazie @Poke

Ungolfed:

import java.math.*;
class M{
  public static void main(String[] a){
    BigInteger n,
               i,
               o,
               r = new BigInteger(a[0]);
    for(r = r.add(o = r.ONE); ; r = r.add(o)){
      for(n = r, i = o.add(o); i.compareTo(n) < 0; n = n.mod(i).compareTo(o)< 0
                                                        ? r.ZERO
                                                        : n,
                                                   i = i.add(o));
      if(n.compareTo(o) > 0){
        break;
      }
    }
    System.out.print(r);
  }
}

Provalo qui.

Alcuni esempi di input / output:

7 -> 11
1609 -> 1613
104723 -> 104729

@Poke Ho giocato a golf altri 31 byte aggiungendo staticper il campo e il metodo p, ma rimuovendo il metodo ce pil parametro.
Kevin Cruijssen,

0

QBIC , 34 byte

:{a=a+1[2,a/2|~a%b=0|b=a]]~a<b|_Xa

Basato su questo tester di primalità QBIC . Spiegazione:

:{a=a+1    Read 'a' from the command line, start an infinite loop 
           and at the start of each iteration increment 'a'
[2,a/2|    FOR b = 2, b <= a/2, b++
~a%b=0|    IF b cleanly divides a, we're no prime
b=a]]      so, break out of the FOR loop ( ]] = End if, NEXT )
~a<b|      If the FOR loop completed without breaking
_Xa        then quit, printing the currently tested (prime) number
           The second IF and the DO-loop are implicitly closed by QBIC.

0

JavaScript (ES7), 61 byte

a=>{for(;a++;){for(c=0,b=2;b<a;b++)a%b||c++;if(!c)return a;}}

uso

f=a=>{for(;a++;){for(c=0,b=2;b<a;b++)a%b||c++;if(!c)return a;}}
f(2)

Produzione

3

Bello, ma non penso che funzionerà, poiché JavaScript stesso (non il computer) perderà precisione dopo solo 2 ^ 53.
ETHproductions

Hai ragione, ma non credo che il limite possa essere evitato, anche se dividiamo il numero in porzioni di 32 bit in un array, perché alla fine il numero deve essere elaborato nel suo insieme. Se hai un'idea su come risolverlo, per favore fatemelo sapere.
Luca

1
Ci sono librerie JS per matematica di precisione arbitraria - ne ho persino costruita una ad un certo punto - quindi sono certo che sia possibile. Ci
proverò

Ho fatto un po 'di googling e sembra interessante. Ci proverò anche io.
Luca

0

MATL, 3 byte

_Yq 

La funzione Yqrestituisce il primo primo del valore assoluto dell'input se l'ingresso è negativo, quindi prendiamo implicitamente l'input, lo neghiamo ( _) e troviamo il primo primo usando Yq.

Provalo online!


0

Haskell, 42 46 43 byte

f n=[i|i<-[n..],all((>0).rem i)[2..i-1]]!!1

il solito codice per la forza bruta.

Ovviamente questo trova il numero primo più piccolo successivo dopo n. Non esiste un numero primo.

Funziona per n > 0 .

modifica: Presuppone nè primo. Grazie ai consigli di @Laikoni nei commenti .


È possibile salvare un byte sostituendolo head[...]con [...]!!0. Comunque penso che si possa presumere che nsia primo, quindi puoi usare [n..]invece di [n+1..]e quindi prendere il secondo elemento con [...]!!1.
Laikoni,

0

SimpleTemplate, 132 byte

L'algoritmo è terribile, dal momento che devo fare il mio codice per verificare se un numero è primo o no.
Si è rivelato orribile, ma funziona.

{@setY argv.0}{@setX 1}{@whileX}{@setX}{@set+T Y,-1}{@for_ from2 toT}{@ifY is multiple_}{@incX}{@/}{@/}{@ifX}{@incY}{@/}{@/}{@echoY}

Riceve il numero come primo argomento, producendo il risultato.


Ungolfed:

{@set number argv.0}
{@set remainder 1}
{@while remainder}
    {@set remainder 0}
    {@set+ tmp number, -1}
    {@for divisor from 2 to tmp}
        {@if number is multiple divisor}
            {@inc by 1 remainder}
        {@/}
    {@/}
    {@if remainder}
        {@inc by 1 number}
    {@/}
{@/}
{@echo number}

Qualche consiglio su come rimuoverlo per ultimo @if?


0

Lua, 876 byte

function I(a)a.s=a.s:gsub("(%d)(9*)$",function(n,k)return tostring(tonumber(n)+1)..("0"):rep(#k)end)end function D(a)a.s=a.s:gsub("(%d)(0*)$",function(n,k)return tostring(tonumber(n)-1)..("9"):rep(#k)end):gsub("^0+(%d)","%1")end function m(a,b)local A=K(a)local B=K(b)while V(0,B)do D(A)D(B)end return A end function M(a,b)local A=K(a)local B=K(b)while V(m(B,1),A)do A=m(A,B)end return A end function l(n)return#n.s end function p(a)local A=K(a)local i=K(2)while V(i,A)do if V(M(A,i),1)then return false end I(i)end return true end function V(b,a)A=K(a)B=K(b)if l(A)>l(B)then return true end if l(B)>l(A)then return false end for i=1,l(A)do c=A.s:sub(i,i)j=B.s:sub(i,i)if c>j then return true elseif c<j then return false end end return false end function K(n)if(type(n)=='table')then return{s=n.s}end return{s=tostring(n)}end P=K(io.read("*n"))repeat I(P)until p(P)print(P.s)

Lua, a differenza di alcune altre lingue, ha una dimensione intera massima. Una volta che un numero diventa maggiore di 2 32 , le cose smettono di funzionare correttamente e Lua inizia a provare a fare stime invece di valori esatti.

Come tale, ho dovuto implementare un nuovo metodo di memorizzazione dei numeri, in particolare, li ho archiviati come stringhe Base10, perché Lua non ha un limite di dimensione su Stringhe, oltre alla dimensione della memoria.

Sento che questa risposta è molto di più per lo Spirito della domanda, in quanto deve implementare numeri interi di precisione arbitraria, nonché un test di base.

spiegato

-- String Math
_num = {}

_num.__index = _num

-- Increase a by one.
-- This works by grabbing ([0-9])999...$ from the string.
-- Then, increases the first digit in that match, and changes all the nines to zero.
-- "13", only the "3" is matched, and it increases to 1.
-- "19", firstly the 1 is turned to a 2, and then the 9 is changed to a 0.
-- "9" however, the 9 is the last digit matched, so it changes to "10"
function _num.inc(a)
    a.str = a.str:gsub("(%d)(9*)$",function(num,nines)
            return tostring(tonumber(num)+1)..("0"):rep(#nines)
        end)
end


-- Decrease a by one
-- Much like inc, however, uses ([0-9])0...$ instead.
-- Decrements ([0-9]) by one and sets 0... to 9...
-- "13" only the "3" is matched, and it decreases by one.
-- "10", the "1" is matched by the ([0-9]), and the 0 is matched by the 0..., which gives 09, which is clipped to 9.
function _num.dec(a)
    a.str = a.str:gsub("(%d)(0*)$",function(num,zeros)
        return tostring(tonumber(num)-1)..("9"):rep(#zeros)
    end)         :gsub("^0+(%d)","%1")
end

-- Adds a and b
-- Makes A and B, so that the original values aren't modified.
-- B is then decremented until it hits 0, and A is incremented.
-- A is then returned.
function _num.__add(a,b)
    local A = str_num(a)
    local B = str_num(b)
    while B > 0 do
        A:inc()
        B:dec()
    end
    return A
end

-- Subs b from a
-- Works just like Addition, yet Dec's A instead of Incs.
function _num.__sub(a,b)
    local A = str_num(a)
    local B = str_num(b)
    while B > 0 do
        A:dec()
        B:dec()
    end
    return A
end

-- A % B
-- Makes A and B from a and b
-- Constantly subtracts B from A until A is less than B
function _num.__mod(a,b)
    local A = str_num(a)
    local B = str_num(b)
    while A >= B do
        A = A - B
    end
    return A
end

-- #a
-- Useful for golfiness
function _num.__len(n)
    return #n.str
end

-- Primacy Testing
-- Generates A from a and i from 2.
-- Whilst i is less than A, i is incremented by one, and if A % i == 0, then it's not a prime, and we return false.
-- Once that finishes, we return true.
function _num.isprime(a)
    local A = str_num(a)
    local i = str_num(2)
    while i < A do
        if A%i < 1 then
            return false
        end
        i:inc()
    end
    return true
end

-- b < a
-- A and B are generated from a and b
-- Fristly, if the length of A and B aren't equal, then that result is output.
-- Otherwise, each character is searched from left to right, the moment they are unequal, the difference is output.
-- If all the characters match, then it's equal. Return false.
function _num.__lt(b,a)
    A=str_num(a)
    B=str_num(b)
    if #A > #B then
        return true
    end
    if #B > #A then
        return false
    end
    for i=1, #A.str do
        As = A.str:sub(i,i)
        Bs = B.str:sub(i,i)
        if As > Bs then
            return true
        elseif As < Bs then
            return false
        end
    end
    return false
end


-- b <= a
-- Same as b < a, but returns true on equality.
function _num.__le(b,a)
    A=str_num(a)
    B=str_num(b)
    if #A > #B then
        return true
    end
    if #B > #A then
        return false
    end
    for i=1, #A.str do
        As = A.str:sub(i,i)
        Bs = B.str:sub(i,i)
        if As > Bs then
            return true
        elseif As < Bs then
            return false
        end
    end
    return true
end

-- Just straight up returns it's string component. Endlessly faster than the int equivalent, mostly because it never is anything _but_ the string form.
function _num.__tostring(a)
    return a.str
end

-- Just set up the metatable...
function str_num(n)
    if(type(n)=='table')then
        return setmetatable({str = n.str}, _num)
    end
    return setmetatable({str = tostring(n)}, _num)
end

-- Generate a new str_num from STDIN
Prime = str_num(io.read("*n"))

-- This is handy, because it will call Prime:inc() atleast once, and stop at the next prime number it finds.
-- Basically, if it weren't for all that overhead of making the math possible, that's all this would be.
repeat
    Prime:inc()
until Prime:isprime()
print(Prime)

Sebbene quanto sopra utilizza Metatables, invece di funzioni regolari come la risposta effettiva, che ha funzionato più piccolo.


0

Rubino, 28 + 6 = 34 byte

Usa la -rprimebandiera.

f=->i{i+=1;i.prime??i :f[i]}

Versione non ricorsiva per 31 + 6 = 37 byte:

->i{i+=1;i+=1 while i.prime?;i}

0

Python + primefac , 34 32 byte

Non abbastanza breve come l'utilizzo sympy(un'altra risposta lo utilizza già), ma è comunque piuttosto breve ed è molto più veloce.

import primefac as p
p.nextprime

Provalo online

Inserimento di 2**2000completamenti in un paio di secondi.


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.