Brainterpart

From Esolang
Jump to navigation Jump to search

Brainterpart is an esolang invented by User:None1, inspired by brainfuck, it is the counterpart of brainfuck without comments.

Definitions

Define the brainfuck charset (BC for short) as +,-.<>[].

Define the non-brainfuck charset (NBC for short) as the charset which contains characters that aren't in BC with ASCII values between 33 and 126 (! to ~, inclusive).

Define brainfuck string as a string that only consists of characters in BC.

Define non-brainfuck string as a string that only consists of characters in NBC.

Define the string number of a string in a charset of length N+1 as the result of replacing each character with a base-N+1 digit. (e.g.: The string number of the brainfuck string +. is (14)8=12).

Programs

Programs in brainterpart are non-brainfuck strings, which are converted to brainfuck strings when executing.

Let A be the infinite sequence of brainfuck strings sorted by their string number.

Let B be the infinite sequence of non-brainfuck strings sorted by their string number.

The conversion is a mapping from A to B:

A: !  "  #  $  %  &  '  (  )  *  ...
   ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
B: +  ,  -  .  <  >  [  ]  ++ +, ...

Examples

Though not originally intended for golfing, programs in Brainterpart are significantly shorter than their original brainfuck program. As such, Brainterpart can be used for golfing.

Print a null character

$

Hello, world!

!8?IrPRFn}=6_A}XgM)pijBvh/3PMF/'nOuBs(9w=NNhX!_fKT

Cat

!^4

A+B Problem

#K2PDvL~khq`7lkk!R=ypszEz#X?MS{{00L5ZtlUFgk{v2~FjtyRBHFHI*Zzl1$)gLV?\&5~=FBLHLXq@b/93}g~%?lm{e1:$n"&vVpbED9tuY3:;g24)Mp/mv'mcGe4i*dEK)yegd'u#5OpJC8C:NCi:B!s#eodKkr"zTz\96mX

XKCD Random Number

DO`|&QQO8tt

Infinite loop

!P

One Time Cat

8

Interpreter

Python

Also a brainfuck ↔ Brainterpart converter.

import sys

BC = "+,-.<>[]"
NBC = "!\"#$%&'()*/0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz{|}~"


def atonum(a, cs):
    r, p = 0, 1
    for i in a:
        r += p
        p *= cs
    z = 0
    for i in a:
        z = z * cs + i - 1
    return r + z


def numtoa(num, cs):
    p, w = 1, 0
    while num >= 0:
        num -= p
        p *= cs
        w += 1
    num += p
    p //= cs
    w -= 1
    res = []
    for i in range(w):
        res.append(num % cs + 1)
        num //= cs
    return list(reversed(res))


ctoa = lambda c, cs: [cs.index(i) + 1 for i in c]

atoc = lambda a, cs: "".join(cs[i - 1] for i in a)


def bp2b(bp):
    return atoc(numtoa(atonum(ctoa(bp, NBC), len(NBC)), len(BC)), BC)


def b2bp(bp):
    return atoc(numtoa(atonum(ctoa(bp, BC), len(BC)), len(NBC)), NBC)


def bf(code):
    s = []
    matches = {}
    tape = [0] * 1000000
    for i, j in enumerate(code):
        if j == "[":
            s.append(i)
        if j == "]":
            m = s.pop()
            matches[m] = i
            matches[i] = m
    cp = 0
    p = 0
    while cp < len(code):
        if code[cp] == "+":
            tape[p] = (tape[p] + 1) % 256
        if code[cp] == "-":
            tape[p] = (tape[p] - 1) % 256
        if code[cp] == ",":
            c = sys.stdin.read(1)
            tape[p] = (ord(c) if c else 0) % 256
        if code[cp] == ".":
            print(chr(tape[p]), end="")
        if code[cp] == "<":
            p -= 1
        if code[cp] == ">":
            p += 1
        if code[cp] == "[":
            if not tape[p]:
                cp = matches[cp]
        if code[cp] == "]":
            if tape[p]:
                cp = matches[cp]
        cp += 1


brainterpart = lambda code: bf(bp2b(code))
if __name__ == "__main__":
    brainterpart(input())