We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

K-Pointers Cycle Machine

From Esolang
Jump to navigation Jump to search

K-Pointers Cycle Machine is an esoteric programming language created by User:Rainwave in 2026. It is the successor to Rainwave's unpublished Two Worlds, a brainfuck-like language that uses two tapes and two pointers. K-Pointers Cycle Machine operates on an infinite bit tape using multiple pointers, with its defining operation being the cyclic copying of data between pointers, from which it derives its name.

Memory model

The language operates on a bidirectionally infinite tape of cells.

Each cell stores a single bit, either 0 or 1.

A program may initialize a finite subset of the tape. Every cell that is not explicitly initialized contains 0.

Pointers

A program places one or more pointers onto the tape.

Let K denote the number of pointers.

Pointers are numbered from 0 to K−1. Multiple pointers may occupy the same tape cell.

At any point during execution, exactly one pointer is active.

Initially, pointer 0 is active.

After pointer P has taken its turn, the next active pointer is

Execution

Suppose the active pointer is P.

During its turn:

  1. Read the bit under pointer P.
  2. If the bit is 0, move pointer P one cell to the left.
  3. Otherwise, move pointer P one cell to the right.
  4. Perform a cyclic copy on every other pointer.

The cyclic copy is performed in the following order:

For each pointer p in this sequence, copy the value stored under pointer to the cell currently under pointer p.

The active pointer itself is excluded from this copying process.

Example interpreter

The following Python implementation demonstrates the execution model.

The two variables of interest are:

  • code, which specifies the finite initialized portion of the tape.
  • pointers, which specifies the initial locations of the pointers.

Pointer positions use 0-based indexing. Thus, a pointer value of 0 refers to the first element of code.

import optparse

code = list('0011')
pointers: list[int] = [0, 1, 3, 0]
K = len(pointers)
p = 0

parser = optparse.OptionParser()
parser.add_option(
    "-l", "--limit",
    type=int,
    dest="limit",
    help="Limits the number of iterations"
)
parser.add_option(
    "-w", "--wait",
    default=False,
    action="store_true",
    dest="wait",
    help="Wait for input between each step"
)
parser.add_option(
    "-m", "--multiple",
    type=int,
    dest="multiple",
    help="Only display the state when the step counter is a multiple of the argument"
)
(options, args) = parser.parse_args()

assert K > 0


def init():
    global code, pointers

    pad = max(0, -min(pointers))
    code = list('0' * pad) + code

    for i in range(len(pointers)):
        pointers[i] += pad

    rem = max(0, max(pointers) - len(code) + 1)
    code += list('0' * rem)

def display():
    width = max(1, len(str(K - 1)))

    print("    CODE | ", end="")
    for c in code:
        print(c.rjust(width), end="")
    print()

    cols = []
    rows = 0
    for i in range(len(code)):
        ps = [str(j) for j, k in enumerate(pointers) if k == i]
        cols.append(ps)
        rows = max(rows, len(ps))

    for r in range(rows):
        if r == 0:
            print("POINTERS | ", end="")
        else:
            print("         | ", end="")

        for ps in cols:
            if r < len(ps):
                print(ps[r].rjust(width), end="")
            else:
                print(" " * width, end="")
        print()

    print(f"       P | {p}")
    print()

def advance():
    global p, code

    if code[pointers[p]] == '1':
        pointers[p] += 1
    else:
        pointers[p] -= 1

    if pointers[p] >= len(code):
        code += '0'

    if pointers[p] < 0:
        code = list('0') + code
        for i in range(len(pointers)):
            pointers[i] += 1

    for i in range(1, K):
        code[pointers[(p + i) % K]] = code[pointers[(p + i + 1) % K]]

    p = (p + 1) % K


def main():
    init()

    mxstep = options.limit
    multiple = options.multiple
    step = 0

    if mxstep is None:
        mxstep = -1

    if multiple is None:
        multiple = 1

    while step < mxstep:
        if step % multiple == 0:
            print(f"STEP #{step}")
            display()

        advance()
        step += 1

        if options.wait:
            input()


if __name__ == '__main__':
    main()

Running the interpreter

Save the interpreter as kpcm.py and execute it with

python kpcm.py -l 50

The -l option limits the number of execution steps.

Additional command-line options are:

  • -w — wait for user input between steps.
  • -m N — display the machine state only every N steps.