NucleotideBF (nBF)

From Esolang
Jump to navigation Jump to search

NucleotideBF (nBF) is created by Maurice Ling which is a derivative of Brainfuck based on IUPAC nucleotide code. It uses only 5 of the 8 operations in Brainfuck, and there is no loop operations.

The commands for nBF can be divided into 2 classes - deterministic operations and random operations. The deterministic operations are A (increment), T (decrement), C (backward), and G (forward).

Based on the same interpreter as Loose Circular Brainfuck (LCBF), the tape or array is circular (a ring list) instead of linear. When the pointer is at the "end" of the tape, an increment ("A") will move the tape to the start. Similarly, when the pointer is decremented at the "beginning" of the tape, the pointer goes to the end.

nBF Command Brainfuck command Description
G > Move the pointer to the right
C < Move the pointer to the left
A + Increment the memory cell under the pointer
T - Decrement the memory cell under the pointer
. . Output the character signified by the cell at the pointer
R Random between A or G
Y Random between C or T
S Random between G or C
W Random between A or T
K Random between G or T
M Random between A or C
B Random between C or G or T
D Random between A or G or T
H Random between A or C or T
V Random between A or C or G
N Random between A or T or C or G

Python Implementation

    import random
    
    def increment(array, apointer, inputdata, output, source, spointer):
        array[apointer] = array[apointer] + 1
        return (array, apointer, inputdata, output, source, spointer)
    
    def decrement(array, apointer, inputdata, output, source, spointer):
        array[apointer] = array[apointer] - 1
        return (array, apointer, inputdata, output, source, spointer)
    
    def forward(array, apointer, inputdata, output, source, spointer):
        return (array, apointer + 1, inputdata, output, source, spointer)
    
    def backward(array, apointer, inputdata, output, source, spointer):
        return (array, apointer - 1, inputdata, output, source, spointer)
    
    def call_out(array, apointer, inputdata, output, source, spointer):
        output.append(array[apointer])
        return (array, apointer, inputdata, output, source, spointer)
    
    def random_op(array, apointer, inputdata, output, source, spointer):
        r = random.random()
        if source[spointer] == 'R' and r < 0.5:
            return increment(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'R' and r >= 0.5:
            if (apointer + 1) == len(array): 
                return (array, 0, inputdata, output, source, spointer)
            else:
                return forward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'Y' and r < 0.5:
            return decrement(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'Y' and r >= 0.5:
            if apointer == 0: 
                return (array, len(array) - 1, inputdata, output, source, spointer)
            else:
                return backward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'S' and r < 0.5:
            if (apointer + 1) == len(array): 
                return (array, 0, inputdata, output, source, spointer)
            else:
                return forward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'S' and r >= 0.5:
            if apointer == 0:
                return (array, len(array) - 1, inputdata, output, source, spointer)
            else:
                return backward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'W' and r < 0.5:
            return increment(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'W' and r >= 0.5:
            return decrement(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'K' and r < 0.5:
            return decrement(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'K' and r >= 0.5:
            if (apointer + 1) == len(array): 
                return (array, 0, inputdata, output, source, spointer)
            else:
                return forward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'M' and r < 0.5:
            return increment(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'M' and r >= 0.5:
            if apointer == 0: 
                return (array, len(array) - 1, inputdata, output, source, spointer)
            else:
                return backward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'B' and r < 0.33:
            if (apointer + 1) == len(array): 
                return (array, 0, inputdata, output, source, spointer)
            else:
                return forward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'B' and r >= 0.33 and r < 0.67:
            return decrement(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'B' and r >= 0.67:
            if apointer == 0:
                return (array, len(array) - 1, inputdata, output, source, spointer)
            else:
                return backward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'D' and r < 0.33:
            return increment(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'D' and r >= 0.33 and r < 0.67:
            return decrement(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'D' and r >= 0.67:
            if (apointer + 1) == len(array):
                return (array, 0, inputdata, output, source, spointer)
            else:
                return forward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'H' and r < 0.33:
            return increment(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'H' and r >= 0.33 and r < 0.67:
            return decrement(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'H' and r >= 0.67:
            if apointer == 0:
                return (array, len(array) - 1, inputdata, output, source, spointer)
            else:
                return backward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'V' and r < 0.33:
            return increment(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'V' and r >= 0.33 and r < 0.67:
            if (apointer + 1) == len(array):
                return (array, 0, inputdata, output, source, spointer)
            else:
                return forward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'V' and r >= 0.67:
            if apointer == 0:
                return (array, len(array) - 1, inputdata, output, source, spointer)
            else:
                return backward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'N' and r < 0.25:
            return increment(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'N' and r >= 0.25 and r < 0.5:
            return decrement(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'N' and r >= 0.5 and r < 0.75:
            if (apointer + 1) == len(array): 
                return (array, 0, inputdata, output, source, spointer)
            else:
                return forward(array, apointer, inputdata, output, source, spointer)
        elif source[spointer] == 'N' and r >= 0.75:
            if apointer == 0:
                return (array, len(array) - 1, inputdata, output, source, spointer)
            else:
                return backward(array, apointer, inputdata, output, source, spointer)
    
    
    
    nBF = {'A': increment,
           'T': decrement,
           'G': forward,
           'C': backward,
           'R': random_op,
           'Y': random_op,
           'S': random_op,
           'W': random_op,
           'K': random_op,
           'M': random_op,     
           'B': random_op,
           'D': random_op,
           'H': random_op,
           'V': random_op,
           'N': random_op,
           '.': call_out
           }
    
    def interpret(source, functions,
                 function_size=1, inputdata=[],
                 array=None, size=30):
        spointer = 0
        apointer = 0
        output = list()
        if array == None:
            array = [0] * size
        if len(array) > size:
            array = array[0:size]
        if len(source) % function_size != 0:
            source = source + '!'*(function_size - \
                                   len(source) % function_size)
        tokens = functions.keys()
        source = ''.join([x for x in source if x in tokens])
        while spointer < len(source):
            try:
                token = source[spointer:spointer+function_size]
                (array, apointer, inputdata, output,
                     source, spointer) = functions[token](array, apointer,
                                                          inputdata, output,
                                                          source, spointer)
            except KeyError:
                print ' '.join(['Unknown function: ',
                                source[i:i+function_size],
                                'at source position',
                                str(i)])
            if apointer > size:
                apointer = apointer - size
            if apointer < 0:
                apointer = size + apointer
            spointer = spointer + function_size
        return (array, apointer, inputdata, output, source, spointer)
    
    if __name__ == '__main__':
        print interpret('AAAAGGTTTCAAA', nBF)
        print interpret('AAAAGGTTTCAAARRYYSKVDVDBBHVNVH', nBF)