Kolakoski sequence

From Esolang
Jump to navigation Jump to search

The Kolakoski sequence is a sequence of 1's and 2's such that if you take the lengths of each run of the sequence, the result is the same as the original sequence. There are actually two sequences that fit this definition with their only difference being a 1 at the beginning. Its first 16 terms are:

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

There are a few different ways to generate the sequence, such as iteratively making bigger copies of the sequence from smaller ones or using a growing queue.

Examples

1+

(1|1\":##[#1](2|11+\":##[#11+](1)))

><>

>  >1}:n1-?!v1}v
^}2^!?-1n:}2<  <

Binary lambda calculus

A 0 bit corresponds to 1, and a 1 bit corresponds to 2.

  0    000 010    1   1    000    0    011 001    0
 11      0   0   00  01      0   01      0   1   01
  0    001 101    0   0    000    0    001 000    0
  0    1   0      1   1    0      1    1   0      0
 101   011 111   101 111   100   001   011 111   100

1   0 1       1 1       1 0   0 0   0 1       0 1   1
01111 101100001 011011111 00001 01101 111110111 00000 1 0

  0      101       111      0     0      000      1
 00        0         0     01    10        0     10
  1      110       001      0     0      000      1
  1      0         0        0     0      0        0
 101     100       000     101   100     000     110

Below is a breakdown of the expression.

ONE = λfirst. λsecond. first
TWO = λfirst. λsecond. second

INVERT item = item TWO ONE
CONS head tail = λf. f head tail

GENERATE = λqueue. λnext. (
  λhead. CONS head (
    GENERATE (
      λenqueue. queue (
        head (CONS next enqueue) (CONS next (CONS next enqueue))
      ) TWO
    ) (INVERT next)
  )
) (queue (λx. x) ONE)
MAIN = λ_. CONS ONE (CONS TWO (GENERATE (λenqueue. CONS TWO enqueue) ONE))

Bitdeque

In the deque, 1 is represented by a 1 bit, and 2 is represented by a 0 bit.

INVERT PUSH EJECT GOTO 6 INVERT PUSH INVERT PUSH EJECT GOTO 1 PUSH INVERT GOTO 1

Bitwise Cyclic Tag

In the data string, 1 is represented as 10 and 2 as 11. The initial data string is a single 2 (11), skipping the first 1, 2 of the sequence.

11100111001111011110

brainfuck

Uses two-pointers to work. It initializes the first 5 terms and adds the number that's different from the fast pointer value for slow pointer value times.

+++++++[>+++++++<-]>.+..-..[-] ; Print out "12211"
+>>>>++>>>>++>>>>+>+>>>+>>+<<<<<<<<<<<<<<<<<<< ; Store 1 2 2 1 1
                                               ;            s^ f^
+[ ; Infinite loop
    >>-[+>>>>-]+ ; Go to the slow pointer
    <[
        >>-[+>>>>-]+ ; Go to the fast pointer
        >>[>>>>]+++ ; Set top value to 3
        <<-[+<<<<-]+ ; Go back to the fast pointer
        <<[>>>+>[>>>>]<<<<-<<-[+<<<<-]+<<-] ; Set top value to 3 minus fast pointer value
        >>>[<<<+>>>-] ; Restore fast pointer value
        <<<[>>>>]<<<++++++[<++++++++>-]<. ; Output top value as character
        >++++++[<-------->-] ; Restore to number
        -[+<<<<-]+<- ; Decrement slow pointer value
    ]
    >>>[<<<+>>>-] ; Restore slow pointer value
    <-[+>>>>-]+ ; Go to the fast pointer
    [>>[>>>>]<<+<<<<-[+<<<<-]] ; Move fast pointer to top
    <-[+<<<<-]+[>>>>+<<<<-] ; Move slow pointer to the next
    >>-[+<<<<-]+ ; Move back to infinite loop flag
]

Another by User:Jan jelo:

cells:tmp|flag|tmp|tmp|tmp|term|preflag|lastflag|tmp|tmp|term|preflag|lastflag|tmp|tmp…
>+>>>>
+>+>+>>>
++>+>+>>>
++
[
 >
 [<<<<<]
 <<<<<<<<
 ++++++[->++++++++<]
 <<<[->>>>+<<<<]
 >>>>.
 <++++++[->--------<]
 >[-<<<<+>>>>]
 >>>>>>
 [->>>+>+<<<<]
 >>>>[-<<<<+>>>>]
 <[-<<<[<<<<<]>>+>>>>[>>>>>]>>]
 <<<[<<<<<]
 >>[
    -
    <[->>+>+<<<]
    >>[-<<+>>]
    >[->>>[>>>>>]>>>+[<<<<<]>>>>]
    >>>[>>>>>]+>>>>+<[<<<<<]
    >>
 ]
 +++<[->-<]
 >[-<+>]
 >>>>[>>>>>]+>>>>>-
 >>>>
]

And another 176-bytes one by User:Blashyrkh, with o(log n) memory consumption. Generation of first 26 million terms of the sequence uses only 132 memory cells and 6.12 billion operations. Here's the stripped version. Version with comments is available at User:Blashyrkh/Kolakoski-brainfuck.

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

FALSE

This stores the queue as a pair of integers, one containing the actual data in bits, and the other being used as the "enqueue pointer".

[@$2*\@*@+]n:  {enqueue}
[\2/\$2/\1&]d: {dequeue}
1 0            {initialize queue}
[0~][0n;!d;!$1+._[0n;!]?1n;!d;!$1+._[1n;!]?]#

This program instead stores the queue elements in the stack and uses ø to dequeue.

{queue is stored as <discarded elements>, <queue elements>, <queue length>}
[\1+]n:    {enqueue}
[1-$1+ø]d: {dequeue}
0 {initialize queue}
[0 0=][1n;!d;!$.2=[1n;!]?2n;!d;!$.2=[2n;!]?]#

This interpreter has a handful more commands, but the roll n command "®" is quite helpful here.

1q:{current}
0h:{height}
 [0 0=][
 q;{push}
 h;1+®{pop bottom}
 $.", "{output}
 2={popped == 2?}
 [
  q;{push another}
  h;1+h:{increment h}
 ]?
 3q;-q:{3 - q -> q}
]#{do forever!}

Kawa

Raw text version at Kawa/Raw programs#Kolakoski sequence

Lazy K

`k```s`s````ssi`s`k`s``s`ks``s``s`ks``s`k`s`k``s``s`ks``s`k`si``s`s`kk`k`sk``s`si`kk````ssi`s`k`s``s`ks``s``s``s`s`k`s`s`ks`k`k`k`k`sk`kk`k``s`k`s``ss`k`k`skk``s`k`s``s`ks``s`s`k``s```sik```ss`ss`kk``s`ks``s`k`sik`kk``s``s`ks``s`s`kki`k``si`k`sk`k``s`k`s`k``s```sss`ks`kk``s``s`ks``s`k`s`k``s`ks`s`k``s`ks``s`k`sik``s``s`ks``s`k`s`k``s`ks``s`k`sik``s`k`s````ssi`s`k`s``s`ks``s``s``s`s`k`s`s`ks`k`k`k`k`sk`kk`k``s`k`s``ss`k`k`skk``s`k`s``s`ks``s`s`k``s```sik```ss`ss`kk``s`ks``s`k`sik`kk``s``s`ks``s`s`kki`k``si`k`skk`kk```ss``ss``ss`s``si`k`sk`kk``s`kk``s`kk``s`s`k`s`k`s`k``s`k``s`k`s``s`k``s`ks``s`k`sik``s``si`k```si``si``s`s``s`k``s`ksk``s``sski```sski`s``s`ksk`k```si``s`s``s`k``s`ksk``s``sski```sski`s``s`kskkkiki

This is the result of "compilation" of the following lambda calculus code (preamble with definition of car/cdr/nil/etc... is omitted):

pushpop   = lambda q p . (lambda q f . f (cdr q) (car q)) (append q p)
onestep   = lambda q p . pushpop q p (lambda q x f . f (x (append q p) q) (not p) x)
kolakoski = (lambda f input . f f nil false) lambda self q p . onestep q p (lambda q p x . cons (x 50 49) (self self q p))

One can see that it's just the python example (see below) rewritten in functional paradigm.

MoreMathRPN

"p
1
"do
 "q.append(p)
 >> 0
 "x = q.pop(0)
 #
 -> ]0
 del 1
 "yield x
 >> 0
 outputV
 outputS ", "
 "if x == 2
 -3
 *
 7
 +
 jmp ]0
  del 0
  "q.append(p)
  >> 0
  jmp 2
 del 0
 "p = 3 - p
 3
 -> 1
 -
"while true
jmp -19

Muriel

S:"@\"S:\\\"\"+|S+\"\\\";\\nK:\\\"\"+K+$f+(%$f,0,(2=#(%K,i+2,i+3)))+\"\\\";\\nf:\"+$(3-f)+\";i:\"+$(i+1)+\";\\n.%K,i,i+1;\\n\"+S";
K:"122";
f:1;i:0;
.%K,i,i+1;
@"S:\""+|S+"\";\nK:\""+K+$f+(%$f,0,(2=#(%K,i+2,i+3)))+"\";\nf:"+$(3-f)+";i:"+$(i+1)+";\n.%K,i,i+1;\n"+S

Post correspondence problem

These two are listed in the OEIS entry (they're mentioned as fixed points of substitutions, which are equivalent):

11 12
12 122
21 112
22 1122

This one skips the first 1:

11 21
12 211
21 221
22 2211

Python 3

def kolakoski():
    q, p = [], 1
    while True:
        q.append(p)
        yield (x := q.pop(0))
        if x == 2:
            q.append(p)
        p = 3 - p

Another one:

k=[1,2,2]
i=2
while True:
  print(k[i-2])
  k+=[3-k[-1]]*k[i]
  i+=1

Tag system

Here, 1 is encoded as abc and 2 is encoded as ababc. The initial word is a single 2, skipping the first 1, 2 of the sequence.

Tag system 
    m: 2
    A: {a,b,c} 
    P:
        a  -->  abc
        b  -->  ababc
        c  -->  

Computation
    Initial word: ababc
                    abcabc
                      cabcabc
                        bcabc
                          abcababc
                            cababcabc
                              ...

Thue

[1>]1::=1[1>]
[1>]2::=2[1>]
[1>]*1::=[<1]1*[a1>]
[1>]*2::=[<1]2*[a1>][a1>]

(1)::=~1
(2)::=~2

1[<1]::=[<1]1
2[<1]::=[<1]2
>[<1]1::=1>[2>](1)
>[<1]2::=2>[2>](2)

[a1>]1::=1[a1>]
[a1>]2::=2[a1>]
[a1>]|::=1|

[2>]1::=1[2>]
[2>]2::=2[2>]
[2>]*1::=[<2]1*[a2>]
[2>]*2::=[<2]2*[a2>][a2>]

1[<2]::=[<2]1
2[<2]::=[<2]2
>[<2]1::=1>[1>](1)
>[<2]2::=2>[1>](2)

[a2>]1::=1[a2>]
[a2>]2::=2[a2>]
[a2>]|::=2|

::=

|>[1>]12*2|

Uiua

⍢(↘1⊂:↙:⊂.⊂[]-:3⊣,⊡2.&pf⊢.|1)[1 2 2]

External resources