Un generatore principale naturale


42

Esistono un numero piuttosto elevato di funzioni di generazione primaria. Praticamente tutti sono costruiti e si basano sul setaccio di Eratostene, sulla funzione di Möbius o sul teorema di Wilson e sono generalmente impossibili da calcolare in pratica. Ma ci sono anche generatori, che hanno una struttura molto semplice e sono stati trovati per caso.

Nel 2003 Stephen Wolfram ha esplorato una classe di equazioni di ricorrenza nidificate in un esperimento informatico dal vivo presso la NKS Summer School. Un gruppo di persone intorno a Matthew Frank ha seguito ulteriori esperimenti e ha scoperto un'interessante proprietà della semplice ricorrenza

a(n) = a(n-1) + gcd(n,a(n-1))

con il valore iniziale di a(1) = 7. La differenza a(n) - a(n-1) = gcd(n,a(n-1))sembrava sempre essere 1 o un numero primo. Le prime differenze sono ( OEIS A132199 ):

1, 1, 1, 5, 3, 1, 1, 1, 1, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 3, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 3, 1, 5, 3, ...

Se omettiamo solo gli 1 otteniamo la seguente sequenza ( OEIS A137613 ):

5, 3, 11, 3, 23, 3, 47, 3, 5, 3, 101, 3, 7, 11, 3, 13, 233, 3, 467, 3, 5, 3, 
941, 3, 7, 1889, 3, 3779, 3, 7559, 3, 13, 15131, 3, 53, 3, 7, 30323, 3, ...

Eric S. Rowland ha dimostrato il primato di ogni elemento in questa lista qualche anno dopo. Come puoi vedere, i numeri primi sono mescolati e alcuni di essi appaiono più volte. È stato anche dimostrato che la sequenza include infiniti numeri primi distinti. Inoltre è ipotizzato che compaiano tutti i numeri primi dispari.

Poiché questo generatore principale non è stato costruito ma è stato semplicemente trovato per caso, il generatore principale è chiamato "naturale". Ma nota che in pratica questo generatore è anche abbastanza impossibile da calcolare. A quanto pare, un primo p appare solo dopo (p–3)/21s consecutivi. Tuttavia implementare questo generatore principale sarà il tuo compito.

Sfida:

Scrivi una funzione o un programma che stampa i primi nelementi della sequenza A137613(la sequenza senza 1). È possibile leggere il numero di input n >= 0tramite STDIN, argomento della riga di comando, prompt o argomento della funzione. Stampa i primi nelementi in qualsiasi formato leggibile su STDOUT o restituisce un array o un elenco con questi valori.

Questo è code-golf. Pertanto vince il codice più breve.

Classifica:

Ecco uno snippet di stack per generare sia una classifica regolare che una panoramica dei vincitori per lingua. Per assicurarti che la tua risposta venga visualizzata, ti preghiamo di iniziare la risposta con un titolo, usando il seguente modello Markdown:

# Language Name, N bytes

dove N è la dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

# Ruby, <s>104</s> <s>101</s> 96 bytes


1
Mentre il generatore principale non è costruito, stai effettivamente implementando una divisione di prova usando la ricorsione.
orlp

Se a (1) = 7, perché la sequenza non inizia con 7?
feersum

3
@feersum perché la sequenza di cui ci occupiamo èa(n)-a(n-1)
Maltysen il

Può nessere zero?
Sp3000,

1
@jrenk Non sono sicuro. Magari contalo come 2 byte (dato che stai rimuovendo 2 caratteri //) e spiegalo nel tuo invio. Se qualcuno non è d'accordo con te, puoi sempre modificare il tuo post.
Jakube,

Risposte:


19

Pyth, 14 13 byte

meaYhP+sY-5dQ

Usa a(n) = Lpf(6 - n + sum(a(i) for i in range(1, n))dove Lpfsignifica il fattore primo minimo.

Provalo qui online.


7

Python 3.5.0b1 +, 95 93 byte

Collegamento a Python 3.5.0b1 + release

import math
def f(k,n=2,a=7,L=[]):x=math.gcd(n,a);return k and f(k-1%x,n+1,a+x,L+1%x*[x])or L

Un'implementazione diretta della ricorrenza, con:

  • Il nostro buon amico 1%xe
  • math.gcd, al contrario di fractions.gcd.

Cosa fa 1%x? Domanda a margine: dove trovo la documentazione della cronologia delle revisioni di Python che include beta? Modifica: Nevermind, l'ho trovato in fondo alla cronologia delle revisioni .
mbomb007,

@ mbomb007 Da x >= 1, 1%xrestituisce 0 if x == 1, 1 altrimenti (utilizzato per decidere se aggiungere xall'elenco)
Sp3000

5

Julia, 110 byte

n->(a(n)=(n1&&(n==1?7:a(n-1)+gcd(n,a(n-1))));i=2;j=0;while j<n x=a(i)-a(i-1);x>1&&(j+=1;println(x));i+=1end)

Ungolfed:

function a(n::Int)
    n  1 && (n == 1 ? 7 : a(n-1) + gcd(n, a(n-1)))
end

function f(n::Int)
    i = 2;
    j = 0;
    while j < n
        x = a(i) - a(i-1)
        if x > 1
            j += 1
            println(x)
        end
        i += 1
    end
end

Wow, un 8k perfetto, carino: D
Decadimento beta

1
Usa n<2invece di n==1. Inoltre, se si guarda in avanti invece che all'indietro, è possibile utilizzare i=1e x=a(i)-a(i+=1), quindi, println(-x)e -x>1correggere la negatività, evitando così la necessità di un incremento separato di i. Ed è tre byte, mentre >=è due ... ma poi, è possibile utilizzare n<1||()anziché n>=1&&()... e tuttavia, non è nemmeno necessario in primo luogo (eliminare il condizionale, n non sarà mai inferiore a 1). Inoltre, non è necessario utilizzare le parentesi più esterne quando si definisce a (n). Con queste modifiche, dovresti almeno scendere a 97 byte.
Glen O

5

PHP, 101 96 99 98 77 72 byte

<?for(;2>$t=gmp_strval(gmp_gcd(~++$i,7+$e+=$t))or$argv[1]-=print"$t ";);


Uso:
chiama lo script con un argomento: php -d error_reporting=0 script.php 30
se vuoi testarlo devi decommentare ;extension=php_gmp.dllnel tuo php.ini
-> extension=php_gmp.dll
Devo aggiungere l'estensione al mio conteggio byte? qualche idea?


Registro:
salvato 3 byte grazie a Ismael Miguel.
26 byte salvati grazie a primo.


1
Puoi abbreviare il tag di apertura <?e rimuovere la definizione di $j.
Ismael Miguel,

1
Sì, conta. Ma puoi rimuovere quella nuova riga. Il che farà risparmiare 1-2 byte, a seconda di come hai contato la dimensione del tuo codice.
Ismael Miguel,

1
Piccoli miglioramenti: utilizzare <in $j<=$argv[1](stampa uno di troppo) (-1). Lascia $enon inizializzato, usa $e+7invece (-3). Usa for(;;)invece di while(), usando le espressioni pre e post (-2). Sostituire echo$t.' ';$j++con $j+=print"$t ", rilasciare le parentesi (-3). Sostituire if($t>1)con 2>$t||(-2). Combina il compito $tcon il condizionale, passa ||a or, rilascia le parentesi (-5). Spostare $argv[1]l' $jincremento, spostare l'intera espressione al forcondizionale (-2). Passare >=$j+=printa -=print(-3). Passo dopo passo: codepad.org/s6LNSPSM
primo

1
@primo grazie per la bella spiegazione! Non sapevo che avrei potuto fare tutto questo.
Jrenk,

1
Qualche altro: Combina $e+7con $e+=$t(-2). Lascia $inon inizializzato, usa ~++$iinvece (-3). codepad.org/fDIImajp
primo

4

Haskell, 51 byte

d=zipWith gcd[2..]$scanl(+)7d
f=($filter(>1)d).take

Si noti che fè una funzione che restituirà i primi n elementi.

Anziché a(n)calcolare le differenze d(n)e quindi elaborarle, calcoliamo le differenze e le sommiamo per ottenere a(n). (Coloro che non hanno familiarità con Haskell possono protestare sul fatto che a(n)prima abbiamo bisogno per ottenere d(n), ma ovviamente una valutazione pigra ci risolve questo problema!)

Ungolfed:

a = scanl (+) 7 d        -- yielding a(n) = 7 + d(1) + d(2) + ... + d(n-1)
d = zipWith gcd [2..] a  -- yielding d(n) = gcd(n+1, a(n))

f n = take n $ filter (> 1) d -- get rid of 1s and take the first n

4

Pyth, 30 byte

Molto male il golf, può essere considerevolmente ridotto. Definisce la funzione ricorsiva nella parte anteriore, filtra .first-n e quindi mappa la differenza.

L?tb+KytbibK7m-yhdyd.ft-yhZyZQ

Provalo qui online .


Ciò fornisce un output errato pern = 0
Sp3000,

2
@ Sp3000 che è un bug in Pyth. Metterò una richiesta pull.
Maltysen,

Bug trovato e risolto - la patch verrà implementata quando github smetterà di essere DDoS'd.
isaacg,

1
Eccolo qui: meta.codegolf.stackexchange.com/questions/5318/… . Personalmente considererei le correzioni di bug nei linguaggi di programmazione come una risposta
Thomas Weller,

2
@ThomasWeller In un certo senso ha raggiunto l'intera lingua ...
isaacg,

4

Julia, 69 67 byte

n->(i=1;a=7;while n>0 x=gcd(i+=1,a);a+=x;x>1&&(n-=1;println(x))end)

Questa è una semplice soluzione iterativa al problema. xè la differenza (che è la gcd) e quindi aggiorno aaggiungendo x.


Penso che stampa A231900 .
alephalpha,

@alephalpha - Penso di vedere l'errore. Facilmente risolto. Anche rasato due byte nel processo.
Glen O

3

JavaScript (ES6), 91

GCD ricorsivo, funzione principale iterativa. Non così in fretta.

Nota usuale: test di esecuzione dello snippet su qualsiasi browser compatibile con EcmaScript 6 (in particolare Chrome non MSIE. Ho testato su Firefox, Safari 9 potrebbe andare)

F=m=>{
  for(G=(a,b)=>b?G(b,a%b):a,o=[],p=7,n=1;m;d>1&&(o.push(d),--m))
    p+=d=G(++n,p);
  return o
}

O.innerHTML=F(+I.value)
<input id=I value=10><button onclick='O.innerHTML=F(+I.value)'>-></button>
<pre id=O></pre>


3

Haskell, 74 71 66 byte

f=($filter(>1)$tail>>=zipWith(-)$scanl(\x->(x+).gcd x)7[2..]).take

Ho usato il trucco qui: https://codegolf.stackexchange.com/a/39730/43318 e reso privo di punti.

(Precedente: 71 byte)

a=scanl(\x->(x+).gcd x)7[2..]
f m=take m$filter(>1)$zipWith(-)(tail a)a

Prima fai la sequenza di a, quindi prendi le differenze.

(Precedente: 74 byte)

f m=take m$filter(>1)$map snd$scanl(\(x,d)->(\y->(x+y,y)).gcd x)(7,1)[2..]

Funzioni di elenco standard, oltre a un uso intelligente della funzione lambda. Si noti che questo è 1 byte più corto del più ovvio

g m=take m$filter(>1)$map snd$scanl(\(x,d)n->(x+gcd x n,gcd x n))(7,1)[2..]

Se non contiamo le importazioni, posso arrivare a 66.

import Data.List
h m=take m$filter(>1)$snd$mapAccumL(\x->(\y->(x+y,y)).gcd x)7[2..]

3

PARI / GP, 60 byte

a(n)=a=7;i=1;while(n,if(1<d=gcd(i+=1,a),n-=1;print(d));a+=d)

Preso più o meno direttamente dalla definizione a (n) - a (n-1) = gcd (n, a (n-1))

Uscita per a(20):

5
3
11
3
23
3
47
3
5
3
101
3
7
11
3
13
233
3
467
3

2

C ++, 193 182 180 172 byte

Grazie @Jakube - 8 byte salvati in output.

int g(int a,int b){return a==b?a:a>b?g(b,a-b):g(a,b-a);}void f(int *r,int n){int m=1,i=0,a=7,b;while(i<n){b=g(a,++m);if(b>1){r[i]=b;++i;}a+=b;}}int main(){int r[6];f(r,6);}

Probabilmente puoi salvare alcuni byte definendo una funzione f, che restituisce un array con i risultati. In questo modo è possibile rimuovere l'inclusione, lo scanf e la stampa.
Jakube,

2

Mathematica, 59 byte

For[i=j=1;a=7,i<=#,,d=GCD[++j,a];If[d>1,Print@d;i++];a+=d]&
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.