Calcule la secuencia de Kolakoski

54

Este es un reenvío de un viejo desafío , con el fin de ajustar los requisitos de E / S a nuestros estándares recientes. Esto se hace en un esfuerzo por permitir que más idiomas participen en un desafío sobre esta secuencia popular. Vea esta meta publicación para una discusión de la nueva publicación.

La secuencia de Kolakoski es una secuencia divertida autorreferencial, que tiene el honor de ser la secuencia OEIS A000002 (y es mucho más fácil de entender e implementar que A000001). La secuencia se inicia con 1 , se compone sólo de 1 s y 2 s y el elemento de secuencia de un (n) describe la longitud de la n º plazo de 1 s o 2 s en la secuencia. Esto define de forma única la secuencia que debe ser (con una visualización de las ejecuciones debajo):

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,...

Su tarea es, por supuesto, implementar esta secuencia. Puede elegir uno de los tres formatos para hacerlo:

  1. Tome una entrada n y la salida de la n º término de la secuencia, donde n comienza ya sea desde 0 o 1 .
  2. Tome una entrada n y la salida de los términos hasta e incluyendo el n º término de la secuencia, donde n comienza ya sea desde 0 o 1 (es decir, imprimir o bien la primera n o la primera n + 1 términos).
  3. Valores de salida de la secuencia indefinidamente.

En el segundo y tercer caso, puede elegir cualquier formato de lista razonable y sin ambigüedades. Está bien si no hay un separador entre los elementos, ya que siempre son un solo dígito por definición.

En el tercer caso, si su envío es una función, también puede devolver una lista infinita o un generador en idiomas que los admitan.

Puede escribir un programa o una función y utilizar cualquiera de nuestros métodos estándar para recibir entradas y proporcionar salidas. Tenga en cuenta que estas lagunas están prohibidas por defecto.

Este es el , por lo que gana la respuesta válida más corta, medida en bytes .

Martin Ender
fuente
Relacionado , pero no un engañado.
Magic Octopus Urn
Generalización del problema , pero las optimizaciones son probablemente posibles ya que la parte inicial de la secuencia es fija.
Giuseppe
Mientras lo hacemos, también tengo otra generalización .
Martin Ender

Respuestas:

17

Jalea , 7 bytes

2Rṁxṁµ¡

Este es un programa completo que imprime los primeros n términos.

Pruébalo en línea!

Cómo funciona

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

Ejecución de ejemplo

Deje n = 5 .

La primera invocación de la cadena se repite 1, 2 cíclicamente para alcanzar la longitud 5 , luego cada elemento 5 veces y finalmente trunca el resultado a la longitud 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

Esto produce una lista de longitud 5 . El primer elemento es el primer elemento de la secuencia de Kolakoski.

La segunda invocación de la cadena repite 1, 2 cíclicamente para alcanzar la longitud 5 , luego repite el elemento k ésimo j veces, donde j es el elemento k ésimo de la lista anterior, y finalmente trunca el resultado a la longitud 5 .

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

   1 2 1 2 1

Esto produce otra lista de longitud 5 . Los dos primeros elementos son los dos primeros elementos de la secuencia de Kolakoski.

El proceso continúa durante tres iteraciones más.

   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

Estos son los primeros cinco elementos de la secuencia de Kolakoski.

Dennis
fuente
12

Python 2 , 51 bytes

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

Imprime indefinidamente. Crea la lista a lmedida que se repite. Para cada entrada xde l, agrega xcopias de 1o 2, lo que sea opuesto al último elemento actual.

La principal dificultad es tratar con el fragmento inicial autorreferencial [1,2,2]. Este código solo imprime la inicial 1,2y procede desde allí. La impresión extra cuesta 12 bytes. Sin eso:

39 bytes , faltan las dos primeras entradas:

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

Otro enfoque es inicializar especialmente las dos primeras entradas. Inicializamos lcomo [0,0,2]para que las dos primeras entradas no causan anexar, pero print x or nlos hace ser impresa como n.

51 bytes

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

Otra solución es inicializar l=[1], rastrear la alternancia manualmente ny corregir la impresión:

51 bytes

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

Sin el (l==[1,1])+, todo funciona excepto las secuencias impresas que comienzan en 1,1,2lugar de 1,2,2. Tiene que haber una mejor manera de reconocer que estamos en este segundo paso.

Y otra solución extraña, también de alguna manera el mismo conteo de bytes:

51 bytes

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

Wumpus , 13 11 bytes

=[=)O?=!00.

Pruébalo en línea!

Imprime la secuencia indefinidamente sin separadores.

Estoy realmente sorprendido por lo breve que es esto.

Explicación

La idea básica es mantener la secuencia en la pila y usar repetidamente el elemento más inferior para generar otra ejecución y luego imprimirla. Estamos abusando efectivamente de la pila como una cola aquí. También podemos guardar un par de bytes trabajando 0e 1(incrementando solo para la salida) en lugar de 1y 2, porque de esta manera no necesitamos inicializar explícitamente la pila con a 1y podemos usar la negación lógica para alternar entre los dos valores.

     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.
Martin Ender
fuente
10

Brachylog , 30 26 25 23 17 16 14 bytes

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

Emite los primeros n valores. Utiliza la "variable de salida" .para la entrada y las salidas a la "variable de entrada" ?. Pruébalo en línea!

Explicación

Estoy bastante contento con lo declarativo que resultó: el programa es básicamente una descripción de alto nivel de la lista de resultados y su relación con la entrada.

~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.

Como {1|2}ᵐprueba las listas en orden lexicográfico, la salida comenzará con 1.

Zgarb
fuente
9

Casco , 10 bytes

Ṡωo↑⁰`Ṙ¢ḣ2

Devuelve los primeros n valores. Pruébalo en línea!

Explicación

Ṡω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.

Para la entrada 20, el proceso es el siguiente:

[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]
Zgarb
fuente
1
Aquí hay una variación que imprime la secuencia indefinidamente, el mismo conteo de bytes, pero tal vez verá algunas oportunidades de golf. ¡No lo probé en línea!
Leo
9

Java 10, 155 108 105 100 97 bytes

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

Imprime indefinidamente sin delimitador.

-3 bytes después de una sugerencia indirecta de @Neil .
-5 bytes gracias a @MartinEnder .
-3 bytes que convierten Java 8 a Java 10.

Explicación:

Pruébelo en línea (agota el tiempo de espera después de 60 segundos en 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`
Kevin Cruijssen
fuente
1
Me gusta cómo has hecho que esto parezca tan simple.
Erik the Outgolfer
@EriktheOutgolfer ¡Gracias! :) Cuando leí el desafío, no estaba seguro de cómo comenzar, pero luego me di cuenta (usando una lista con la inicial [1,2,2]e ir desde allí) y escribí la respuesta de 155 bytes (que ahora se juega con una cadena en lugar de Lista).
Kevin Cruijssen
¿Por qué no usar en (3-i)lugar de (1+i%2)?
Erik the Outgolfer
1
@EriktheOutgolfer porque ino es 1 o 2, es el índice de cadena.
Martin Ender
7

Jalea , 10 bytes

’߀+\<¹SḂ‘

Devuelve el n º plazo.

Pruébalo en línea!

Cómo funciona

’߀+\<¹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.
Dennis
fuente
7

Haskell , 33 bytes

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

Pruébalo en línea!

Ørjan Johansen guardó 7 bytes usando un patrón irrefutable para forzar el prefijo.

xnor
fuente
55
Puede guardar 7 bytes haciéndolo más perezoso. Pruébalo en línea!
Ørjan Johansen
@ ØrjanJohansen Eso es increíble y el patrón perezoso es mágico para mí. ¿Quieres publicar tu propia respuesta?
xnor
No, estuviste la mayor parte del camino. Al usar n:al comienzo de la expresión, no necesita saber si xestá allí para producir la primera n. Pero necesita que el patrón sea perezoso para evitar que la función lo verifique antes de llegar al n:.
Ørjan Johansen
6

Gol> <> , 8 7 bytes

:{:PnKz

Pruébalo en línea!

Explicación

Este es un puerto de mi respuesta Wumpus . Gol> <> es básicamente el lenguaje que tiene todas las características necesarias para portar la respuesta Wumpus (específicamente, ceros implícitos en la parte inferior de la pila, "duplicado" implementado "pop, push, push" y un comando de rotación de pila), pero :

  • Tiene una cuadrícula toroidal, lo que significa que no necesitamos lo explícito 00.para volver al principio.
  • Tiene K, que es "pop N, luego duplica el siguiente elemento N veces", que puede reemplazar ?=, guardando otro byte.

Entonces el mapeo de Wumpus a Gol> <> se convierte en:

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

Lenguaje de programación Shakespeare , 594 583 572 bytes

¡Gracias a Ed Wynn por -10 bytes!

,.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!

Pruébalo en línea!

Esta es una versión de golf de la solución no adaptada de Ed Wynn , comenzando desde la solución de 828 bytes que vinculó en los comentarios y a partir de ahí.

Explicación:

,.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!
Jo King
fuente
¡Agradable! Puede guardar 7 bytes haciendo que el hijo único sea (-1 o 0) en lugar de los gemelos. Esto le cuesta 1 byte justo antes de la Escena X (cuando "Si es así" se convierte en "Si no"), y otro byte justo después del bucle de la Escena X (cuando "¿Soy mejor?" Se convierte en "¿Es mejor cero?"). El ahorro es que puede reemplazar el "¡Si no, recuerde! con simplemente "¡Recuerda yo!" Una línea antes. Insertamos un segundo hijo o un terminador de repuesto. (Esta es la razón por la que necesita cambiar el fino equilibrio "¿Soy más amable con usted?", Ya no puede confiar en Ford == 0 después de la Escena X). Aquí está TIO, 587 bytes: tinyurl.com/yb9zg4gp
Ed Wynn
Puede eliminar el primer "Si es así" en la Escena L y mover el comando al inicio de la Escena V. Esto le ahorra solo 1 byte, porque necesita un nuevo "Ford:". Pero guarda un par de bytes en la Escena I, siempre y cuando pueda confiar en que Ford se inicialice automáticamente en cero. No tiene derecho a confiar en esto, pero podría funcionar: aquí está TIO, 584 bytes: tinyurl.com/y9f6vy7u
Ed Wynn
5

> <> , 13 12 bytes

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

Pruébalo en línea!

Un puerto de la respuesta Wumpus de Martin Ender . Desafortunadamente, ><>no tiene un comando de incremento o de inversión ni tiene ceros implícitos en la parte inferior de la pila, por lo que esto termina siendo un poco más largo.

Jo King
fuente
1
Sí, esto es lo que tenía antes de recordar Gol> <>. :)
Martin Ender
5

JavaScript, 67 66 60 58 52 51 50 bytes

¡Bueno, eso hizo que mi cerebro picara más de lo que debería! Vuelve a ejecutar el ntérmino th, 0-indexado.

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

¡5 + 1 bytes guardados gracias a tsh rascando mi cerebro con picazón!


Pruébalo

El fragmento a continuación mostrará los primeros 50 términos.


Explicación

Esta es una de esas raras ocasiones en las que podemos declarar algunas variables fuera del alcance de nuestra función, modificarlas dentro de la función y aún así poder reutilizarlas en llamadas posteriores de la función.

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)
Lanudo
fuente
¿Qué pasan=>(g=s=>s[n]||g(s+(++x%2+1)*(10*s[x]-9)))('122',x=1)
Tsh
Por cierto, ¿se s='122',x=1,g=n=>s[n]||g(n,s+=(++x%2+1)*(10*s[x]-9))considera una presentación válida?
tsh
Gracias @tsh. s[n]||¡Era un caso claro de no ver la madera de los árboles! Sin embargo, su segunda sugerencia no sería válida, ya que la función solo se puede llamar una vez; s& xnecesita ser inicializado con cada llamada.
Shaggy
el segundo es reutilizable, siempre sy cuando xno sea tocado por otros códigos entre cada invocación (que es por defecto).
tsh
1
¡Agradable! s[x]+0-9es un truco bastante bueno
JollyJoker
4

Python (2 y 3), 65 60 bytes

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

Devuelve el n ° de entrada, 0-indexado.

Alternativa (65 bytes):

f=lambda n:n>1and sum([f(i)*[i%2+1]for i in range(n)],[])[n]or-~n
ManfP
fuente
3
Bienvenido a PPCG!
Martin Ender
1
Puede (probablemente, no lo probé) guardar 5 bytes en la versión alternativa utilizando [1,2,2]como valor inicial en elsum
Rod
4

Haskell , 48 bytes

-1 byte gracias a nimi. -2 bytes gracias a Lynn.

c=1:2:c
l=1:2:drop 2(id=<<zipWith replicate l c)

Pruébalo en línea!

Repita cada elemento su posición mod 2 + 1 veces.

totalmente humano
fuente
Puede guardar dos más definiendoc=1:2:c
Lynn el
4

brainfuck , 61 bytes

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

Pruébalo en línea!

Imprime números como códigos char indefinidamente. Para mayor claridad, aquí hay una versión que se imprime en números (excepto los dos primeros elementos, que son lo suficientemente fáciles de verificar).

Cómo funciona:

+.+. 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
]
Jo King
fuente
4

05AB1E , 12 9 bytes

Guardado 3 bytes gracias a Grimy

Imprime los primeros n elementos.

Δ2LÞsÅΓI∍

Pruébalo en línea!

Explicación

Δ           # 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
Emigna
fuente
La decodificación de longitud de ejecución ahora está incorporada, por lo que esto simplemente puede ser 2L[2LÞsÅΓ.
Grimmy
O aún mejor: ∞[2LÞsÅΓ.
Grimmy
O Δ2LÞsÅΓI∍para una versión que imprime los primeros n elementos con la entrada n.
Grimmy
@ Grimy: ¡Gracias! Me gusta la primera versión n ya que realmente termina :)
Emigna
3

05AB1E , 15 bytes

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

Pruébalo en línea! o con un límite de iteración

Explicación

Ƶ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
Emigna
fuente
En lugar de ¸«, =los imprimiría para 2 bytes guardados. ƵLS[NÌ©èF®É>=, no hay necesidad de engañar si no estás consumiendo.
Magic Octopus Urn
@MagicOctopusUrn: Sin embargo, no
produzco
3

J , 12 bytes

Función de argumento único que toma n y produce los primeros n términos. Pruébalo en línea!

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

Simplemente arreglando mi vieja respuesta a la vieja pregunta.

I.es un verbo que toma una matriz de números y escupe una lista de índices, de modo que si el k -ésimo elemento en la matriz es n , entonces el índice k aparece n veces. Lo usaremos para iniciar la secuencia de Kolakowski desde una semilla inicial. Cada paso procederá de la siguiente manera:

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) 

Si realizamos esta operación ( 1+2|I.) una y otra vez desde 10, se ve así:

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

Observe cómo obtenemos más y más términos correctos cada vez, y después de un tiempo los primeros n términos son fijos. El número de iteraciones que se necesitan para establecerse es difícil de describir con precisión, pero parece ser aproximadamente logarítmico en n , por lo que si lo ejecutamos n veces ( ^:]) debería estar bien. (Consulte estas otras secuencias OEIS para obtener más información: longitudes de generación , sumas parciales ).

Una vez que hayamos hecho eso, todo lo que tenemos que hacer es tomar los primeros n términos usando $. La construcción $vde cualquier verbo ves un ejemplo de un gancho, y si nse ejecuta como argumento se ejecutará n $ (v n).

Aquí está la vieja versión de 13 bytes, que es mucho menos desperdicio de tiempo y espacio: ($1+2|I.)^:_~. Trunca la entrada en cada paso, por lo que podemos ejecutar exactamente tantas veces como sea necesario para resolver, en lugar de muchas veces linealmente.

Algoritmo de tiburón
fuente
Oh, esto funciona perfectamente con I.. Siempre he querido ver la función de copia que se usa en algunos campos de golf.
millas
3

Fueue , 30 bytes

Fueue es un esolang basado en la cola en el que el programa en ejecución y sus datos están en la misma cola, la ejecución gira alrededor de la cola en ciclos y la programación requiere mucha sincronización para evitar que algo se ejecute en el momento equivocado.

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

Pruébalo en línea!

Lo anterior imprime una lista interminable de dígitos como códigos de control. Para 34 bytes, puede imprimir dígitos reales:

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

Pruébalo en línea!

El resto de la explicación usa la última versión.

Resumen de elementos de Fueue

La cola de Fueue puede contener el siguiente tipo de elementos:

  • Los enteros, que imprimen su punto de código Unicode cuando se ejecutan,
  • Bloques de subprograma delimitados por corchetes, que son misericordiosamente inactivos (solo se mueven al final de la cola) a menos que la )función los desbloquee , y
  • Funciones de un solo carácter, que se ejecutan si son seguidas por el tipo correcto de argumentos y permanecen inactivas de lo contrario.
    • Las únicas funciones utilizadas en este programa son ~(intercambiar dos elementos siguientes), :(duplicar el siguiente elemento) y )(desbloquear el siguiente bloque).

Resumen de alto nivel

Durante el ciclo principal del programa, la cola consiste en:

  • una cadena de bloques que representan dígitos para ser iterados;
    • Un dígito 1 o 2 está representado por los bloques [49]y [50:], respectivamente.
  • una sección de bucle principal autorreplicante que atraviesa los bloques de dígitos y coloca 1s y 2s alternos después de ellos, luego los desbloquea.
    • Un bloque de dígitos desbloqueado imprime su propio dígito d , y luego crea d copias del siguiente bloque, creando así los dígitos para la ejecución que describe.

Seguimiento de bajo nivel de los primeros 10 comandos

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:])~)~~

Tutorial de una iteración completa del bucle principal

Se ha insertado un espacio en blanco opcional para separar los comandos.

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

Ciclo 1: 49impresiones 1. )está inactivo, esperando ser reunido con el bloque de bucle principal. 50impresiones 2. :duplica el bloque del bucle principal (que necesita una copia para la autorreplicación)

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

Ciclo 2: )desbloquea el primer bloque del bucle principal, lo que hace que comience a ejecutarse el próximo ciclo.

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

Ciclo 3: [50:]representa el primer dígito producido en la cadena, 2aún no desbloqueado. Lo siguiente )finalmente lo hará después de que el resto del bucle principal lo haya atravesado. ~)~:~es un retraso de un ciclo de golf (usando un intercambio y una copia) de ~)~~. [[49]:~))~:~~]está inactivo ~intercambia el siguiente bloque de bucle principal más allá del [50:]bloque de dígitos.

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

Ciclo 4: )todavía espera, ~)~produce ~), ~intercambia más [[49]:~))~:~~]allá del [50:]bloque de dígitos.

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

Ciclo 5: ~intercambios más )allá del [50:]bloque de dígitos.

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

Ciclo 6: el primero )ahora desbloquea el [50:]bloque de dígitos, el siguiente )desbloquea el subprograma [[49]:~))~:~~].

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

Ciclo 7: 50imprime 2, :duplica el [49]bloque de dígitos recién producido , creando una serie de dos 1s. :~))~:~es un retraso de un ciclo de ~~))~:. ~intercambia el bloque de bucle principal restante más allá del primero [49].

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

Ciclo 8: ~~))es un retraso de un ciclo de )~). ~intercambia más :allá del recorrido actual [49].

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

Ciclo 9: ~intercambios )pasados [49]. :duplica el bloque del bucle principal.

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

Ciclo 10: el primero )desbloquea el [49]bloque de dígitos que acaba de atravesar, el segundo )reinicia el bucle principal para atravesar el siguiente (se muestra arriba al comienzo de la cola).

Ørjan Johansen
fuente
¡Buen trabajo! La razón por la que aprendí algo de Fueue y respondí al desafío HW porque en realidad lo busqué para este desafío, pero terminé siendo demasiado intimidado por la naturaleza basada en la cola. ¡Esa es una puntuación realmente buena para Fueue! :)
Martin Ender
3

x86, 41 37 35 33 28 bytes

Me divertí mucho jugando con diferentes instrucciones x86, ya que esta es mi primera respuesta x86 "no trivial". En realidad, aprendí x86-64 primero, y ahorré muchos bytes simplemente convirtiendo mi programa a 32 bits.

Resulta que el algoritmo que utilicé de OEIS empuja los valores a una matriz, lo que lo hace compatible con x86 y almacena valores en la pila (tenga en cuenta que MIPS no tiene instrucciones de pila).

Actualmente, el programa toma Nvalores como entrada ecxy devuelve una dirección ebpde una matriz con el enésimo elemento que representa el enésimo valor de la secuencia. Supongo que regresar a la pila y calcular valores adicionales es válido (de todos modos, consideramos lo que está más allá de la matriz como basura).

Registro de cambios

  • -4 bytes calculando x = 2 - n%2con xorcada iteración

  • -2 bytes usando do-while en lugar de while loop.

  • -2 bytes presionando los valores iniciales 1, 2, 2 usando eax

  • -5 bytes al no almacenar nexplícitamente y en su lugar ejecutar Ntiempos de bucle

.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 
qwr
fuente
3

C (gcc) , 72 71 65 64 62 bytes

-9 bytes gracias a @ceilingcat

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

Pruébalo en línea!

Genera valores de la secuencia indefinidamente (opción 3 del desafío)

vazt
fuente
¡Explicación por favor! No tengo idea de cómo funciona esto. No hay matriz! Y los números permanecen demasiado pequeños para contener uno como bits.
Ørjan Johansen
@ ØrjanJohansen Tengo que admitir que tampoco tengo idea de cómo funciona. :) Tomé la aplicación de pitón de OEIS A000002 , portado a C y que Jugamos al golf :)
vazt
Ah, pensé que podría haber sido algo allí, pero no busqué lo suficiente en esa página para encontrar el Python. Hay un enlace a una explicación , pero estaba un poco enterrado en la sección de enlaces. Este método definitivamente se ajusta a C al menos también.
Ørjan Johansen
1) 56 Bytes PHP: for($x=$y=-1;;$y=$y+1|$f&.5*$x^=$f=$y&-$y-2)echo$x&1?:2;. 2) 50-x%2debería guardar un byte para usted. 3) Traté de hacerlo funcionar con x=y=1; pero no podía hacer las operaciones bien hasta ahora. ¿Puedes?
Titus
2

Perl 5 , 36 bytes

Todavía una modificación trivial de la solución clásica de TPR (0,3):

Emite la serie de 0an

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

Pruébalo en línea!

Ton Hospel
fuente
2

Javascript ES6 - 71 70 68 bytes

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

1 bit ahorrado gracias a Neil

Gracias a Shaggy por corregir mi error, también por ahorrar 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>

Luis felipe De jesus Munoz
fuente
Esto parece un puerto de mi respuesta Java 8 (excepto en x=0lugar de x=1), pero @Shaggy tiene razón: esto no funciona en su forma actual (agregué ,i=100;i-->0temporalmente para ver los primeros 100 elementos, en lugar de tener que espere 60 segundos antes de ver una salida). Sin embargo, no tengo idea de por qué no funciona. JS no es lo mío.
Kevin Cruijssen
Los problemas son: 1.iniciar xa 0 en lugar de 1 (como mencionó @KevinCruijssen) y 2.verificar si el xcarácter th en la cadena, que solo puede ser 1 o 2, es mayor que 49.
Shaggy
2
Aquí hay una versión reducida (pero no completamente probada) de la solución fija: tio.run/…
Shaggy
(_[x]*10-9)que(_[x]>1?11:1)
l4m2
2

Manzana , 89 bytes

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

Define una función Kque no toma argumentos y devuelve la secuencia de Kolakoski como una lista infinita. Pruébalo en línea!

Este enfoque se inspiró en la respuesta de Haskell del totalmente humano . Mi enfoque original fue más largo y probablemente fue O (2 ^ n). : ^ P

Sin golf

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

La lista de retorno comienza con (1 2). Después de eso, para generar el resto (lectura de adentro hacia afuera):

  • Llama recursivamente (kolakoski)para obtener la lista de secuencias de Kolakoski (debido a una evaluación perezosa, no importa que la lista aún no se haya generado por completo)
  • (cycle (list 1 2)) crea una lista infinita (1 2 1 2 1 2 ...)
  • Comprime las dos listas infinitas juntas usando la función repeat-val. Esto repetirá 1o 2desde la cyclelista una o dos veces dependiendo del valor asociado en la lista de Kolakoski. Resultado:((1) (2 2) (1 1) ...)
  • flatten esa lista en (1 2 2 1 1 ...)
  • Ya tenemos los dos primeros términos (concat (list 1 2), así que droplos dos primeros de la lista generada para evitar la duplicación.
DLosc
fuente
2

Stax , 12 bytes

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

Ejecutar y depurarlo

Esta es la representación ascii del mismo programa.

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

Expande la secuencia x veces donde x es la entrada. Entonces se da salida a la x ésimo elemento, 0 indexados.

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

Aquí hay una solución adicional de 12 bytes que produce resultados como una secuencia infinita. Presione Ejecutar para comenzar.

recursivo
fuente
2

R, 63 bytes o 61 bytes

Aplicación 1: imprime el n º término de la secuencia.

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

Implementación 2: imprime los primeros n términos de la secuencia.

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 diferencia es solo en la última línea).

Sí, sí, puede quejarse de que mi solución es ineficiente, que calcula realmente más términos de los necesarios, pero aún así ...

Actualización: Gracias a @Giuseppe por reducir 9 bytes.

Andreï Kostyrka
fuente
1
use en a=c(a,rep(2-n%%2,a[n]))lugar del segundo forbucle para eliminar algunos bytes.
Giuseppe
@Giuseppe Implementado, ¡gracias!
Andreï Kostyrka
No nos importa las soluciones ineficientes para el golf aquí. De hecho, el uso de un algoritmo más ineficiente es uno de los consejos en el wiki de la etiqueta de código de golf .
Ørjan Johansen el
2

Lenguaje de programación Shakespeare, 575 bytes (pero defectuoso), o 653 o 623 bytes

,.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.

En la categoría SPL muy disputada, esto superaría la entrada actual de Jo King (583 bytes), excepto que es defectuoso: Primero, no se ejecuta en la versión TIO (implementando el sitio web SPL), pero se ejecuta en el Perl versión , así que tal vez no sea un defecto grave. En segundo lugar, sin embargo, no imprime los dos primeros dígitos. Si permitimos ese defecto en la solución de Jo King, entonces esa solución defectuosa sería de 553 bytes, superando a mi solución defectuosa.

Mi solución falla en TIO por dos razones: intentamos confiar en una pila vacía que devuelve cero cuando aparece; y pasamos a la primera escena, con "[Enter Ford and Puck]" aunque nadie haya salido del escenario. Estas son meras advertencias en la versión Perl. Si corrijo estos errores y pongo los dos primeros dígitos, llego a 653 bytes:

 ,.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.

Pruébalo en línea!

Puedo generar la secuencia completa en la implementación de Perl usando 623 bytes:

,.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.

Sin embargo, quisiera señalar que esta solución es rápida comparación con muchas otras soluciones y utiliza cantidades logarítmicas de memoria en lugar de almacenar toda la lista. (Esto es similar a la solución C de vazt, con la cual está relacionado de forma distante). Esto no hace ninguna diferencia para el golf, pero aún así estoy satisfecho. Puede generar un millón de dígitos en aproximadamente un minuto en Perl (por ejemplo, si canaliza a sed y wc para obtener un recuento de dígitos), donde la otra solución podría proporcionarle unos pocos miles de dígitos.

Explicación

Almacenamos una secuencia de variables en orden: la pila de Puck (de abajo hacia arriba), el valor de Puck, el valor de Ford, la pila de Ford (de arriba hacia abajo). Además de los valores cero en los extremos (con el cero a la izquierda tal vez por hacer estallar una pila vacía), cada valor es el dígito generado a continuación en esa generación, con 2 agregados si la próxima generación necesita tener otro hijo de ese padre. Cuando tenemos N valores distintos de cero en la secuencia, generamos todos los hijos hasta la generación N-ésima incluida, en una especie de recorrido de árbol de profundidad primero. Imprimimos valores solo de la enésima generación. Cuando la enésima generación se ha generado por completo, los valores almacenados son de hecho los valores iniciales para las generaciones 2 a (N + 1), por lo que agregamos un 2 a la izquierda y comenzamos de nuevo, esta vez generando el (N + 1 ) -th generación.

Entonces, un bosquejo: Escena X: Cuando llegamos aquí, este es el comienzo de un nuevo recorrido. Puck == 0. Opcionalmente, empujamos ese cero en la pila de Puck y establecemos Puck = 2. Escena L: Si Ford == 0, hemos alcanzado la generación de impresión. Si no, vaya a V. Para imprimir, si el valor en Puck ha agregado 2, elimine el 2 e imprímalo dos veces; si no, imprímalo una vez. Escena M: este es un bucle donde repetidamente alternamos el valor de Puck y volvemos a través de la secuencia. Repetimos hasta llegar al final (Puck == 0), en cuyo caso ir a X, o alcanzar un valor que necesite otro hijo (Puck> 2), en cuyo caso restar el 2 extra y avanzar en V. Escena V: Aquí vamos hacia adelante. Si Puck es 2 o 4, la próxima generación contendrá dos hijos del padre actual, por lo que Ford + = 2. Avanza por la secuencia. Pase a L para verificar la terminación.

Ed Wynn
fuente
1

axo , 13 bytes

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

Pruébalo en línea!

Explicación

Esto comenzó como un puerto de una solución alternativa en mi respuesta de Wumpus :

2%)[=]&=[O00.

Esto resultó en 18 bytes. Terminé jugando golf hasta los 13 bytes que ves arriba para ajustarlo más a la forma en que funciona axo. Esta versión de 13 bytes terminó inspirando la mejora hasta 11 bytes en Wumpus, por lo que ahora está más cerca de esa versión.

Al igual que en Wumpus, en la iteración i , la parte inferior de la pila contiene un (i) -1 y la parte superior contiene el primer elemento de la i ésima ejecución, pero estamos trabajando con 0 y 1 en todo momento, excepto para la impresión.

[:    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.
Martin Ender
fuente