La sequenza è troppo meta


25

Iniziamo con una sequenza vuota 1 indicizzata:

_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,...

Nel n ° passo, riempiamo in ogni una (n) spazi vuoti con i numeri interi maggiori di 1 A partire da vuota la prima rimanente, dove a (n) è il n ° ingresso nella sequenza.

Dopo il primo passo:

2,_,3,_,4,_,5,_,6,_,7,_,8,_,9,_,10,_,11,_,12,_,13,_,...

Si noti che a (1) deve essere 2 perché il primo numero intero maggiore di 1 è 2.

Nel secondo passaggio, riempiamo ogni a (2) spazi vuoti. Sarà evidente che a (2) deve essere 2.

2,2,3,_,4,3,5,_,6,4,7,_,8,5,9,_,10,6,11,_,12,7,13,_,...

Nel terzo passaggio, riempiamo ogni a (3) spazi vuoti. Dalla sequenza, a (3) = 3.

2,2,3,2,4,3,5,_,6,4,7,_,8,5,9,3,10,6,11,_,12,7,13,_,...

Nel quarto passaggio, riempiamo ogni a (4) spazi vuoti. Dalla sequenza, a (4) = 2.

2,2,3,2,4,3,5,2,6,4,7,_,8,5,9,3,10,6,11,3,12,7,13,_,...

Infine:

2,2,3,2,4,3,5,2,6,4,7,2,8,5,9,3,10,6,11,3,12,7,13,2,...

Compito

Dato n, restituisce l' ennesimo elemento della sequenza.

I primi 10.000.000 di termini della sequenza sono disponibili qui .

Questo è . Vince la risposta più breve in byte. Si applicano scappatoie standard .


@LuisMendo Grazie, l'ho aggiunto.
Leaky Nun,

Solo curioso, che male ha fatto Mr. One essere escluso dalla sequenza?
Dead Possum,

@DeadPossum bene, se riempi tutti gli spazi vuoti, hai finito in un solo passaggio.
Leaky Nun,

2
@DeadPossum Se a (n) è 1, l'ennesimo passaggio riempirà tutti gli spazi vuoti rimanenti, terminando la generazione.
Leaky Nun,

1
@QBrute Ho fornito un elenco dei primi 10.000.000 collegati nella domanda; complottali e basta.
Leaky Nun,

Risposte:


20

Haskell , 80 67 byte

g~(a:b)|let k!l=k:take(a-1)l++(k+1)!drop(a-1)l=2!g b
m=g m
(!!)$0:m

Provalo online!

Haskell è il linguaggio perfetto per definire un elenco infinito in termini di se stesso.


1
Dato che il collegamento TIO funziona come previsto, immagino che la mia domanda dovrebbe essere: Potresti aggiungere una spiegazione di come funziona?
Julian Wolf,

2
@JulianWolf Sembra che tu non abbia familiarità con le letguardie dei modelli. pattern1 | let pattern2 = expr2 = expr1significa la stessa cosa di pattern1 = let pattern2 = expr2 in expr1(per lo stesso motivo che [expr1 | let pattern2 = expr2]significa la stessa cosa di [let pattern2 = expr2 in expr1]).
Anders Kaseorg,

1
Devo ricordare le letprotezioni dei modelli (specialmente che possono fare funzioni)! Inoltre, m=2:2:2`drop`g mè un byte più breve.
Ørjan Johansen,

1
(!!)$0:mè due byte più breve.
Ørjan Johansen,

1
In realtà, puoi lasciar perdere 2:2:tutto con un po 'più di pigrizia: g ~(a:b)|...e m=g m.
Ørjan Johansen,

10

C, 123 byte

f(n){int*p=calloc(n,4),i=0,j,k;for(*p=p[1]=2;i<n;++i)for(j=0,k=i/2?0:2-i;j<n;++j)p[j]||k++%p[i]||(p[j]=k/p[i]+2);n=p[n-1];}

Provalo online!

Procedura dettagliata

f(n){int*p=calloc(n,4),

Allocare una matrice di n numeri interi per memorizzare i primi n elementi della sequenza. Questo hardcodes sizeof(int)come 4, che è un presupposto sicuro nella maggior parte dei casi e sicuramente uno che sono disposto a fare nel contesto del code golf. :)

i=0,j,k;

Questi sono tutti contatori: iper l'indice del passo in cui ci troviamo, jper scorrere la sequenza alla ricerca di spazi vuoti e kper contare quanti spazi vuoti sono stati visti.

for(*p=p[1]=2;i<n;++i)

Prima di iniziare il nostro ciclo principale, ci avviciniamo di soppiatto all'inizializzazione dei primi due elementi della sequenza 2. ( p[0]= *(p + 0)= *p.) Questo butta via il conteggio per k, però, ma ...

for(j=0,k=i/2?0:2-i;j<n;++j)

... facciamo anche un'inizializzazione subdola k, che verifica se iè minore di 2e corregge il valore iniziale di kse. Anche il ciclo interno inizia qui, che scorre su tutta la sequenza fino ad ora durante ogni passaggio.

p[j]||k++%p[i]||(p[j]=k/p[i]+2);

Questa riga potrebbe davvero usare qualche spiegazione. Possiamo espandere questo a:

if (!(p[j] || ((k++) % p[i]))) {
    p[j] = k / p[i] + 2;
}

da corto circuito, e quindi dalle leggi di De Morgan e dal fatto che 0è falso in C:

if (p[j] == 0 && ((k++) % p[i]) == 0) {
    p[j] = k / p[i] + 2;
}

Questo afferma essenzialmente: "se questo spazio è vuoto, incrementare k. E se in kprecedenza era un multiplo della dimensione del passo, eseguire la seguente istruzione". Quindi, eseguiamo l'istruzione su ogni elemento di dimensione del passo , che è esattamente come viene descritta la sequenza. L'affermazione stessa è semplice; tutto ciò che fa è generare 2, 3, 4, ....

n=p[n-1];}

Utilizzando il difficile-ritorno-senza-ritorno che funziona con gcc, noi "ritorno" l'ultimo elemento dei primi n termini nella sequenza, che risulta essere il n esimo termine.


3

Pyth, 29 byte

M?tH?eJ.DtHg1GghG-tHhJ+2hJ2g1

Provalo online

Come funziona

Invece di scherzare con gli elenchi, utilizza una semplice formula ricorsiva.

M                                def g(G, H):
 ?tH                                 if H - 1:
      J.DtHg1G                           J = divmod(H - 1, g(1, G))
    ?e                                   if J[-1]:
              ghG-tHhJ                       return g(G + 1, H - 1 - J[0])
                                         else:
                      +2hJ                   return 2 + J[0]
                                     else:
                          2              return 2
                           g1Q   print(g(1, eval(input())))

3

Haskell , 67 byte

0%j=2
i%j|d<-div i$f j=last$d+2:[(i-d-1)%(j+1)|d*f j<i]
f=(%1).pred

Provalo online!

Una soluzione aritmetica ricorsiva che si è rivelata sostanzialmente lo stesso metodo della risposta Pyth di Anders Kaseorg .

Questo codice è coperto di verruche - parti brutte che sembrano poter essere portate via dal golf, ma non ho visto come.

La funzione i%jvuole davvero usare una guardia per verificare se mod i(f j)>0e valutare una delle due espressioni corrispondenti. Ma entrambe le espressioni usano div i(f j). Vincolare che in una guardia non lo farà applicare ad entrambi i lati. Per quanto ne so, una guardia non può essere fatta per "distribuire" su altre guardie. lete wheresono troppo lunghi. Quindi, il codice usa lastper scegliere una delle due espressioni mentre la guardia lega la variabile. Ugh.

Idealmente avremmo usiamo divModperché sia la dive modsono utilizzati, ma (d,m)<-divMod ...è una lunga espressione. Invece controlliamo in modo hackerato la mod è diversa da zero vedendo se il divvalore per il divisore è inferiore al valore originale.

Il 0%j=2caso non sarebbe necessario se Haskell fosse in cortocircuito div 0, cosa che non accade. I .predconvertiti l'ingresso 1-indicizzato a zero indicizzati, altrimenti ci sarebbe -1correzioni ovunque.


Se si gira %1-indicizzato, allora è necessaria una correzione di cinque byte, che si lega solo. Tuttavia , è possibile inline fin %senza alcun costo e quindi fdiventa anonimo in modo da risparmiare due byte complessivi.
Ørjan Johansen,

@ ØrjanJohansen Cosa intendi qui per inline? Non vedo come modificare i riferimenti fsenza perdere byte.
xnor

divModsembra essere più economico di un byte, perché consente la ramificazione con !!(0^m). Finora ho:1%j=2;i%j|(d,m)<-divMod(i-1)$j%1=[(i-d-1)%(j+1),d+2]!!(0^m);(%1)
Ørjan Johansen il

Come vedi, l'inline presuppone l'1-reindicizzazione, che rimuove il .pred.
Ørjan Johansen,

2

JavaScript (ES6), 98 93 91 byte

Una funzione ricorsiva che si interrompe non appena il risultato è disponibile.

f=(n,p,a=[...Array(n)])=>a[n-1]||f(n,-~p,a.map(c=>c?c:i?i++%(a[p]||2)?c:++v:(i=1,v=2),i=0))

Versione alternativa, 90 byte

Suggerito da Shaggy per -1 byte

Questo deve essere chiamato con f(n)(). Sebbene il post corrispondente in meta attualmente dia un punteggio positivo, questa sintassi è apparentemente contestata.

n=>g=(p,a=[...Array(n)])=>a[n-1]||g(-~p,a.map(c=>c?c:i?i++%(a[p]||2)?c:++v:(i=1,v=2),i=0))

dimostrazione


n=>g=(p,a=[...Array(n)])=>a[n-1]||g(-~p,a.map(c=>c?c:i?i++%k?c:++v:(i=1,v=2),i=0,k=a[p]||2))dovrebbe funzionare per 92 byte. Chiamalo con f(n)().
Shaggy,

@Shaggy Grazie! Aggiunto come versione alternativa.
Arnauld,

1

Java 8, 124 byte

(i)->{int j=1,a[]=new int[i+1],k,s,n;for(;a[i]<2;){for(k=0,n=2;a[++k]>0;);for(s=a[j++]|2*k;k<=i;k+=s)a[k]=n++;}return a[i];}

Espressione lambda.

Crea un array intero e lo popola continuamente fino a quando non viene popolato l'ennesimo valore.

Pre-dichiarare le variabili in alto per ridurre il maggior numero possibile di dichiarazioni ciascuna delle quali intcosta 4 byte di spazio anziché aggiungere ,n2.

Sul j'esima iterazione del calcolo, il numero di 'uno sbozzati' deve saltare è uguale a[j](o 2, se vuoto). Risolve che se il primo spazio vuoto che dobbiamo riempire è in posizione k, k * a[j]ci dà il 'passo' ( s).

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.