TernLSB

From Esolang
Jump to navigation Jump to search

TernLSB is an esolang invented by User:None1, it uses Steganography to store its program.

How to write programs

To write a program in TernLSB, first write a program in brainfuck, then convert it into a sequence of ternary numbers using the table below. After that, add the ternary number 22 at the end of the sequence of ternary numbers which works like a string terminator.

Ternary representation brainfuck
00 +
01 -
02 ,
10 .
11 <
12 >
20 [
21 ]

Then assign the last two ternary bits with the ternary representation for every channel of every pixel in the image, starting from top-left, going right then restarting at the next line from the left. If the assigned result is larger than 255, then subtract it by 9.

Note: TernLSB programs have to be stored in a lossless compressed or uncompressed image type that uses RGB or RGBA color type (e.g.: BMP and PNG image type).

How to run programs

To run a TernLSB program, get the last two ternary bits for every channel of every pixel until you get 22, starting from top-left, going right then restarting at the next line from the left. Then recover the brainfuck program using the table above. Finally, execute the brainfuck program you get.

Example Programs

Hello World

Nope. interpreter

brainfuck interpreter

Inspired by dbfi.

Cat Program

Truth Machine

Polyglot Truth Machine

The following program behaves like a Truth Machine when running in either TernLSB or StegFuck.

Infinite fibonacci sequence

Made from this brainfuck program.

XKCD Random Number

Interpreter

Currently, the esolang has a Python interpreter (which is also an encoder for writing programs in the language), written by the author of the language (User:None1), it requires the Python Imaging Library.

#Usage:
#python tlsb.py <filename> - interpret a TernLSB program
#python tlsb.py <inputfn> <brainfuckfn> <outputfn> - Encodes brainfuck into an image file to make it a TernLSB program
import sys
from PIL import Image
def bf(code):
    s1=[]
    s2=[]
    matches={}
    tape=[0]*1000000
    for i,j in enumerate(code):
        if j=='[':
            s1.append(i)
        if j==']':
            m=s1.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]==',':
            tape[p]=ord(sys.stdin.read(1))%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
def run(fn):
    im=Image.open(fn)
    d=im.tobytes()
    fuck='+-,.<>[]'
    b=''
    for i in d:
        try:
            b+=fuck[i%9]
        except:
            break
    bf(b)
def enc(fn,b,o):
    im=Image.open(fn)
    fuck='+-,.<>[]'
    d=im.tobytes()
    d=list(d)
    w=''
    for i in b:
        if i in fuck:
            w+=i
    for i,j in enumerate(w):
        d[i]=d[i]//9
        d[i]=d[i]*9
        d[i]+=fuck.index(j)
        if d[i]>=256:
            d[i]-=9
    d[len(w)]=d[len(w)]//9*9+8
    if d[len(w)]>=256:
        d[len(w)]-=9
    db=bytes(d)
    Image.frombytes(im.mode,im.size,db).save(o)
    
if __name__=='__main__':
    a=sys.argv
    if len(a)==2:
        run(a[1])
    if len(a)==4:
        enc(a[1],open(a[2]).read(),a[3])
    if len(a) not in [2,4]:
        print('Must pass 1 or 3 arguments')

Turing completeness

The language is of course Turing complete since brainfuck is.

See also

  • StegFuck, a similar idea but uses binary bits instead of ternary ones.