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.