81
- Not to be confused with 8.
- Note that 81 is always italicized.
| Paradigm(s) | Imperative |
|---|---|
| Designed by | User:Waffelz |
| Appeared in | 2025 |
| Memory system | Cell-based |
| Dimensions | one-dimensional |
| Computational class | Turing complete |
| Reference implementation | Unimplemented |
| File extension(s) | *.81 |
About
81 is an esolang created by User:Waffelz during class because he was bored. It is entirely based on base-81 literals, whose digits are listed in the table below:
| X0 | X1 | X2 | X3 | X4 | X5 | X6 | X7 | X8 | X9 | |
| 0X | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 1X | A | B | C | D | E | F | G | H | I | J |
| 2X | K | L | M | N | O | P | Q | R | S | T |
| 3X | U | V | W | X | Y | Z | a | b | c | d |
| 4X | e | f | g | h | i | j | k | l | m | n |
| 5X | o | p | q | r | s | t | u | v | w | x |
| 6X | y | z | ! | @ | # | $ | % | ^ | & | * |
| 7X | + | / | | | \ | < | > | ~ | ` | ? | = |
| 8X | _ |
In 81 code, number literals are surrounded in brackets ([...]), and memory addresses are surrounded in braces ({...}). It has a set of 28 opcodes, which are Turing-complete.
Memory
There are 43,046,721 memory cells, indexed from [0] to [ _ _ _ ], all initialized as 0. They can store integers from 0–15,009,4635,296,999,120, or [0] to [ _ _ _ _ _ _ _ _ ]. It has 5 built-in registers — an accumulator (A), 3 general-purpose registers (RX/RY/RZ), and an overflow flag (V).
Commands
(M1/M2 represent arbitrary memory addresses, C1/C2 represent arbitrary number literals or memory adressess, and label represents an arbitrary label.)
| CPY C1 M1 | Copies the value of C1 to M1. |
| INC M1 | Increments the value of M1. |
| DEC M1 | Decrement the value of M1. |
| ADD C1 C2 | Add the values of C1 and C2 and store it in the accumulator. |
| SUB C1 C2 | Subtracts the values of C1 and C2 and stores it in the accumulator. |
| MUL C1 C2 | Multiplies the values of C1 and C2 and stores it in the accumulator. |
| DIV C1 C2 | Divides the values of C1 and C2 and stores it in the accumulator, rounding down if necessary. |
| POW C1 C2 | Raise sthe value of C1 to the value of C2 and stores it in the accumulator. |
| CLR M1 | Resets the value of M1 to 0. |
| SWP M1 M2 | Swaps the values of M1 and M2. |
| EQL C1 C2 | Stores 1 in the accumulator if C1 is equal to C2, else 0. |
| NEQ C1 C2 | Stores 1 in the accumulator if C1 is not equal to C2, else 0. |
| GRT C1 C2 | Stores 1 in the accumulator if C1 is greater than C2, else 0. |
| LSS C1 C2 | Stores 1 in the accumulator if C1 is less than C2, else 0. |
| ) label | Defines a label for use with JMP or related commands. |
| JMP label | Moves code execution to the specified label. |
| JEQ C1 C2 label | Moves code execution to the specified label if C1 is equal to C2, else continue normally. |
| JNQ C1 C2 label | Moves code execution to the specified label if C1 is not equal to C2, else continue normally. |
| JGR C1 C2 label | Moves code execution to the specified label if C1 is greater than to C2, else continue normally. |
| JLS C1 C2 label | Moves code execution to the specified label if C1 is less than C2, else continue normally. |
| JCD C1 label | Moves code execution to the specified label if C1 is 1, else continue normally. |
| RET | Moves code execution to the instruction after the last executed JMP (or related) command. |
| OUT C1 | Outputs the Unicode character whose codepoint is stored in C1. |
| INP | Takes one character as input and store its Unicode codepoint in the accumulator. |
| †NOU C1 | Outputs the number in C1 in base 10. |
| †NIN | Takes one base-10 number as input and store it in the accumulator. |
| HLT | Halts the program. |
| NOP | No-op (does nothing). |
†This operator exists solely for user-friendliness. The programmer must use base 81 internally.
Note: A HLT command is not required for a program.
Syntax/Semantics
The syntax of 81 is very simple. Every command is on its own line, followed by its arguments, each separated by one space.
81 has two types of comments — a normal (inline) comment, and a header. Inline comments are delimited via @, and everything after is ignored by the runtime. A header comment must be on its own line, and is surrounded by three equal signs (=== ... ===). Its purpose is organizing code.
Example Programs
- Note: These programs contain the original comments from the draft of 81.
“Hello, World!”
OUT [/] @ H (72) OUT [1K] @ e (101) OUT [1R] @ l (108) OUT [1R] @ l (108) OUT [1U] @ o (111) OUT [i] @ , (44) OUT [W] @ (32) OUT [16] @ W (87) OUT [1U] @ o (111 OUT [1X] @ r (114) OUT [1R] @ l (108) OUT [1J] @ d (100) OUT [X] @ ! (33) HLT
Fibonacci Numbers
=== input collection ===
NIN @ iteration count
CPY A RX
=== edge cases ===
JEQ RX [0] _
JEQ RX [1] c1
JEQ RX [2] c2
=== prepare memory ==
CPY [0] {0}
CPY [1] {1}
DEC RX
DEC RX
=== set up output ===
OUT {0}
OUT [D]
OUT {1}
=== main loop ===
) loop
ADD {0} {1} @ calculate the next number based on
@ the current ones in memory
JCD V err @ jump to )err on an overflow
OUT [D] @ output a space, then the number
NOU A @ this stops trailing spaces in the
CPY {0} A @ program’s output.
SWP {0} {1} @ keep only what’s needed for the next
DEC RX @ iteration
JGR RX 0 loop
=== 0 edge case ===
) _
HLT
=== 1 edge case ===
) c1
NOU {0}
HLT
=== 2 edge case ===
) c2
NOU {0}
OUT [D]
NOU {1}
HLT
=== overflow error ===
) err
OUT [*] @ E (69)
OUT [1X] @ r (114)
OUT [1X] @ r (114)
Primality Check
=== input collection === NIN @ the number to check CPY RX A === handle n = 0 or 1 edge cases === JLS RX [2] N/A === prepare memory === CPY RY [2] @ the current integer being divided === main loop === ) loop @ if RY^2 > RX, and the loop is still going (meaning @ it passed), stop the program MUL RY RY JGR A RX p @ if RX % RY != 0, stop the program DIV RX RY MUL A RY SUB RX A JEQ A [0] _ @ increment RY and loop INC RY JMP loop === primality check indeterminant === ) N/A OUT [?] @ N (78) OUT [l] @ / (47) OUT [$] @ A (65) HLT === primality check passed (prime) === ) p OUT [_4] @ T (84) HLT === primality check failed (not prime) === ) _ OUT [+] @ F (70) HLT