Brainfuckn't

From Esolang
Jump to navigation Jump to search

Brainfuckn't is a tape-based esolang created by user:4gboframram. The goal of the language was to make a language that is more frustrating to use than brainfuck, but at the same time to have a just as simple instruction set. Like brainfuck, this language's name should be written in all lowercase unless at the start of a sentence.

Brief Specification

Brainfuckn't is a tape-based esolang where there are two tapes with binary cells. Each tape has a pointer that can be cast to different sizes and when doing so, the pointer expands or contracts from the right (the lower bits, higher position value). The entire program state be defined as the 5-tuple (s, p1, t1, p2, t2), where s is the size of the tape pointers. pn is the position of the nth tape's pointer, and tn is the bit array representing the contents of the nth tape. s and pn are unsigned integers. The term "region" refers to the pn to pn + s - 1 bits of the nth tape, zero-indexed. The most significant bits of a region are considered the bits with a lower position.

Bit-wise operations can be applied between the two regions. Applying a bit-wise operation when the tape pointer size is zero results in a noop. The result of the operation overrides the content of the first region. The list of all instructions is as follows:

Instruction Description
> Move the first tape's pointer to the right (increment its position). If the implementation has a finite tape, then the position pointing past the tape length is implementation-defined behavior.
< Move the first tape's pointer to the left (decrement its position). Underflow is implementation-defined behavior.
} Move the second tape's pointer to the right (increment its position). Same rules apply as with the first pointer.
{ Move the second tape's pointer to the left (decrement its position). Same rules apply as with the first pointer.
+ Increment the pointer size.
- Decrement the pointer size. Underflow is implementation-defined behavior.
. Convert first tape's region to byte, cutting off any most-significant bits if the tape pointer size is larger than the number of bits in a byte. If the tape pointer size is smaller than the number of bits in a byte, then the value is zero-extended to fit the byte.
* Read a single byte from standard input and set the contents of the first tape's region to each corresponding bit of the byte, cutting off most-significant bits of the input if the tape pointer size is smaller than the number of bits in a byte. If the tape pointer size is smaller than the number of bits in a byte, higher-order bits are cut off to fit the region.
, Output the value of the first tape's region as an unsigned decimal integer, encoded into characters with whatever encoding is sensible for the implementation, but ASCII is typically used. If the pointer size is zero, zero is outputted. Implementations should have accurate results for at least up to 4-byte integers.
~ Flip each bit in the contents of the first region
| Apply a bit-wise or operation between the contents of both tapes' regions and override the contents of the first tape's region with the result of the operation
& Apply a bit-wise and operation between the contents of both tapes' regions and override the contents of the first tape's region with the result of the operation
^ Apply a bit-wise and operation between the contents of both tapes' regions and override the contents of the first tape's region with the result of the operation
@ Swap the two tapes and the two pointer positions, making the new program state (s, p2, t2, p1, t1).
[ Jump past the matching ] if the first tape's region contains only zeros or if the pointer size is zero
] Jump back to the matching [
_ Print a binary representation of both tapes to standard output and provide an indication of the position and size of the pointer. Bits with a lower position should be printed first. The actual indication may vary depending on implementation. Should mostly be used for debugging purposes.

All other characters are treated as comments and are to be ignored.

Examples

Feel free to add more examples (with commented and uncommented versions).

Cat (12 characters)

(Commented)

+++++++ Set size to 8
~ Invert the byte so that the loop can start
[*.] Keep printing each character in the input

(Uncommented)

+++++++~[*.]

Truth Machine (29 characters)

(Commented)


>>+~++++++<< Put ascii of 0 onto first tape
@* Get input character into second tape
^ Check if the character is 0
If the character is 0 then a zero is put onto the tape otherwise there will be a non zero value on the first tape
[@ If that value is not zero switch tapes
>>[-]+[,] Move to the first 1 in the binary of 0 and decrease the pointer size to 1 and continuously print the 1 as a digit 
] End of loop
@. Otherwise switch tapes and print the 0 once

(Uncommented)


>>+~++++++<<@*^[@>>[-]+[,]]@.

Hello World! (104 characters)

The shortest known program that prints Hello, World! with the comma and trailing newline was created by the author of the language. There is too much to comment on, so there are no comments. It's a lot of character by character "bit fuckery," as phrased by the author. They also believe that it is possible to create such a program with less than 80 characters.

++++++~>~>>~>~<<<<.@^>^>>^<<<.@>>>>^..<<<<@|.-@>>>>>.[>]<.+^<.@.[>]<^<<<.>>^<<<<<.>>&<<.[>-]~++~++<.--@.

Computational Class

If the length of the tapes are unbounded, brainfuckn't is Turing complete due to its instruction set being a superset of the instruction set of a brainfuck with binary cells, which has been proven to be Turing complete by user:Keymaker. If the size of the pointer is always 1 and the instruction set is reduced to []~><, then brainfuckn't is equivalent to brainfuck with binary cells with a 1-to-1 instruction substitution. Since Ørjan Johansen proved that said version of brainfuck is Turing complete even with the added restriction of loops being nested only 2 levels deep, that same restriction applies to brainfuckn't.

External Resources