Brainterpart
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())