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
- This language is a derivative of Ultimate bf instruction minimalization!.
2DFIM, also called 2dfim, is a family of 2D languages which arguably have only two "real" instructions, though you could argue Version 1 has 4 instructions including no-op and newline, and Version 2 has 3 instructions including no-op. 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.
Version 1
Specification
The memory tape is left-bounded. 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 representation is big-endian, so the 4th cell contains the largest bit and the 11th cell contains the smallest.
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.
| 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 0, end the program. Otherwise, if this is the first newline in the file, move the instruction pointer to the beginning of the file. Otherwise, move the instruction pointer back to the instruction after the previous newline. |
| (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).
<(<( (<( <
(<( (<(
(<( (<(
(<( (<(
(<( <<<<<<<<<<(<(((<(
Truth Machine
This truth machine works for 0 and 1, but can have undefined behavior for other inputs.
<(<( <( this line does loop management
<<((((( this line takes in input and prints 1 on subsequent loops
( 1 0
(((( <(
<(<<(<<(
<<(<<(
<<( <<(
<<(<<(<<(<<(<<(<<(
<<( <<(
<<<(( <<<( this line prints output for 1 and 0
This can also be made 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 1 <= in_num <= 255:
in_str = input("Input ASCII value between 1 and 255, inclusive:")
if in_str == '':
in_num = 0
else:
in_num = ord(in_str[0])
if 1 <= in_num <= 255:
input_string += in_str[1:]
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),end='')
memory[1] = False
pointer = (pointer[0], pointer[1] + 1)
if pointer[1] == max_columns:
if memory[cell]:
pointer = (pointer[0], 0)
else:
break
Version 2
The point of this version is to change the behavior around newlines so it's easier to argue the language has 3 instructions rather than 4.
Specification
The memory tape is left-bounded. 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 representation is big-endian, so the 4th cell contains the largest bit and the 11th cell contains the smallest.
The instruction pointer starts at the first (topmost) row of the first (leftmost) column. Once it hits or passes the rightmost end of that line of the program (the newline), it goes to the next row. The only exception is the end of the program itself. At that point, 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.
| 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. |
| (anything else / no-op) | Move the instruction pointer one character to the right. |
If the instruction pointer is at the lowest row and ( flips a bit to zero, it is treated the same as hitting the end of the program (starting at the beginning of the program again).
Programs
Infinite Loop
(
This is still an infinite loop.
Cat Program
The cat program is actually simpler in this version, though it can't be compacted. However, it's possible that the cat program can be simplified even more than this.
<(<( 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 loops.
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]
instruction = 'x'
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 1 and 255, inclusive:")
if in_str == '':
in_num = 0
else:
in_num = ord(in_str[0])
input_string += in_str[1:]
while not 1 <= in_num <= 255:
in_str = input("Input ASCII value between 1 and 255, inclusive:")
if in_str == '':
in_num = 0
else:
in_num = ord(in_str[0])
if 1 <= in_num <= 255:
input_string += in_str[1:]
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),end='')
memory[1] = False
pointer = (pointer[0], pointer[1] + 1)
if pointer[1] == max_columns:
if pointer[0] == max_rows - 1:
if memory[cell]:
pointer = (pointer[0], 0)
else:
break
else:
pointer = (pointer[0] + 1, 0)