Calcola la sequenza di Kolakoski


54

Questo è un ripubblicare di una vecchia sfida , al fine di adeguare i requisiti I / O ai nostri standard recenti. Questo viene fatto nel tentativo di consentire a più lingue di partecipare a una sfida su questa sequenza popolare. Vedi questo meta post per una discussione sul repost.

La sequenza di Kolakoski è una divertente sequenza autoreferenziale, che ha l'onore di essere la sequenza OEIS A000002 (ed è molto più facile da capire e implementare di A000001). La sequenza inizia con 1 , è composto solo di 1 s e 2 s e l'elemento di sequenza a (n) descrive la lunghezza del n ° corsa di 1 s o 2 s nella sequenza. Questo definisce in modo univoco la sequenza da essere (con una visualizzazione delle piste sottostanti):

1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1,2,2,1,2,1,1,2,1,2,2,1,1,2,1,1,2,...
= === === = = === = === === = === === = = === = = === === = === =
1, 2,  2, 1,1, 2, 1, 2,  2, 1, 2,  2, 1,1, 2, 1,1, 2,  2, 1, 2, 1,...

Il tuo compito è, ovviamente, implementare questa sequenza. Puoi scegliere uno dei tre formati per farlo:

  1. Prendere un input n e uscita n esimo termine della sequenza, dove n inizia sia da 0 o 1 .
  2. Prendere un input n ed emettere i termini fino al il n esimo termine della sequenza, dove n inizia sia da 0 o 1 (cioè o stampare la prima n o il primo n + 1 termini).
  3. Valori di output dalla sequenza indefinitamente.

Nel secondo e terzo caso, puoi scegliere qualsiasi formato di elenco ragionevole e inequivocabile. Va bene se non c'è un separatore tra gli elementi, dal momento che sono sempre una singola cifra per definizione.

Nel terzo caso, se l'invio è una funzione, è anche possibile restituire un elenco infinito o un generatore in lingue che li supportano.

È possibile scrivere un programma o una funzione e utilizzare uno qualsiasi dei nostri metodi standard per ricevere input e fornire output. Si noti che queste scappatoie sono vietate per impostazione predefinita.

Questo è , quindi la risposta valida più breve - misurata in byte - vince.


Correlato , ma non un duplicato.
Magic Octopus Urn

Generalizzazione del problema , ma probabilmente sono possibili ottimizzazioni poiché la parte iniziale della sequenza è fissa.
Giuseppe

Risposte:


17

Gelatina , 7 byte

2Rṁxṁµ¡

Questo è un programma completo che stampa i primi n termini.

Provalo online!

Come funziona

2Rṁxṁµ¡  Main link. Argument: n (integer)

     µ   Combine the preceding links into a monadic chain.
      ¡  Set t = n.  Call the chain n times, updating t with the return value after
         each call. Yield the last value of t.
2R           Set the return value to 2 and take its range. Yields [1, 2].
  ṁ          Mold; cyclically repeat 1 and 2 to match t's length.
             In the first run, ṁ promotes t = n to [1, ..., n].
   x         Repeat the k-th element of the result t[k] times.
             In the first run, x repeats each element t = n times.
    ṁ        Mold; truncate the result to match the length of t.
             In the first run, ṁ promotes t = n to [1, ..., n].                 

Esempio di esecuzione

Sia n = 5 .

La prima invocazione della catena ripete ciclicamente 1, 2 per raggiungere la lunghezza 5 , quindi ogni elemento 5 volte e infine tronca il risultato alla lunghezza 5 .

  1         2         1         2         1
x 5         5         5         5         5
---------------------------------------------------
  1 1 1 1 1 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2 1 1 1 1 1

  1 1 1 1 1

Questo produce un elenco di lunghezza 5 . Il primo elemento è il primo elemento della sequenza di Kolakoski.

La seconda invocazione della catena ripete 1, 2 ciclicamente lunghezza portata 5 , quindi ripete il k esimo elemento j volte, dove j è il k esimo elemento della lista precedente, e infine tronca il risultato a lunghezza 5 .

   1 2 1 2 1
x  1 1 1 1 1
------------
   1 2 1 2 1

   1 2 1 2 1

Questo produce un altro elenco di lunghezza 5 . I primi due elementi sono i primi due elementi della sequenza di Kolakoski.

Il processo continua per altre tre iterazioni.

   1 2   1 2   1
x  1 2   1 2   1
----------------
   1 2 2 1 2 2 1

   1 2 2 1 2
   1 2   1   2 1
x  1 2   2   1 2
------------------
   1 2 2 1 1 2 1 1

   1 2 2 1 1
   1 2   1   2 1
x  1 2   2   1 1
----------------
   1 2 2 1 1 2 1

   1 2 2 1 1

Questi sono i primi cinque elementi della sequenza di Kolakoski.


12

Python 2 , 51 byte

l=[2]
print 1,2,
for x in l:print x,;l+=x*[l[-1]^3]

Stampa indefinitamente. Crea l'elenco lmentre viene ripetuto. Per ogni voce xdi l, accoda xcopie di 1o 2, qualunque sia opposta all'ultimo elemento corrente.

La principale difficoltà sta affrontando il frammento autoreferenziale iniziale [1,2,2]. Questo codice stampa solo l'iniziale 1,2e procede da lì. La stampa aggiuntiva costa 12 byte. Senza quello:

39 byte , mancano le prime due voci:

l=[2]
for x in l:print x;l+=x*[l[-1]^3]

Un altro approccio è quello di inizializzare appositamente le prime due voci. Inizializziamo lin [0,0,2]modo tale che le prime due voci non causino l'aggiunta, ma le facciano print x or nstampare come n.

51 byte

l=[0,0,2]
n=1
for x in l:print x or n;l+=x*[n];n^=3

Un'altra correzione consiste nell'inizializzare l=[1], tenere traccia dell'alternanza manualmente ne correggere la stampa:

51 byte

n,=l=[1]
for x in l:print(l==[1,1])+x;l+=x*[n];n^=3

Senza il (l==[1,1])+, tutto funziona tranne che le sequenze stampate iniziano 1,1,2invece di 1,2,2. Deve esserci un modo migliore per riconoscere che siamo a questo secondo passo.

E un'altra strana correzione, anche in qualche modo lo stesso conteggio di byte:

51 byte

l=[1];q=2
for x in l:print x;l+=x*[l[-1]^3]*q;q=q<2

12

Wumpus , 13 11 byte

=[=)O?=!00.

Provalo online!

Stampa la sequenza indefinitamente senza separatori.

Sono sinceramente sorpreso da quanto sia breve.

Spiegazione

L'idea di base è mantenere la sequenza in pila e utilizzare ripetutamente l'elemento più in basso per generare un'altra corsa e quindi stamparla. Stiamo effettivamente abusando dello stack come una coda qui. Possiamo anche salvare un paio di byte lavorando 0e 1(incrementando solo per l'output) anziché 1e 2, poiché in questo modo non abbiamo bisogno di inizializzare esplicitamente lo stack con a 1e possiamo usare la negazione logica per alternare tra i due valori.

     The entire program is run in a loop.
     At the beginning of loop iteration i, a(i)-1 will be at the bottom of the
     stack and the first element of the ith run of values will be on top.
     The caveat is that on the first iteration, the stack is empty, but
     popping from an empty stack produces an implicit zero.
=    Duplicate the top of the stack. Since this is defined as "pop x, push
     x, push x" this will result in 2 zeros when the stack is empty.
     After this we've got two copies of the ith run's value on top of the stack.
[    Pull up a(i)-1 from the bottom of the stack.
=)O  Duplicate, increment to a(i) and print it.
?=   If a(i)-1 is 1 (as opposed to 0), make another copy of the top of the
     stack. We've now got a(i)+1 copies, so one more than the run should be 
     long, but that's great because we can use the additional copy to get 
     the start of the next run.
!    Logical negation which swaps 0 and 1.
00.  Jump back to the beginning of the program.

10

Brachylog , 30 26 25 23 17 16 14 byte

~a₀{1|2}ᵐḅlᵐ?l

Emette i primi n valori. Utilizza la "variabile di output" .per l'input e l'output alla "variabile di input" ?. Provalo online!

Spiegazione

Sono abbastanza contento di quanto sia risultato dichiarativo: il programma è sostanzialmente una descrizione di alto livello dell'elenco di output e della sua relazione con l'input.

~a₀{1|2}ᵐḅlᵐ?l  Input is a number N.
                Output is a term that I'll call T.
~a₀             T is a prefix of a list L.
   {   }ᵐ       Each element of L
    1|2         is either 1 or 2.
         ḅ      If you cut L into blocks of equal elements
          lᵐ    and take the length of each block,
            ?   the result is T.
             l  The length of T is N.

Poiché {1|2}ᵐprova gli elenchi in ordine lessicografico, l'output inizierà con 1.


9

Buccia , 10 byte

Ṡωo↑⁰`Ṙ¢ḣ2

Restituisce i primi n valori. Provalo online!

Spiegazione

Ṡωo↑⁰`Ṙ¢ḣ2  Input is an integer N.
        ḣ2  The range [1,2]
       ¢    Cycle: C = [1,2,1,2,1,2...
 ω          Iterate until fixed point is found:
Ṡ    `Ṙ      Replicate the list C element-wise according to the current list,
  o↑⁰        then take first N elements.

Per l'ingresso 20, il processo procede in questo modo:

[1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2...
[1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2]
[1,2,2,1,1,2,1,1,2,2,1,2,2,1,1,2,1,1,2,2]
[1,2,2,1,1,2,1,2,2,1,2,1,1,2,2,1,2,2,1,1]
[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1,2,1,2]
[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1,2,2,1]
[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1,2,2,1]

1
Ecco una variante che stampa la sequenza indefinitamente, lo stesso numero di byte ma forse vedrai alcune opportunità di golf che non ho provato online!
Leone

9

Java 10, 155 108 105 100 97 byte

v->{var s="122";for(int i=1;;s+=(1+i%2)*(s.charAt(i)>49?11:1))System.out.print(s.charAt(++i-2));}

Stampa indefinitamente senza delimitatore.

-3 byte dopo un suggerimento indiretto di @Neil .
-5 byte grazie a @MartinEnder .
-3 byte che convertono Java 8 in Java 10.

Spiegazione:

Provalo online (scade dopo 60 secondi su TIO).

v->{              // Method with empty unused parameter and no return-type
  var s="122";    //  String, starting at "122"
  for(int i=1;;   //  Loop `i` from 1 upwards indefinitely
      s+=         //    After every iteration: Append the String with:
         (1+i%2)  //     1+`i`modulo-2
         *(s.charAt(i)>49?11:1))
                  //     either once or twice depending on the digit at index `i`
    System.out.print(s.charAt(++i-2));}
                  //   Print the character at index `i-2` of the String
                  //   After we've first increased `i` by 1 with `++i`

1
Mi piace come hai reso questo aspetto così semplice.
Erik the Outgolfer,

@EriktheOutgolfer Grazie! :) Quando ho letto la sfida non ero sicuro di come iniziare, ma poi mi ha colpito (usando un elenco con l'iniziale [1,2,2]e vai da lì) e ho scritto la risposta a 155 byte (che ora viene giocata a golf usando una stringa invece di Elenco).
Kevin Cruijssen,

Perché non usare (3-i)invece di (1+i%2)?
Erik the Outgolfer

1
@EriktheOutgolfer perché inon è 1 o 2, è l'indice di stringa.
Martin Ender,

7

Gelatina , 10 byte

’߀+\<¹SḂ‘

Restituisce il n ° periodo.

Provalo online!

Come funziona

’߀+\<¹SḂ‘  Main link. Argument: n (positive integer)

’           Decrement; yield n-1.
 ߀         Recursively map the main link over [1, ..., n-1].
   +\       Take the cumulative sum.
            The k-th sum is the combined length of the first k runs.
     <¹     Compare each sum with n.
       S    Sum the Booleans.
            This counts the number of runs that occur before the n-th term.
            If there's an even number (including 0) of runs, the n-th term is 1.
            If there's an odd number of runs, the n-th term is 2.
        Ḃ   Extract the least significant bit of the count.
         ‘  Increment.

7

Haskell , 33 byte

r=r%1
~(x:t)%n=n:[n|x>1]++t%(3-n)

Provalo online!

Ørjan Johansen ha salvato 7 byte usando un modello irrefutabile per forzare il prefisso.


5
È possibile salvare 7 byte rendendolo più pigro. Provalo online!
Ørjan Johansen

@ ØrjanJohansen È fantastico e il modello pigro è magico per me. Vuoi pubblicare la tua risposta?
xnor

No, eri la maggior parte lì. Usando n:all'inizio dell'espressione non è necessario sapere che xc'è per produrre il primo n. Ma è necessario che il pattern sia pigro per evitare che la funzione lo controlli prima di arrivare a n:.
Ørjan Johansen

6

Gol> <> , 8 7 byte

:{:PnKz

Provalo online!

Spiegazione

Questa è una porta della mia risposta di Wumpus . Gol> <> è fondamentalmente il linguaggio che ha tutte le funzionalità necessarie per eseguire il port della risposta di Wumpus (in particolare, zeri impliciti nella parte inferiore dello stack, "duplicato" implementato "pop, push, push" e un comando di rotazione dello stack), ma :

  • Ha una griglia toroidale, il che significa che non abbiamo bisogno dell'esplicito 00.per tornare all'inizio.
  • Ha K, che è "pop N, quindi duplica il prossimo elemento N volte", che può sostituire ?=, salvando un altro byte.

Quindi la mappatura da Wumpus a Gol> <> diventa:

Wumpus   Gol><>
=        :
[        {
=        :
)        P
O        n
?=       K
!        z
00.

6

Shakespeare Programming Language , 594 583 572 byte

Grazie a Ed Wynn per -10 byte!

,.Ford,.Puck,.Act I:.Scene I:.[Enter Ford and Puck]Ford:You cat!Open heart!You big cat!Open heart!Puck:Remember you!Remember me!Scene V:.Ford:You is the sum ofI a cat!Puck:Recall!Open heart!Ford:Remember a pig!Is I nicer a cat?If notyou be the sum ofyou a big pig!Scene X:.Puck:Recall!Ford:Is I nicer zero?If soremember I!If solet usScene X!Puck:Is I nicer zero?You is the sum ofI a big cat!If soyou is I!Remember zero!Remember I!Remember you!You be the difference betweena big cat you!Scene L:.Ford:Recall!Is you worse I?If so,let usScene V!Puck:Remember I!Let usScene L!

Provalo online!

Questa è una versione giocata a golf della soluzione ungolfed di Ed Wynn , a partire dalla soluzione a 828 byte che ha collegato nei commenti e andando un po 'fuori di testa da lì.

Spiegazione:

,.Ford,.Puck,.Act I:.Scene I:.[Enter Ford and Puck]    Boilerplate, introducing the characters
Ford:You cat!Open heart!You big cat!Open heart!  Print 1,2 as the first two terms of the sequence

Puck:Remember you!Remember me!  Initialise stack as 0, 2
                                Ford's value is currently 0, representing the value to be pushed to the stack

Scene V:.     Start infinite loop
  Ford:You is the sum ofI a cat!         
  Puck:Recall!Open heart!                 Pop the next value in the stack and print it
  Ford:Remember a pig!                    Push -1 as the end of the stack
  Is I nicer a cat?                       If Ford's value is 2
  If notyou be the sum ofyou a big pig! Subtract 2 from Puck's value to represent making 2 only one copy

        #Reverse the stack until it reaches the terminator value 0 or -1
  Scene X:.Puck:Recall!Ford:Is I nicer zero?If soremember I!If solet usScene X!

  Puck:Is I nicer zero?                          Check if the Puck's value is bigger than 0 (only making one copy)
  You is the sum of Ia big cat!                 Set Ford's value to Puck+2 to counter the change
  If soyou is I!                                But undo it if making one copies
  Remember zero!                                 Push 0 as the stack terminator
  Remember I!                                    Push Ford's value, which is 0 or -1 if this is a single copy, or 1 or 2 for a double copy
  Remember you!                                  Push one copy of Puck's value
  You be the difference betweena big cat you!   Map Ford's value from 1,2 to 1,0

  Scene L:.   #Reverse the stack until it reaches the terminator 0 
     Ford:Recall!Is you worse I?If solet us Scene V!
     Puck:Remember I!Let usScene L!

Bello! È possibile salvare 7 byte facendo in modo che il singolo figlio sia (-1 o 0) anziché i gemelli. Questo ti costa 1 byte appena prima della scena X (quando "In tal caso" diventa "In caso contrario") e un altro byte subito dopo il ciclo della scena X (quando "È più gentile" diventa "È più bello zero"). Il risparmio è che puoi sostituire "Se no, ricordati di te!" con semplicemente "Ricordati di me!" una riga prima. Inseriamo un secondo figlio o un terminatore di riserva. (Questo è il motivo per cui è necessario modificare il finemente bilanciato "Sono più gentile?" - non puoi più fare affidamento su Ford == 0 dopo la scena X.) Ecco TIO, 587 byte: tinyurl.com/yb9zg4gp
Ed Wynn,

È possibile rimuovere il primo "In tal caso" nella scena L e spostare il comando all'inizio della scena V. Ciò consente di risparmiare solo 1 byte, poiché è necessario un nuovo "Ford:". Ma risparmi un paio di byte nella scena I, a condizione che tu possa fare affidamento sul fatto che Ford viene automaticamente inizializzato a zero. Non hai il diritto di fare affidamento su questo, ma potrebbe funzionare: ecco TIO, 584 byte: tinyurl.com/y9f6vy7u
Ed Wynn,

5

> <> , 13 12 byte

0:{:1+n?:0=!

Provalo online!

Un porto della risposta Wumpus di Martin Ender . Sfortunatamente, ><>non ha un incremento o un comando invertito né ha 0 impliciti nella parte inferiore dello stack, quindi finisce per essere un po 'più lungo.


1
Sì, questo è quello che avevo prima di ricordare Gol> <>. :)
Martin Ender il

5

JavaScript, 67 66 60 58 52 51 50 byte

Bene, questo mi ha fatto prudere il cervello più di quanto avrebbe dovuto! Annulla il ntermine, indicizzato 0.

s=`122`
x=1
f=n=>s[n]||f(n,s+=s[++x%2]*(s[x]+0-9))

5 + 1 byte salvati grazie a tsh che graffia il mio cervello pruriginoso!


Provalo

Lo snippet di seguito mostrerà i primi 50 termini.


Spiegazione

Questa è una di quelle rare occasioni in cui possiamo dichiarare alcune variabili al di fuori dell'ambito della nostra funzione, modificarle all'interno della funzione ed essere ancora in grado di riutilizzarle nelle successive chiamate della funzione.

s=`122`       :Initialise variable s as the string "122"
x=1           :Initialise variable x as integer 1
f=n=>         :Named function f taking input as an argument through parameter n
 s[n]         :If s has a character at index n, return it and exit
 ||           :Or
 f(n          :Call f with n again
  ,s+=        :At the same time, append to s
  s[++x%2]    :  Increment x, modulo by 2 and get the character at that index in s
  *           :  Multiplied by (the above gets cast to an integer)
  (s[x]+0-9)  :  Append a 0 to the xth character of s and subtract 9
 )            :  (The above gives "1"+0-9="10"-9=1 or "2"+0-9="20"-9=11)

Che diren=>(g=s=>s[n]||g(s+(++x%2+1)*(10*s[x]-9)))('122',x=1)
tsh

A proposito, è s='122',x=1,g=n=>s[n]||g(n,s+=(++x%2+1)*(10*s[x]-9))considerata una proposta valida?
TSH

Grazie @tsh. s[n]||è stato un chiaro caso di non vedere il bosco per gli alberi! Il tuo secondo suggerimento non sarebbe valido, tuttavia, poiché la funzione poteva essere chiamata una sola volta; se xdevono essere inizializzati ad ogni chiamata.
Shaggy

il secondo è riutilizzabile, purché se xnon sia toccato da altri codici tra ogni invocazione (che è di default).
dal

1
Bello! s[x]+0-9è un bel trucco
JollyJoker

4

Python (2 e 3), 65 60 byte

f=lambda n:sum([f(i)*[i%2+1]for i in range(2,n)],[1,2,2])[n]

Restituisce il n ° di entrata, 0-indicizzato.

Alternativa (65 byte):

f=lambda n:n>1and sum([f(i)*[i%2+1]for i in range(n)],[])[n]or-~n

3
Benvenuti in PPCG!
Martin Ender,

1
Puoi (probabilmente, non ho ancora testato) salvare 5 byte nella versione alternativa usando [1,2,2]come valore iniziale nelsum
Rod


4

Brainfuck , 61 byte

+.+.[.[>]>+++>+++<<<[->+>->-<<<]<[[->+<]<]>>--[[>]<,<[<]>+]>]

Provalo online!

Stampa i numeri come codici carattere indefinitamente. Per chiarezza, ecco una versione che viene stampata in numeri (ad eccezione dei primi due elementi, che sono abbastanza facili da verificare).

Come funziona:

+.+. Prints the first two elements. These are the self-referential elements
     This also intitialises the tape with the third element, 2
[ Start infinite loop
   . Print current lowest element
   [>]>+++>+++ Move to end of tape and create two 3s
   <<<[->+>->-<<<] Subtract the last element of the tape from these 3s
   <[[->+<]<]>> Move to the beginning of the tape
   --  Subtract two from the first element
       This leaves 2 as 0 and 1 as -1
   [ If the number was 1
     [>]<,  Delete the excess element from the end of the tape
     <[<]>+ Remove the -1
   ]
   > Move to the next element of the list
]

4

05AB1E , 12 9 byte

Salvato 3 byte grazie a Grimy

Stampa i primi n elementi.

Δ2LÞsÅΓI∍

Provalo online!

Spiegazione

Δ           # repeat until ToS doesn't change
 2LÞ        # push [1,2,1,2 ...]               
    sÅΓ     # run-length encode with previous value (initially input)
       I∍   # extend/shorten to the length specified by input

La decodifica della lunghezza di esecuzione è ora integrata, quindi può essere semplicemente così 2L[2LÞsÅΓ.
Grimmy,

O ancora meglio: ∞[2LÞsÅΓ.
Grimmy,

O Δ2LÞsÅΓI∍per una versione che stampa i primi n elementi dati input n.
Grimmy,

@Grimy: grazie! Mi piace la prima versione n poiché termina in realtà :)
Emigna il

3

05AB1E , 15 byte

ƵLS[DNÌ©èF®É>¸«

Provalo online! o con un limite di iterazione

Spiegazione

ƵLS               # push our initial list [1,2,2]
   [              # for every N in [0 ...
    D             # duplicate current list of numbers
     NÌ©è         # get the N+2'th element from the list
         F        # that many times do
          ®É>     # push ((N+2)%2==1)+1
             ¸«   # append to current list

Invece di ¸«, =li stampa per 2 byte salvati. ƵLS[NÌ©èF®É>=, non è necessario ingannare se non stai consumando.
Magic Octopus Urn

@MagicOctopusUrn: Non produco i primi 3 articoli, quindi la stampa purtroppo non funziona
Emigna


3

J , 12 byte

Funzione a argomento singolo che prende n e produce i primi n termini. Provalo online!

$(1+2|I.)^:]

Sto solo elaborando la mia vecchia risposta alla vecchia domanda.

I.è un verbo che accetta una matrice di numeri e sputa un elenco di indici, quindi se l' elemento k -esima nella matrice è n , l'indice k appare n volte. Lo useremo per avviare la sequenza di Kolakowski da un seme iniziale. Ogni passaggio procederà come segue:

1 2   2   1 1 2   1 2   2   1   (some prefix)
0 1 1 2 2 3 4 5 5 6 7 7 8 8 9   (use I.)
0 1 1 0 0 1 0 1 1 0 1 1 0 0 1   (mod 2)
1 2 2 1 1 2 1 2 2 1 2 2 1 1 2   (add 1) 

Se eseguiamo questa operazione ( 1+2|I.) più e più volte a partire da 10, è simile a questa:

10
1 1 1 1 1 1 1 1 1 1
1 2 1 2 1 2 1 2 1 2
1 2 2 1 2 2 1 2 2 1 2 2 1 2 2
1 2 2 1 1 2 1 1 2 2 1 2 2 1 1 ...
1 2 2 1 1 2 1 2 2 1 2 1 1 2 2 ...
1 2 2 1 1 2 1 2 2 1 2 2 1 1 2 ...

Nota come otteniamo sempre più termini corretti ogni volta e dopo un po ' vengono fissati i primi n termini. Il numero di iterazioni necessarie per sistemarsi è difficile da descrivere con precisione, ma sembra essere approssimativamente logaritmico in n , quindi se lo eseguiamo solo n volte ( ^:]) dovrebbe andare bene. (Dai un'occhiata a queste altre sequenze OEIS per maggiori informazioni: lunghezze di generazione , somme parziali .)

Una volta fatto, tutto ciò che dobbiamo fare è prendere i primi n termini usando $. La costruzione $vdi ogni verbo vè un esempio di hook e neseguendolo come argomento verrà eseguito n $ (v n).

Ecco la versione 13-byte, che è molto meno spreco di tempo e di spazio: ($1+2|I.)^:_~. Tronca l'input ad ogni passo, quindi possiamo correre esattamente quante volte è necessario per accontentarci, invece che linearmente molte volte.


Oh, questo funziona perfettamente con I.. Ho sempre desiderato vedere la sua funzione di copia utilizzata in alcuni campi da golf.
miglia

3

Fueue , 30 byte

Fueue è un esolang basato sulla coda in cui il programma in esecuzione e i suoi dati sono entrambi nella stessa coda, l'esecuzione gira intorno alla coda in cicli e la programmazione richiede molta sincronizzazione per impedire che qualsiasi cosa venga eseguita al momento sbagliato.

1)2:[[2:])~)~:~[[1]:~))~:~~]~]

Provalo online!

Quanto sopra stampa un elenco infinito di cifre come codici di controllo. Per 34 byte può stampare cifre effettive:

49)50:[[50:])~)~:~[[49]:~))~:~~]~]

Provalo online!

Il resto della spiegazione utilizza quest'ultima versione.

Riepilogo degli elementi Fueue

La coda Fueue può contenere il seguente tipo di elementi:

  • Numeri interi, che stampano il loro punto di codice Unicode quando eseguiti,
  • Blocchi di sottoprogrammi delimitati da parentesi quadre, che sono misericordiosamente inattivi (si stanno spostando fino alla fine della coda) a meno che la )funzione non li blocchi , e
  • Funzioni a carattere singolo, che vengono eseguite se sono seguite dal giusto tipo di argomenti e restano inattive in caso contrario.
    • Le uniche funzioni utilizzate in questo programma sono ~(scambiare due elementi seguenti), :(duplicare l'elemento successivo) e )(deblock dopo il blocco).

Panoramica di alto livello

Durante il ciclo principale del programma, la coda è composta da:

  • una catena di blocchi che rappresentano le cifre da ripetere;
    • Una cifra 1 o 2 è rappresentata dai blocchi [49]e [50:], rispettivamente.
  • una sezione di loop principale autoreplicante che attraversa i blocchi di cifre e inserisce alternativamente 1 e 2 secondi, quindi li sblocca.
    • Un blocco di cifre deblocked stampa la propria cifra d , quindi crea d copie del blocco seguente, creando così le cifre per l'esecuzione che descrive.

Traccia di basso livello dei primi 10 comandi

Cmds   Explanation              Queue
49     Print '1'.               )50:[[50:])~)~:~[[49]:~))~:~~]~]
)      Inactive, move to end.   50:[[50:])~)~:~[[49]:~))~:~~]~])
50     Print '2'.               :[[50:])~)~:~[[49]:~))~:~~]~])
:[...] Duplicate block.         )[[50:])~)~:~[[49]:~))~:~~]~][[50:])~)~:~[[49]:~))~:~~]~]
)[...] Deblock (rmv. brackets). [[50:])~)~:~[[49]:~))~:~~]~][50:])~)~:~[[49]:~))~:~~]~
[...]  Inactive.                [50:])~)~:~[[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~]
[50:]  Inactive.                )~)~:~[[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~][50:]
)      Inactive.                ~)~:~[[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~][50:])
~)~    Swap ) and ~.            :~[[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~][50:])~)
:~     Duplicate ~.             [[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~][50:])~)~~

Procedura dettagliata di un'iterazione del ciclo principale completo

Lo spazio bianco opzionale è stato inserito per separare i comandi.

49 ) 50 :[[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 1: 49stampe 1. )è inattivo, in attesa di essere riunito con il blocco loop principale. 50stampe 2. :duplica il blocco del ciclo principale (che necessita di una copia per l'auto-replica).

) [[50:])~)~:~[[49]:~))~:~~]~] [[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 2: )esegue il deblock del primo blocco di loop principale, facendolo iniziare l'esecuzione del ciclo successivo.

[50:] ) ~)~ :~ [[49]:~))~:~~] ~[[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 3: [50:]rappresenta la prima cifra prodotta nella catena, un 2non ancora sbloccato. Quanto segue )alla fine lo farà dopo che il resto del loop principale lo avrà attraversato. ~)~:~è un ritardo golfizzato (usando uno scambio e una copia) di un ciclo di ~)~~. [[49]:~))~:~~]è inattivo. ~scambia il seguente blocco di loop principale oltre il [50:]blocco di cifre.

) ~)~ ~[[49]:~))~:~~][50:] [[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 4: )attende ancora, ~)~produce ~), ~scambia [[49]:~))~:~~]oltre il [50:]blocco di cifre.

) ~)[50:] [[49]:~))~:~~] [[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 5: ~swap )oltre il [50:]blocco di cifre.

)[50:] )[[49]:~))~:~~] [[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 6: il primo )ora esegue il deblock del [50:]blocco cifre, il successivo )esegue il deblock del sottoprogramma [[49]:~))~:~~].

50 :[49] :~ ) ) ~:~ ~[[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 7: 50stampa 2, :duplica il [49]blocco di cifre appena prodotto , creando una sequenza di due 1secondi. :~))~:~è un ritardo di un ciclo di ~~))~:. ~scambia il blocco di loop principale rimanente oltre il primo [49].

[49] ~~) ) ~:[49] [[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 8: ~~))è un ritardo di un ciclo di )~). ~swap :ultimi attualmente attraversato [49].

[49] ) ~)[49] :[[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 9: ~scambi )passati [49]. :duplica il blocco del loop principale.

[49] )[49] )[[50:])~)~:~[[49]:~))~:~~]~] [[50:])~)~:~[[49]:~))~:~~]~]

Ciclo 10: il primo )esegue il deblock del [49]blocco di cifre appena attraversato, il secondo )riavvia il ciclo principale per attraversare quello successivo (mostrato sopra all'inizio della coda).


Bel lavoro! Il motivo per cui ho imparato un po 'di Fueue e ho risposto alla sfida HW perché in realtà l'ho esaminata per questa sfida, ma alla fine sono stato troppo intimidito dalla natura basata sulla coda. È davvero un ottimo punteggio per Fueue! :)
Martin Ender,

3

x86, 41 37 35 33 28 byte

Mi sono divertito molto a scherzare con diverse istruzioni x86, poiché questa è la mia prima risposta x86 "non banale". In realtà ho imparato prima x86-64 e ho salvato molti byte semplicemente convertendo il mio programma a 32 bit.

Si scopre che l'algoritmo che ho usato da OEIS invia i valori a un array, il che lo rende suscettibile a x86 e memorizza i valori nello stack (nota che MIPS non ha istruzioni sullo stack).

Attualmente il programma accetta i Nvalori come input ecxe restituisce un indirizzo in ebpun array con l'ennesimo elemento che rappresenta l'ennesimo valore nella sequenza. Suppongo che il ritorno in pila e il calcolo di valori extra siano validi (consideriamo comunque ciò che va oltre l'array come immondizia).

changelog

  • -4 byte calcolando x = 2 - n%2con xorogni iterazione

  • -2 byte utilizzando il ciclo do-while anziché while.

  • -2 byte premendo i valori iniziali 1, 2, 2 usando eax

  • -5 byte non memorizzando in modo nesplicito e invece eseguendo i Ntempi di ciclo

.section .text
.globl main
main:
        mov     $10, %ecx           # N = 10 

start:
        mov     %esp, %ebp          # Save sp
        push    $1
        push    $2                  # x = 2
        pop     %eax       
        push    %eax                # push 2
        push    %eax                # push 2
        mov     %esp, %esi          # sn = stack+3 addr

loop:                               
        xor     $3, %al             # flip x between 1 <-> 2 
        push    %eax                # push x      
                                    # maybe use jump by parity?
        cmp     $2, (%esi)          # if *sn == 2 
        jne     loop1
        push    %eax                # push x

loop1: 
        sub     $4, %esi            # sn += 1
        loop    loop                # --N, do while (N)
end:
        mov     %ebp, %esp          # Restore sp
        ret

objdump:

00000005 <start>:
   5:   89 e5                   mov    %esp,%ebp
   7:   6a 01                   push   $0x1
   9:   6a 02                   push   $0x2
   b:   58                      pop    %eax
   c:   50                      push   %eax
   d:   50                      push   %eax
   e:   89 e6                   mov    %esp,%esi

00000010 <loop>:
  10:   34 03                   xor    $0x3,%al
  12:   50                      push   %eax
  13:   83 3e 02                cmpl   $0x2,(%esi)
  16:   75 01                   jne    19 <loop1>
  18:   50                      push   %eax

00000019 <loop1>:
  19:   83 ee 04                sub    $0x4,%esi
  1c:   e2 f2                   loop   10 <loop>

0000001e <end>:
  1e:   89 ec                   mov    %ebp,%esp
  20:   c3                      ret 

3

C (gcc) , 72 71 65 64 62 byte

-9 byte grazie a @ceilingcat

x,y;f(z){for(x=y=-1;putchar(49-~x%2);y=-~y|z&x/2)x^=z=y&~-~y;}

Provalo online!

Genera valori della sequenza indefinitamente (opzione 3 dalla sfida)


Spiegazione per favore! Non ho idea di come funzioni. Non c'è array! E i numeri rimangono troppo piccoli per contenerne uno come bit.
Ørjan Johansen,

@ ØrjanJohansen Devo ammetterlo, non ho idea di come funzioni! :) Ho preso l'implementazione di Python da OEIS A000002 , l' ho portato su C e l'ho giocato a golf :)
vazt

Ah, ho pensato che potesse essere stato qualcosa lì, ma non ho guardato abbastanza in basso in quella pagina per trovare il Python. C'è un link a una spiegazione , ma è stato un po 'sepolto nella sezione link. Questo metodo sicuramente si adatta anche a C almeno.
Ørjan Johansen,

1) 56 byte in PHP: for($x=$y=-1;;$y=$y+1|$f&.5*$x^=$f=$y&-$y-2)echo$x&1?:2;. 2) 50-x%2dovrebbe salvare un byte per te. 3) Ho provato a farlo funzionare x=y=1; ma finora non è stato possibile eseguire le operazioni. Puoi?
Tito

2

Perl 5 , 36 byte

Ancora una banale modifica della classica soluzione TPR (0,3):

Emette le serie da 0an

#!/usr/bin/perl
use 5.10.0;
say$_=($n+=!--$_[$n])%2+1for@_=0..<>

Provalo online!


2

Javascript ES6 - 71 70 68 byte

(_="122")=>{for(x=1;;_+=(1+x%2)*(_[x]>1?11:1))console.log(_[++x-2])}

1 bit salvato grazie a Neil

Tanks to Shaggy per aver corretto il mio errore, anche per aver salvato 1 bit.

f = (_="122") => {
  for(x=1;x<20;_+=(1+x%2)*(_[x]>1?11:1))
    document.getElementById('content').innerHTML += '   ' + _[++x-2]
}
f()
<div id="content"></div>


Sembra una porta della mia risposta Java 8 (tranne per x=0invece di x=1), ma @Shaggy ha davvero ragione: questo non funziona nella sua forma attuale (ho aggiunto ,i=100;i-->0temporaneamente il solo per vedere i primi 100 elementi, invece di dover attendere 60 secondi prima di vedere un output). Non ho idea del perché non funzioni, però. JS non è la mia cosa.
Kevin Cruijssen,

I problemi sono: 1.iniziando xsu 0 invece di 1 (come menzionato @KevinCruijssen) e 2.controllando se il xcarattere th nella stringa, che può essere solo 1 o 2, è maggiore di 49.
Shaggy

2
Ecco una versione ridotta (ma non completamente testata) della soluzione fissa: tio.run/…
Shaggy

(_[x]*10-9)di(_[x]>1?11:1)
l4m2

2

Appleseed , 89 byte

(def K(lambda()(concat(q(1 2))(drop 2(flatten(zip-with repeat-val(cycle(q(1 2)))(K)))))))

Definisce una funzione Kche non accetta argomenti e restituisce la sequenza di Kolakoski come un elenco infinito. Provalo online!

Questo approccio è stato ispirato dalla risposta di Haskell totalmente umana . Il mio approccio originale era più lungo ed era probabilmente O (2 ^ n). : ^ P

Ungolfed

(def kolakoski
 (lambda ()
  (concat (list 1 2)
   (drop 2
    (flatten
     (zip-with repeat-val
      (cycle (list 1 2))
      (kolakoski)))))))

L'elenco di ritorno inizia con (1 2). Successivamente, per generare il resto (leggendo dall'interno verso l'esterno):

  • Chiamata ricorsiva (kolakoski)per ottenere l'elenco delle sequenze di Kolakoski (a causa di una valutazione pigra, non importa che l'elenco non sia stato ancora completamente generato)
  • (cycle (list 1 2)) crea un elenco infinito (1 2 1 2 1 2 ...)
  • Comprimi insieme le due liste infinite usando la funzione repeat-val. Questo ripeterà il 1o 2dalla cyclelista di una o due volte a seconda del valore associato nell'elenco Kolakoski. Risultato:((1) (2 2) (1 1) ...)
  • flatten quella lista in (1 2 2 1 1 ...)
  • Abbiamo già ottenuto i primi due termini da (concat (list 1 2), quindi dropi primi due dall'elenco generato per evitare la duplicazione.

2

Stax , 12 byte

╦╥2Bïß▄n»-[╒

Esegui ed esegui il debug

Questa è la rappresentazione ASCII dello stesso programma.

G@}2R;D{|;^]*m$

Espande la sequenza x volte dove x è l'ingresso. Quindi emette l' elemento x esimo , indicizzato 0.

G }             G jumps to trailing } and returns when done
 @              get xth element in array
   2R           [1, 2]
     ;D         repeat the rest x times
       {     m  map array using block
        |;^]    produces [1] and [2] alternately
            *   repeat array specified number of times
              $ flatten array

Ecco una soluzione bonus a 12 byte che produce output come un flusso infinito. Premi Esegui per iniziare.


2

R, 63 byte o 61 byte

Attuazione 1: stampa il n ° termine della successione.

x=scan()
a=c(1,2,2)
for(n in 3:x)a=c(a,rep(2-n%%2,a[n]))
a[x]

Implementazione 2: stampa i primi n termini della sequenza.

x=scan()
a=c(1,2,2)
for(n in 3:x)a=c(a,rep(2-n%%2,a[n]))
a[1:x]

(La differenza è solo nell'ultima riga.)

Sì, sì, potresti lamentarti che la mia soluzione è inefficiente, che calcola davvero più termini del necessario, ma comunque ...

Aggiornamento: grazie a @Giuseppe per la rasatura di 9 byte.


1
utilizzare al a=c(a,rep(2-n%%2,a[n]))posto del secondo forciclo per eliminare alcuni byte.
Giuseppe,

@Giuseppe Implementato, grazie!
Andreï Kostyrka,

Non ci dispiace inefficiente per le soluzioni di golf qui. In effetti, l'utilizzo di un algoritmo più inefficiente è uno dei suggerimenti nel wiki del tag code-golf .
Ørjan Johansen,

2

Shakespeare Programming Language, 575 byte (ma difettoso) o 653 o 623 byte

,.Puck,.Ford,.Act I:.Scene X:.[Enter Puck and Ford]Ford:You big cat!Scene L:.Ford:Is I nicer zero?If so,let us Scene V.Is you nicer a big cat?If so,you is the sum of you a big lie.If so,open heart!Open heart!Scene M:.Puck:Remember you!Is I nicer a cat?You big cat.If so,you cat.Ford:Recall!Is you nicer zero?If not,let us Scene X.Is you nicer a big cat?If not,let us Scene M.You is the sum of you a big lie.Scene V:.Ford:Remember you!Is you worse a big big cat?If not, you big cat.Is you as big as a big cat?If not,you zero.You is the sum of I you.Puck:Recall!Let us Scene L.

Nella categoria SPL fortemente contestata, ciò batterebbe l'attuale voce di Jo King (583 byte), tranne per il fatto che è difettoso: in primo luogo, non funziona nella versione TIO (implementando il sito Web SPL) - ma funziona nel Perl versione , quindi forse non è un difetto grave. In secondo luogo, tuttavia, non stampa le prime due cifre. Se permettessimo quel difetto nella soluzione di Jo King, allora quella soluzione difettosa sarebbe 553 byte, battendo la mia soluzione difettosa.

La mia soluzione non riesce su TIO per due motivi: proviamo a fare affidamento su uno stack vuoto che restituisce zero quando viene visualizzato; e andiamo alla prima scena, con "[Enter Ford and Puck]" anche se nessuno ha lasciato il palco. Questi sono solo avvertimenti nella versione Perl. Se correggo questi errori e inserisco le prime due cifre, raggiungo 653 byte:

 ,.Puck,.Ford,.Act I:.Scene I:.[Enter Puck and Ford]Ford:You cat!Open heart!You big cat!Open heart!You zero!Scene X:.Ford:Remember you!You big cat!Scene L:.Ford:Is I nicer zero?If so,let us Scene V.Is you nicer a big cat?If so,you is the sum of you a big lie.If so,open heart!Open heart!Scene M:.Puck:Remember you!Is I nicer a cat?You big cat.If so,you cat.Ford:Recall!Is you nicer zero?If not,let us Scene X.Is you nicer a big cat?If not,let us Scene M.You is the sum of you a big lie.Scene V:.Ford:Remember you!Is you worse a big big cat?If not, you big cat.Is you as big as a big cat?If not,you zero.You is the sum of I you.Puck:Recall!Let us Scene L.

Provalo online!

Posso generare l'intera sequenza nell'implementazione Perl usando 623 byte:

,.Puck,.Ford,.Act I:.Scene I:.[Enter Puck and Ford]Ford:You cat!Open heart!You big cat!Open heart!Scene L:.Ford:Is I nicer zero?If so,let us Scene V.Is you nicer a big cat?If so,you is the sum of you a big lie.If so,open heart!Open heart!Scene M:.Puck:Remember you!Is I nicer a cat?You big cat.If so,you cat.Ford:Recall!Is you worse a cat?If so,you big cat!If so,let us Scene L.Is you nicer a big cat?If not,let us Scene M.You is the sum of you a big lie.Scene V:.Ford:Remember you!Is you worse a big big cat?If not, you big cat.Is you as big as a big cat?If not,you zero.You is the sum of I you.Puck:Recall!Let us Scene L.

Tuttavia, vorrei sottolineare che questa soluzione è veloce rispetto a molte altre soluzioni e utilizza quantità logaritmiche di memoria anziché archiviare l'intero elenco. (Questo è simile alla soluzione C di Vazt, alla quale è lontanamente correlato.) Questo non fa differenza per il golf, ma ne sono contento. È possibile generare un milione di cifre in circa un minuto in Perl (ad esempio se si esegue il pipe su sed e wc per ottenere un conteggio delle cifre), dove l'altra soluzione potrebbe fornire alcune migliaia di cifre.

Spiegazione

Memorizziamo una sequenza di variabili in ordine: pila di Puck (dal basso verso l'alto), valore di Puck, valore di Ford, pila di Ford (dall'alto verso il basso). A parte i valori zero alle estremità (con lo zero a sinistra forse per far apparire uno stack vuoto), ogni valore è la cifra generata successivamente a quella generazione, con 2 aggiunti se la generazione successiva deve avere un altro figlio da quel genitore. Quando nella sequenza abbiamo N valori diversi da zero, generiamo tutti i bambini fino all'N-esima generazione inclusa, in una sorta di attraversamento dell'albero in profondità. Stampiamo valori solo dalla nona generazione. Quando l'N-esima generazione è stata completamente generata, i valori memorizzati sono in effetti i valori iniziali per le generazioni da 2 a (N + 1), quindi aggiungiamo un 2 a sinistra e ricominciamo, questa volta generando (N + 1 ) di generazione.

Quindi, uno schema: Scena X: Quando arriviamo qui, questo è l'inizio di una nuova traversata. Puck == 0. Opzionalmente spingiamo quello zero nello stack di Puck e impostiamo Puck = 2. Scena L: se Ford == 0, abbiamo raggiunto la generazione di stampa. In caso contrario, vai a V. Per la stampa, se al valore in Puck sono stati aggiunti 2, rimuovi il 2 e stampalo due volte; in caso contrario, stampalo una volta. Scena M: questo è un loop in cui ripetutamente alterniamo il valore di Puck e torniamo indietro attraverso la sequenza. Ripetiamo fino a quando non raggiungiamo la fine (Disco == 0), nel qual caso andiamo a X, o raggiungiamo un valore che ha bisogno di un altro figlio (Disco> 2), nel qual caso sottraggiamo il 2 in più e andiamo avanti in V. Scena V: Qui andiamo avanti. Se Puck è 2 o 4, la generazione successiva conterrà due figli del genitore attuale, quindi Ford + = 2. Fai un passo avanti nella sequenza. Vai a L per verificare la risoluzione.


1

axo , 13 byte

[:|[1+{#;1;-_

Provalo online!

Spiegazione

Questo è iniziato come una porta di una soluzione alternativa nella mia risposta di Wumpus :

2%)[=]&=[O00.

Ciò ha comportato 18 byte. Ho finito per giocare a golf fino ai 13 byte che vedi sopra per adattarlo maggiormente al modo in cui axo funziona. Questa versione a 13 byte ha poi ispirato il miglioramento fino a 11 byte in Wumpus, quindi ora è in realtà più vicina a quella versione.

Come in Wumpus, in iterazione i , il fondo della pila tiene a (i) -1 e all'inizio detiene il primo elemento della i esima corsa, ma stiamo lavorando con 0 e 1 in tutto, tranne che per la stampa.

[:    Store a copy of the top of the stack in register A.
|     Pull up a(i)-1 from the bottom of the stack.
[1+{  Print a(i).
#;    If a(i)-1 is 1, push the value in register A.
1;-   Push another copy of that value and subtract it from 1 to swap
      0 and 1 for the next run.
_     Jump back to the beginning of the program.

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.