We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

2DFIM

From Esolang
Jump to navigation Jump to search
This language is a derivative of Ultimate bf instruction minimalization!.

2DFIM, also called 2dfim, is a language which arguably has only two "real" instructions, though you could argue it has up to 4 instructions including no-op and newline. It is intended to be an extremely literal translation of the idea behind Ultimate bf instruction minimalization! in two dimensions by turning the skip command into a "go down one" command.

Specification

If the leftmost cell of the memory is the "first" cell, the pointer starts at the third cell, with the second cell doing input or output when set to 1 based on whether the 4th-11th cells are all 0 (input) or not (output). That second cell is set to 0 after this occurs. The tape is left-bounded.

The instruction pointer starts at the first (topmost) row of the first (leftmost) column. Once it hits the rightmost end of that line of the program (the newline), if the bit under the code pointer is 1, the instruction pointer goes back around to the first column of that line of the program. If the bit is zero, the program ends. However, if the instruction pointer is at the lowest row and ( flips a bit to zero, the instruction pointer goes to the first row of that column without checking the bit underneath the code pointer.

Instructions
Instruction Effect
< If the code pointer is currently over the first bit, do nothing.
Otherwise, move the code pointer one cell to the left.
Regardless, move the instruction pointer one character to the right.
( Move the code pointer to the next bit and flip it.
If the bit is zero now, move the instruction pointer one character down.
Otherwise, move the instruction pointer one character to the right.
(newline) if the cell under the code pointer is 1, move the instruction pointer back to the instruction after the previous newline or to the beginning of the file if this is the first newline in the file.
Otherwise, end the program.
(anything else / no-op) Move the instruction pointer one character to the right.

Code Examples

Infinite Loop

The following is still an infinite loop:

(

This specific infinite loop program works on any tape because if the cell was already 1, the instruction pointer goes "down" to the same row and hits the same instruction again, making it go to another cell until it turns something to 1 before it hits the end of the loop.

Cat Program

This is a single-character cat program.

(<( This pattern ensures the cell is 0.
  (<(
    (<(
      (<(
        (<(
          (<(
            (<(
              (<(
<<<<<<<<<<<<    (( does nothing the first round, takes input the second round, outputs character the third round

This is an actual cat program which works for multiple inputs, though it can sometimes have issues when a null character is entered as input:

<(<(                               < This line preemptively ensures Cell 3 always starts at 0 in the input/output loop.
   (<( This pattern ensures the cell is 0.
     (<(
       (<(
         (<(
           (<( 
             (<(
               (<(
                 (<(
                   <<<<<<<<<<(<(((<( By the end of this line, Cell 3 will always be 1 so it can loop at the rightmost edge of the first line.

This is a more compact version (half as tall).

<(<(       (<(                     <
   (<(       (<(
     (<(       (<(
       (<(       (<(
         (<(       <<<<<<<<<<(<(((<(

Implementations

I believe this implementation in Python works:

def run_2dfim(code_string, file_name=False, input_string=''):
    code = []
    memory = [False] * 11
    if file_name:
        for line in open(code_string, 'r'):
            code.append(line.rstrip('\n'))
    else:
        code = code_string.split('\n')
    max_columns = max([len(line) for line in code])
    max_rows = len(code)
    pointer = (0, 0)
    cell = 2
    while True:
        row, column = pointer[0], pointer[1]
        if column < len(code[row]) and code[row][column] in '<(':
            instruction = code[row][column]
            if instruction == '<':
                if cell != 0:
                    cell -= 1
            elif instruction == '(':
                cell += 1
                if cell == len(memory):
                    memory += [False]
                memory[cell] = not memory[cell]
                if not memory[cell]:
                    pointer = ((pointer[0] + 1) % max_rows, pointer[1] - 1)
            if memory[1]:
                out = memory[3:11]
                out_num = sum(2 ** (7 - power) for power, bit in enumerate(out) if bit == True)
                if out_num == 0:
                    in_str = ''
                    if input_string:
                        in_str = input_string[0]
                        input_string = input_string[1:]
                    else:
                        in_str += input("Input ASCII value between 0 and 255, inclusive:")
                    if in_str == '':
                        in_num = 0
                    else:
                        in_num = ord(in_str[0])
                        input_string += in_str[1:]
                    while not 0 <= in_num <= 255:
                        in_str = input("Input ASCII value between 0 and 255, inclusive:")
                        if in_str == '':
                            in_num = 0
                        else:
                            in_num = ord(in_str[0])
                    for power in range(7, -1, -1):
                        memory[10 - power] = True if in_num // 2 ** power == 1 else False
                        in_num %= 2 ** power
                else:
                    print(chr(out_num))
                memory[1] = False
        pointer = (pointer[0], pointer[1] + 1)
        if pointer[1] == max_columns:
            if memory[cell]:
                pointer = (pointer[0], 0)
            else:
                break