Self-modifying Brainfuck Sharp
- The title of this article is not correct because of technical limitations. The correct title is actually Self-modifying Brainfuck#.
Self-modifying Brainfuck# or SMBF# is a variation of Self-modifying Brainfuck by User:None1.
Its only difference from Self-modifying Brainfuck is that the IP in Self-modifying Brainfuck# starts out in the first cell (also known as the origin), while the IP in Self-modifying Brainfuck starts out in the cell right after the code.
Some programs shown in Self-modifying Brainfuck needs cell on the left of origin, which is not mentioned in its specification. But the specification of Self-modifying Brainfuck# doesn't require this.
Examples
Hello World
Hello World! ----------[++++++++++.>----------]++++++++++
Note: The line feed is MANDATORY
Cat Program
,[.,]
Quine
[.>]
A quine with some customized text is shown in the following:
[.>]QUINES ARE EASY!
Turing completeness
Since brainfuck is Turing complete, then Self-modifying Brainfuck# is.
Interpreter
Here is an interpreter by User:None1 in JavaScript.
function smbf_sharp(program,input){ var loop=0; var matches={}; var ip=0; var tape=[]; var p=0; var output=''; for(let i of program){ tape.push(i.charCodeAt(0)); } for(let i=0;i<1000000;i++){ tape.push(0); } while(ip<program.length){ console.log(ip); console.log(String.fromCharCode(tape[ip])); console.log(tape.slice(0,40)); if(String.fromCharCode(tape[ip])=='+'){ tape[p]=tape[p]+1; if(tape[p]==256) tape[p]=0; ip=ip+1; } if(String.fromCharCode(tape[ip])=='-'){ tape[p]=tape[p]-1; if(tape[p]==-1) tape[p]=255; ip=ip+1; } if(String.fromCharCode(tape[ip])=='>'){ p=p+1; if(p>=1000000){ throw new Error('Pointer overflow'); } ip=ip+1; } if(String.fromCharCode(tape[ip])=='<'){ p=p-1; if(p<0){ throw new Error('Pointer underflow'); } ip=ip+1; } if(String.fromCharCode(tape[ip])==','){ if(input==''){ tape[p]=0; }else{ tape[p]=input.charCodeAt(0)%256; input=input.slice(1); } ip=ip+1; } if(String.fromCharCode(tape[ip])=='.'){ output+=String.fromCharCode(tape[p]); ip=ip+1; } if(String.fromCharCode(tape[ip])=='['){ if(tape[p]==0){ loop=1; while(loop>0){ ip++; if(String.fromCharCode(tape[ip])=='['){ loop++; } if(String.fromCharCode(tape[ip])==']'){ loop--; } } } ip++; } if(String.fromCharCode(tape[ip])==']'){ loop=1; while(loop>0){ ip--; if(String.fromCharCode(tape[ip])=='['){ loop--; } if(String.fromCharCode(tape[ip])==']'){ loop++; } console.log(loop,ip,tape[ip]); } } if(!('+-,.[]<>'.includes(String.fromCharCode(tape[ip])))){ ip=ip+1; } } return output; }
Here is another interpreter in C# also by User:None1.
using System; public class SMBF_Sharp { private static int loop = 0, cnt = 0; private static string program = ""; private static int[] tape = new int[1000000]; static void read() { int ch; while ((ch = Console.Read()) != -1) { program += Convert.ToChar(ch); tape[cnt++] = ch; } } static void smbf_run() { int ip = 0, p = 0; while (ip < program.Length) { switch (tape[ip]) { case '+': { tape[p] = tape[p] + 1; if (tape[p] > 255) { tape[p] = 0; } break; } case '-': { tape[p] = tape[p] - 1; if (tape[p] < 0) { tape[p] = 255; } break; } case ',': { tape[p] = Console.Read(); if (tape[p] == -1) { tape[p] = 0; } break; } case '.': { Console.Write(Convert.ToChar(tape[p])); break; } case '<': { p--; if(p < 0) { Console.WriteLine("Pointer underflow"); return; } break; } case '>': { p++; if (p >= 1000000) { Console.WriteLine("Pointer overflow"); return; } break; } case '[': { if (tape[p] == 0) { loop = 1; while (loop > 0) { ip++; if (tape[ip] == 91) { loop++; } if (tape[ip] == 93) { loop--; } } } break; } case ']': { loop = 1; while (loop > 0) { ip--; if (tape[ip] == 91) { loop--; } if (tape[ip] == 93) { loop++; } } ip--; break; } } ip++; } } static void Main(string[] args) { read();smbf_run();Console.WriteLine(""); // Weird behavior: If I don't add the writeline, the console gave me "ello World!", but it gave me "Hello World!" when I redirect output to file. } }
External Resources
- Online interpreter using the JavaScript interpreter above.