Unpseudorandom

From Esolang
Jump to navigation Jump to search

Unpseudorandom is a language based on Unrandom, which provides a seed for generating brainfuck code randomly. However, in Unpseudorandom, the randomness is constrained to make meaningful programs more likely, and thus easier to construct. For example, Unrandom can generate ][, an invalid brainfuck program, unlike Unpseudorandom. Unpseudorandom code always ends in a ., never follows + or < with - or > respectively, and vice versa, and always generates [ and ] in pairs. It never follows a [...] block with another, and never generates a program with just a ..

A valid program consists of an string that the host language natively recognises as a single integer, which is used to seed the pseudorandom number generator. The code transpiles to brainfuck.

Whether the language is Turing complete depends on the random number generator used by the implementation. Speaking of implementations, here's a reference transpiler in Python 3.

'''Transpiler from Unpseudorandom to brainfuck'''
import random

def generate(seed, log_func=lambda *s: None):
    commands = [_left, _right, _up, _down, _in, _out, _around, _stop]
    random.seed(seed)
    code = ["@"]
    #replace @ symbols with more code
    while "@" in code:
        log_func(*code)
        where = code.index("@")
        new = random.choice(commands)("".join(code[:where]))
        code[where:where+1] = new
    code += "." #code that is after the last output of program is redundant
    log_func()
    return "".join(code)

#commands:
def _left(previous):
    if previous.endswith(">"):
        # >< is redundant
        return "@"
    return "<@"

def _right(previous):
    if previous.endswith("<"):
        # <> is redundant
        return "@"
    return ">@"

def _up(previous):
    if previous.endswith("-"):
        # -+ is redundant
        return "@"
    return "+@"

def _down(previous):
    if previous.endswith("+"):
        # +- is redundant
        return "@"
    return "-@"

def _in(previous):
    return ",@"

def _out(previous):
    return ".@"

def _around(previous):
    if previous.endswith("]"):
        # [...][...] is redundant
        return "@"
    return "[@]@"

def _stop(previous):
    if previous.endswith("["):
        # [] is redundant
        return "@"
    if previous == "":
        # no empty programs
        return "@"
    return ""

if __name__ == "__main__":
    seed = input("Enter seed:").strip()
    while seed.isnumeric():
        print(generate(int(seed), log_func=print))
        seed = input("Enter seed:")