Calcular a sequência de Kolakoski

54

Este é um reposicionamento de um antigo desafio , a fim de ajustar os requisitos de E / S aos nossos padrões recentes. Isso é feito em um esforço para permitir que mais idiomas participem de um desafio sobre essa sequência popular. Veja este meta post para uma discussão sobre o repost.

A sequência Kolakoski é uma sequência auto-referencial divertida, que tem a honra de ser a sequência OEIS A000002 (e é muito mais fácil de entender e implementar do que A000001). A sequência começa com um , consiste apenas de 1 s e 2 s e o elemento de sequência A (n) descreve o comprimento do n ° de execução de 1 s ou 2 s na sequcia. Isso define exclusivamente a sequência a ser (com uma visualização das execuções abaixo):

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

Sua tarefa é, é claro, implementar essa sequência. Você pode escolher um dos três formatos para fazer isso:

  1. Tomar uma entrada n e saída do n ésimo termo da sequência, em que n é iniciado quer a partir de 0 ou 1 .
  2. Tomar uma entrada n e saída os termos até e incluindo o n ésimo termo da sequência, em que n é iniciado quer a partir de 0 ou 1 (ou seja, quer imprimir a primeira n ou o primeiro n + 1 termos).
  3. Valores de saída da sequência indefinidamente.

No segundo e terceiro caso, você pode escolher qualquer formato de lista razoável e inequívoco. Tudo bem se não houver separador entre os elementos, pois eles sempre têm um único dígito por definição.

No terceiro caso, se o seu envio for uma função, você também poderá retornar uma lista infinita ou um gerador nos idiomas que os suportam.

Você pode escrever um programa ou uma função e usar qualquer um dos nossos métodos padrão de recebimento de entrada e saída. Observe que essas brechas são proibidas por padrão.

Isso é , então a resposta mais curta e válida - medida em bytes - vence.

Martin Ender
fonte
Relacionado , mas não um idiota.
Urna Mágica do Polvo
Generalização do problema , mas as otimizações provavelmente são possíveis, pois a parte inicial da sequência é corrigida.
Giuseppe
Enquanto estamos nisso, eu tenho outra generalização também .
Martin Ender

Respostas:

17

Geléia , 7 bytes

2Rṁxṁµ¡

Este é um programa completo que imprime os primeiros n termos.

Experimente online!

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

Exemplo de execução

Seja n = 5 .

A primeira invocação da cadeia se repete 1, 2 ciclicamente para atingir o comprimento 5 , depois cada elemento 5 vezes e, finalmente, trunca o resultado para o comprimento 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

Isso produz uma lista de comprimento 5 . O primeiro elemento é o primeiro elemento da sequência de Kolakoski.

A segunda invocação da cadeia repete 1, 2 ciclicamente para atingir o comprimento 5 , depois repete o k- ésimo elemento j vezes, onde j é o k- ésimo elemento da lista anterior e, finalmente, trunca o resultado para o comprimento 5 .

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

   1 2 1 2 1

Isso produz outra lista de comprimento 5 . Os dois primeiros elementos são os dois primeiros da sequência de Kolakoski.

O processo continua por mais três iterações.

   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

Estes são os cinco primeiros elementos da sequência de Kolakoski.

Dennis
fonte
12

Python 2 , 51 bytes

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

Imprime indefinidamente. Cria a lista à lmedida que é iterada. Para cada entrada xde l, anexa xcópias de 1ou 2, o que estiver oposto ao último elemento atual.

A principal dificuldade está em lidar com o fragmento auto-referencial inicial [1,2,2]. Este código apenas imprime a inicial 1,2e prossegue a partir daí. A impressão extra custa 12 bytes. Sem isso:

39 bytes , faltando as duas primeiras entradas:

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

Outra abordagem é inicializar especialmente as duas primeiras entradas. Inicializamos lcomo [0,0,2]para que as duas primeiras entradas não causem anexos, mas as print x or nfazem ser impressas como n.

51 bytes

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

Outra correção é inicializar l=[1], rastrear a alternância manualmente ne corrigir a impressão:

51 bytes

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

Sem o (l==[1,1])+, tudo funciona, exceto as seqüências impressas, em 1,1,2vez de 1,2,2. Tem que haver uma maneira melhor de reconhecer que estamos neste segundo passo.

E outra correção estranha, também de alguma forma a mesma contagem de bytes:

51 bytes

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

Wumpus , 13 11 bytes

=[=)O?=!00.

Experimente online!

Imprime a sequência indefinidamente sem separadores.

Estou genuinamente surpreso com o quão curto isso é.

Explicação

A idéia básica é manter a sequência na pilha e usar repetidamente o elemento mais baixo para gerar outra execução e imprimi-la. Estamos abusando efetivamente da pilha como uma fila aqui. Também podemos salvar alguns bytes trabalhando 0e 1(incrementando apenas para saída) em vez de 1e 2, porque dessa forma não precisamos inicializar explicitamente a pilha com ae 1podemos usar negação lógica para alternar entre os dois 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
fonte
10

Brachylog , 30 26 25 23 17 16 14 bytes

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

Produz os primeiros n valores. Usa a "variável de saída" .para entrada e as saídas para a "variável de entrada" ?. Experimente online!

Explicação

Estou muito feliz com o quão declarativo isso acabou: o programa é basicamente uma descrição de alto nível da lista de saída e sua relação com a 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}ᵐas listas de tentativas estão em ordem lexicográfica, a saída começará com 1.

Zgarb
fonte
9

Casca , 10 bytes

Ṡωo↑⁰`Ṙ¢ḣ2

Retorna os primeiros n valores. Experimente online!

Explicação

Ṡω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 a entrada 20, o processo é assim:

[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
fonte
11
Aqui está uma variação que imprime a sequência indefinidamente, a mesma contagem de bytes, mas talvez você veja algumas oportunidades de golfe que eu não experimentei online!
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 sem delimitador.

-3 bytes após uma dica indireta de @Neil .
-5 bytes graças a @MartinEnder .
-3 bytes convertendo Java 8 em Java 10.

Explicação:

Experimente online (o tempo limite é excedido após 60 segundos no 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
fonte
11
Eu gosto de como você fez isso parecer tão simples.
Erik the Outgolfer
@EriktheOutgolfer Thanks! :) Quando li o desafio, não sabia ao certo como começar, mas ele me atingiu (usando uma lista com a inicial [1,2,2]e depois a partir daí) e escrevi a resposta de 155 bytes (que agora é jogada usando uma String em vez de Lista).
Kevin Cruijssen
Por que não usar (3-i) vez de (1+i%2)?
Erik the Outgolfer
11
@EriktheOutgolfer porque i não é 1 ou 2, é o índice de strings.
Martin Ender
7

Gelatina , 10 bytes

’߀+\<¹SḂ‘

Retorna o n º prazo.

Experimente online!

Como 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
fonte
7

Haskell , 33 bytes

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

Experimente online!

Ørjan Johansen salvou 7 bytes usando um padrão irrefutável para forçar o prefixo.

xnor
fonte
5
Você pode salvar 7 bytes, tornando-o mais preguiçoso. Experimente online!
Ørjan Johansen
@ ØrjanJohansen Isso é incrível e o padrão preguiçoso é mágico para mim. Deseja postar sua própria resposta?
Xnor
Nah você estava a maior parte do caminho até lá. Ao usar n:no início da expressão, você não precisa saber o que xestá lá para produzir o primeiro n. Mas você precisa que o padrão seja preguiçoso para evitar que a função o verifique antes de chegar ao n:.
Ørjan Johansen
6

Gol> <> , 8 7 bytes

:{:PnKz

Experimente online!

Explicação

Esta é uma porta da minha resposta Wumpus . Gol> <> é basicamente o idioma que possui todos os recursos necessários para portar a resposta Wumpus (especificamente, zeros implícitos na parte inferior da pilha, "duplicado" implementado "pop, push, push" e um comando de rotação da pilha), mas :

  • Tem uma grade toroidal, o que significa que não precisamos da explícita 00. para voltar ao início.
  • Tem K, que é "pop N, em seguida, duplica o próximo elemento N vezes", que pode substituir ?=, salvando outro byte.

Assim, o mapeamento de Wumpus para Gol> <> se torna:

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

Linguagem de programação de Shakespeare , 594 583 572 bytes

Obrigado 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!

Experimente online!

Esta é uma versão em golfe da solução não destruída de Ed Wynn , começando pela solução de 828 bytes que ele vinculou nos comentários e ficando um pouco louca a partir daí.

Explicação:

,.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!
Brincadeira
fonte
Agradável! Você pode salvar 7 bytes, tornando o filho único ser (-1 ou 0) em vez dos gêmeos. Isso custa 1 byte antes da Cena X (quando "Se assim for" se torna "Se não") e outro byte logo após o loop da Cena X (quando "Estou melhor você" se torna "Estou melhor zero"). A economia é que você pode substituir o "Se não, lembre-se de você!" com simplesmente "Lembre-se!" uma linha antes. Nós inserimos um segundo filho ou um terminador sobressalente. (É por isso que você precisa alterar o equilibrado "Estou melhor?" - você não pode mais confiar na Ford == 0 após a cena X.) Aqui está o TIO, 587 bytes: tinyurl.com/yb9zg4gp
Ed Wynn
Você pode remover o primeiro "Em caso afirmativo" da Cena L e mover o comando para o início da Cena V. Isso economiza apenas 1 byte, pois você precisa de um novo "Ford:". Mas você salva alguns bytes na Cena I, desde que possa confiar que a Ford seja automaticamente inicializada com zero. Você não tem o direito de confiar nisto, mas pode funcionar: aqui está o TIO, 584 bytes: tinyurl.com/y9f6vy7u
Ed Wynn:
5

> <> , 13 12 bytes

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

Experimente online!

Um porto da resposta de Martin Ender Wumpus . Infelizmente, ><>não possui um comando incremental ou invertido, nem 0s implícitos na parte inferior da pilha; portanto, isso acaba sendo um pouco mais longo.

Brincadeira
fonte
11
Sim, é isso que eu tinha antes de me lembrar de Gol> <>. :)
Martin Ender
5

JavaScript, 67 66 60 58 52 51 50 bytes

Bem, isso fez meu cérebro coçar mais do que deveria! Retrocede o ntermo th, indexado a 0.

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

5 + 1 bytes salvos graças a tsh arranhando meu cérebro com coceira!


Teste-o

O snippet abaixo produzirá os 50 primeiros termos.


Explicação

Essa é uma daquelas raras ocasiões em que podemos declarar algumas variáveis ​​fora do escopo de nossa função, modificá-las dentro da função e ainda poder reutilizá-las em chamadas subseqüentes da função.

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)
Shaggy
fonte
Que taln=>(g=s=>s[n]||g(s+(++x%2+1)*(10*s[x]-9)))('122',x=1)
tsh
Btw, é s='122',x=1,g=n=>s[n]||g(n,s+=(++x%2+1)*(10*s[x]-9))considerado um envio válido?
tsh
Obrigado, @tsh. s[n]||foi um caso claro de não ver a madeira das árvores! Sua segunda sugestão não seria válida, porém, pois a função poderia ser chamada apenas uma vez; se xprecisa ser inicializado a cada chamada.
Shaggy
o segundo não ser reutilizável, enquanto se xnão tocado por outros códigos entre cada invoca (que é por padrão).
tsh
11
Agradável! s[x]+0-9é um truque bem arrumado
JollyJoker 07/03
4

Python (2 e 3), 65 60 bytes

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

Retorna o n º de entrada, 0-indexados.

Alternativa (65 bytes):

f=lambda n:n>1and sum([f(i)*[i%2+1]for i in range(n)],[])[n]or-~n
ManfP
fonte
3
Bem-vindo ao PPCG!
Martin Ender
11
Você pode (provavelmente, eu ainda não testei) salvar 5 bytes na versão alternativa usando [1,2,2]como valor inicial o #sum
Rod
4

Haskell , 48 bytes

-1 byte graças a nimi. -2 bytes graças a Lynn.

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

Experimente online!

Repita cada elemento sua posição mod 2 + 1 vezes.

totalmente humano
fonte
Você pode salvar mais dois , definindoc=1:2:c
Lynn
4

brainfuck , 61 bytes

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

Experimente online!

Imprime números como códigos de caracteres indefinidamente. Para maior clareza, aqui está uma versão que imprime em números (exceto os dois primeiros elementos, que são fáceis de verificar).

Como 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
]
Brincadeira
fonte
4

05AB1E , 12 9 bytes

Economizou 3 bytes graças ao Grimy

Imprime os primeiros n itens.

Δ2LÞsÅΓI∍

Experimente online!

Explicação

Δ           # 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
fonte
A decodificação no tamanho da execução agora é um built-in, então isso pode ser simplesmente 2L[2LÞsÅΓ.
Grimmy
Ou melhor ainda: ∞[2LÞsÅΓ.
Grimmy 13/06
Ou Δ2LÞsÅΓI∍para uma versão que imprime os primeiros n itens, com a entrada n.
Grimmy 13/06
@ Grimy: Obrigado! Eu gosto da primeira versão n, uma vez que realmente termina :)
Emigna 14/06
3

05AB1E , 15 bytes

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

Experimente online! ou com um limite de iteração

Explicação

Ƶ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
fonte
Em vez de ¸«, =os imprimiria por 2 bytes salvos. ƵLS[NÌ©èF®É>=, não há necessidade de enganar se você não está consumindo.
Magia Octopus Urna
@MagicOctopusUrn: Eu não produzir os primeiros 3 itens, porém, assim imprimindo infelizmente não trabalho
Emigna
3

Python 3 , 55 54 bytes

n=h=1;l=[]
while n:print(h);n^=3;h,*l=l+[n]*(l+[2])[0]

Experimente online!

ovs
fonte
3

J , 12 bytes

Função de argumento único, tomando n e produzindo os primeiros n termos. Experimente online!

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

Apenas enfeitando minha resposta antiga para a pergunta antiga.

I.é um verbo que pega uma matriz de números e cospe uma lista de índices, de modo que se o k -ésimo item da matriz for n , o índice k aparecerá n vezes. Vamos usá-lo para inicializar a sequência Kolakowski a partir de uma semente inicial. Cada etapa será da seguinte maneira:

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 executarmos esta operação ( 1+2|I.) repetidamente a partir de 10, será algo como isto:

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 como obtemos termos cada vez mais corretos a cada vez e, após algum tempo, os primeiros n termos são corrigidos. O número de iterações necessárias para se estabelecer é difícil de descrever com precisão, mas parece ser logarítmico em n , portanto, se a executarmos n vezes (^:] ), tudo ficará bem. (Confira essas outras sequências OEIS para obter mais informações: comprimentos de geração , somas parciais .)

Uma vez feito isso, tudo o que precisamos fazer é usar os primeiros n termos $. A construção$v de qualquer verbo vé um exemplo de gancho, e fornecê-lo ncomo argumento executarán $ (v n) .

Aqui é a velha versão de 13-byte que é muito menos desperdício de tempo e espaço: ($1+2|I.)^:_~. Ele trunca a entrada a cada etapa, para que possamos executar exatamente quantas vezes forem necessárias para resolver, em vez de linearmente várias vezes.

algoritmshark
fonte
Oh, isso funciona perfeitamente com I.. Eu sempre quis ver o recurso de cópia usado em algum golfe.
miles
3

Fueue , 30 bytes

Fueue é um esolang baseado em fila, no qual o programa em execução e seus dados estão ambos na mesma fila, a execução percorre a fila em ciclos e a programação requer muita sincronização para impedir que qualquer coisa seja executada no momento errado.

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

Experimente online!

O exemplo acima imprime uma lista interminável de dígitos como códigos de controle. Para 34 bytes, ele pode imprimir dígitos reais:

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

Experimente online!

O restante da explicação usa a última versão.

Resumo dos elementos Fueue

A fila do Fueue pode conter o seguinte tipo de elementos:

  • Inteiros, que imprimem seu ponto de código Unicode quando executados,
  • Blocos de subprograma delimitados por colchetes, que são misericordiosamente inativos (apenas passando para o final da fila), a menos que a )função os desbloqueie e
  • Funções de caractere único, que são executadas se forem seguidas pelo tipo certo de argumentos e permanecem inativas.
    • As únicas funções usadas neste programa são ~(trocar dois elementos a seguir), :(duplicar o próximo elemento) e )(desbloquear o bloco a seguir).

Visão geral de alto nível

Durante o loop principal do programa, a fila consiste em:

  • uma cadeia de blocos representando dígitos a serem iterados;
    • Um dígito 1 ou 2 é representado pelos blocos [49]e [50:], respectivamente.
  • uma seção de loop principal auto-replicante que atravessa os blocos de dígitos e coloca 1s e 2s alternados depois deles e os desbloqueia.
    • Um bloco de dígitos desbloqueado imprime seu próprio dígito d e cria d cópias do bloco a seguir, criando assim os dígitos para a execução descrita.

Rastreio de baixo nível dos 10 primeiros 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:])~)~~

Passo a passo de uma iteração de loop principal completa

Espaço em branco opcional foi inserido para separar comandos.

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

Ciclo 1: 49imprime 1. )está inativo, esperando para ser reunido com o bloco de loop principal. 50impressões 2. :duplica o bloco de loop principal (que precisa de uma cópia para auto-replicação).

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

Ciclo 2: )desbloqueia o primeiro bloco de loop principal, iniciando a execução do próximo ciclo.

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

Ciclo 3: [50:]representa o primeiro dígito produzido na cadeia, um 2ainda não desbloqueado. O seguinte )acabará por fazê-lo após o restante do loop principal. ~)~:~é um atraso de um ciclo de golfe (usando uma troca e uma cópia) de ~)~~. [[49]:~))~:~~]está inativo. ~troca o seguinte bloco de loop principal além do [50:]bloco de dígitos.

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

Ciclo 4: )ainda aguarda, ~)~produz ~), ~troca [[49]:~))~:~~]o [50:]bloco de dígitos.

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

Ciclo 5: ~swaps )passado, o [50:]bloco de dígitos.

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

Ciclo 6: o primeiro )agora desbloqueia o [50:]bloco de dígitos, o próximo )desbloqueia o subprograma [[49]:~))~:~~].

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

Ciclo 7: 50imprime 2, :duplica o [49]bloco de dígitos acabado de produzir , criando uma execução de dois 1s. :~))~:~é um atraso de um ciclo de ~~))~:. ~troca o bloco de loop principal restante pelo primeiro [49].

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

Ciclo 8: ~~))é um atraso de um ciclo de )~). ~swaps :além dos atualmente atravessados [49].

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

Ciclo 9: ~troca de )passado [49]. :duplica o bloco principal do loop.

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

Ciclo 10: o primeiro )desbloqueia o [49]bloco de dígitos que acabou de atravessar, o segundo )reinicia o loop principal para percorrer o próximo (acima, mostrado no início da fila).

Ørjan Johansen
fonte
Bom trabalho! O motivo pelo qual aprendi um pouco de Fueue e respondi ao desafio de HW porque realmente o procurei, mas acabei sendo intimidado pela natureza da fila. Essa é realmente uma ótima pontuação para o Fueue! :)
Martin Ender
3

x86, 41 37 35 33 28 bytes

Eu me diverti muito brincando com instruções x86 diferentes, pois esta é minha primeira resposta x86 "não trivial". Na verdade, eu aprendi o x86-64 primeiro e salvei muitos bytes apenas convertendo meu programa em 32 bits.

Acontece que o algoritmo que usei do OEIS envia valores para uma matriz, o que o torna passível de x86 e o ​​armazenamento de valores na pilha (observe que o MIPS não possui instruções de pilha).

Atualmente, o programa recebe Nvalores como entrada ecxe retorna um endereço em ebpuma matriz com o enésimo elemento que representa o enésimo valor na sequência. Presumo que retornar na pilha e calcular valores extras sejam válidos (consideramos o que está além da matriz como lixo de qualquer maneira).

Changelog

  • -4 bytes calculando x = 2 - n%2com xorcada iteração

  • -2 bytes usando do-while em vez de while loop.

  • -2 bytes pressionando os valores iniciais 1, 2, 2 usando eax

  • -5 bytes não armazenando nexplicitamente e executando Ntempos de loop

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

C (gcc) , 72 71 65 64 62 bytes

-9 bytes graças a @ceilingcat

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

Experimente online!

Gera valores da sequência indefinidamente (opção 3 do desafio)

vazt
fonte
Explicação, por favor! Não tenho ideia de como isso funciona. Não há matriz! E os números permanecem muito pequenos para conter um como bits.
Ørjan Johansen
@ ØrjanJohansen Devo admitir, também não tenho ideia de como isso funciona! :) Peguei a implementação python do OEIS A000002 , portou-a para C e
joguei
Ah, eu pensei que poderia ter sido algo lá, mas não parecia suficientemente longe nessa página para encontrar o Python. Há um link para uma explicação , mas foi um pouco enterrado na seção de links. Esse método definitivamente se encaixa em C pelo menos também.
Ørjan Johansen
1) 56 bytes em PHP: for($x=$y=-1;;$y=$y+1|$f&.5*$x^=$f=$y&-$y-2)echo$x&1?:2;. 2) 50-x%2deve salvar um byte para você. 3) Tentei fazê-lo funcionar x=y=1; mas não consegui acertar as operações até agora. Você pode?
Titus
2

Perl 5 , 36 bytes

Ainda uma modificação trivial da solução clássica de TPR (0,3):

Emite a série de 0paran

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

Experimente online!

Ton Hospel
fonte
2

Javascript ES6 - 71 70 68 bytes

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

1 bit economizado graças a Neil

Tanques para Shaggy por corrigir meu erro, também por economizar 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
fonte
Parece uma porta da minha resposta do Java 8 (exceto em x=0vez de x=1), mas o @Shaggy está certo: isso não funciona em sua forma atual (adicionei o ,i=100;i-->0temporariamente para ver apenas os 100 primeiros itens, em vez de precisar aguarde 60 segundos antes de ver uma saída). Mas não faço ideia por que não funciona. JS não é minha coisa.
Kevin Cruijssen 6/03/19
Os problemas são: 1.iniciar xa 0 em vez de 1 (como @KevinCruijssen mencionado) e 2.verificar se o xcaráter th na seqüência, o que só pode ser sempre 1 ou 2, é maior do que 49.
Shaggy
2
Aqui está uma versão golfed para baixo (mas não totalmente testado) da solução fixo: tio.run/...
Shaggy
(_[x]*10-9)então(_[x]>1?11:1)
l4m2 31/03/19
2

Appleseed , 89 bytes

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

Define uma função Kque não aceita argumentos e retorna a sequência Kolakoski como uma lista infinita. Experimente online!

Essa abordagem foi inspirada na resposta de Haskell, totalmente humana . Minha abordagem original foi mais longa e provavelmente foi O (2 ^ n). : ^ P

Ungolfed

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

A lista de retorno começa com (1 2). Depois disso, para gerar o restante (leitura de dentro para fora):

  • Chamada recursivamente (kolakoski) para obter a lista de sequências de Kolakoski (devido a uma avaliação lenta, não importa que a lista ainda não tenha sido totalmente gerada)
  • (cycle (list 1 2)) cria uma lista infinita (1 2 1 2 1 2 ...)
  • Zip os dois infinitas listas em conjunto, utilizando a função repeat-val. Isso repetirá a 1ou 2da cyclelista uma ou duas vezes, dependendo do valor associado na lista Kolakoski. Resultado:((1) (2 2) (1 1) ...)
  • flatten essa lista em (1 2 2 1 1 ...)
  • Já temos os dois primeiros termos (concat (list 1 2), portanto, dropos dois primeiros da lista gerada para evitar duplicação.
DLosc
fonte
2

Stax , 12 bytes

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

Execute e depure

Esta é a representação ascii do mesmo programa.

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

Ele expande a sequência x vezes em que x é a entrada. Em seguida, ele gera o x º elemento, indexado em 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

Aqui está uma solução bônus de 12 bytes que produz saída como um fluxo infinito. Pressione Executar para iniciar.

recursivo
fonte
2

R, 63 bytes ou 61 bytes

Implementação 1: imprime o n th termo da sequência.

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

Implementação 2: imprime os primeiros n termos da sequência.

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

(A diferença está apenas na última linha.)

Sim, sim, você pode reclamar que minha solução é ineficiente, que calcula realmente mais termos do que o necessário, mas ainda assim ...

Atualização: Obrigado a @ Giuseppe por cortar 9 bytes.

Andreï Kostyrka
fonte
11
use em a=c(a,rep(2-n%%2,a[n]))vez do segundo forloop para remover alguns bytes.
Giuseppe
@ Giuseppe Implementado, obrigado!
Andreï Kostyrka
Não nos importamos com ineficiência para soluções de golfe aqui. De fato, usar um algoritmo mais ineficiente é uma das dicas no wiki da tag code-golf .
Ørjan Johansen
2

Linguagem de programação de Shakespeare, 575 bytes (mas com defeito) ou 653 ou 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.

Na categoria SPL muito disputada, isso superaria a entrada atual de Jo King (583 bytes), exceto por estar com defeito: primeiro, não é executado na versão TIO (implementando o site do SPL) - mas é executado no Perl versão , então talvez esse não seja um defeito sério. Segundo, porém, ele não imprime os dois primeiros dígitos. Se permitíssemos esse defeito na solução de Jo King, essa solução defeituosa seria de 553 bytes, superando minha solução defeituosa.

Minha solução falha no TIO por dois motivos: tentamos confiar em uma pilha vazia retornando zero quando exibida; e nós vamos para a primeira cena, com "[Enter Ford and Puck]", mesmo que ninguém tenha saído do palco. Estes são meramente avisos na versão Perl. Se eu corrigir esses erros e colocar os dois primeiros dígitos, chegarei 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.

Experimente online!

Eu posso gerar a sequência completa na implementação 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.

No entanto, gostaria de salientar que esta solução é rápida em comparação com muitas outras soluções e usa quantidades logarítmicas de memória em vez de armazenar a lista inteira. (Isso é semelhante à solução C do vazt, à qual está distante.) Isso não faz diferença para o golfe, mas ainda assim estou satisfeito. Você pode gerar um milhão de dígitos em cerca de um minuto em Perl (por exemplo, se você canaliza para sed e wc para obter uma contagem de dígitos), onde a outra solução pode fornecer alguns milhares de dígitos.

Explicação

Armazenamos uma sequência de variáveis ​​em ordem: pilha de Puck (de baixo para cima), valor de Puck, valor de Ford, pilha de Ford (de cima para baixo). Além dos valores zero nas extremidades (com o zero à esquerda talvez de uma pilha vazia), cada valor é o dígito gerado a seguir nessa geração, com 2 adicionados se a próxima geração precisar ter outro filho desse pai. Quando temos N valores diferentes de zero na sequência, geramos todos os filhos até a N-ésima geração, inclusive em uma espécie de travessia de árvore em profundidade. Nós imprimimos valores somente da N-ésima geração. Quando a N-ésima geração é completamente gerada, os valores armazenados são, de fato, os valores iniciais das gerações 2 a (N + 1), portanto, adicionamos um 2 à esquerda e começamos novamente, desta vez gerando o (N + 1 ) -a geração.

Então, um esboço: Cena X: Quando chegamos aqui, este é o começo de uma nova travessia. Puck == 0. Opcionalmente, pressionamos esse zero na pilha de Puck e definimos Puck = 2. Cena L: Se Ford == 0, chegamos à geração de impressão. Caso contrário, vá para V. Para imprimir, se o valor em Puck tiver 2 adicionados, remova o 2 e imprima-o duas vezes; caso contrário, imprima-o uma vez. Cena M: Este é um loop em que alternamos repetidamente o valor de Puck e voltamos à sequência. Repetimos até chegarmos ao final (Puck == 0), nesse caso, ir para X, ou atingirmos um valor que precisa de outro filho (Puck> 2); nesse caso, subtrair os 2 extras e avançar na V. Cena V: Aqui vamos em frente. Se Puck for 2 ou 4, a próxima geração conterá dois filhos do pai atual, então Ford + = 2. Avance pela sequência. Vá para L para verificar o término.

Ed Wynn
fonte
1

axo , 13 bytes

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

Experimente online!

Explicação

Isso começou como uma porta de uma solução alternativa na minha resposta do Wumpus :

2%)[=]&=[O00.

Isso resultou em 18 bytes. Acabei jogando os 13 bytes que você vê acima para ajustá-lo mais à maneira como o axo funciona. Essa versão de 13 bytes acabou inspirando a melhoria de até 11 bytes no Wumpus, e agora está mais próxima dessa versão.

Como no Wumpus, na iteração i , a parte inferior da pilha contém a (i) -1 e a parte superior contém o primeiro elemento da i- ésima execução, mas estamos trabalhando com 0 e 1 , exceto a impressão.

[:    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
fonte