Here's the whole language:

  • '>' : move the memory pointer to the next cell,
  • '<' : move the memory pointer to the previous cell,
  • '+' : increment the memory cell under the memory pointer,
  • '-' : decrement the memory cell under the memory pointer,
  • ',' : fills the memory cell under the memory pointer with the ASCII value of next character from the input,
  • '.' : writes the contents of the memory cell under the memory pointer as a character with the corresponding ASCII value,
  • '' : moves to the command following the matching '', if the memory cell under the memory pointer is zero, and
  • ']' : moves to the command following the matching '[', if the memory cell under the memory pointer is not zero.

I have no idea if this formatting will work, but it's worth a shot... Here is a 99 bottles of beer on the wall program in brainfuck. Also worth noting, the homepage of brainfuck is currently at: http://www.catseye.mb.ca/esoteric/bf/

>+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>> 
[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+< 
-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<< 
[>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<+++ 
+++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>- 
]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+ 
++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]> 
>>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<+++++++ 
+>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<------ 
---->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++ 
++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++ 
[<---------->-]<++.>++++++++[<++++++++++>-]<++++.----------- 
-.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-. 
>++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]< 
-----.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>+++ 
+[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<. 
><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++ 
++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<++ 
+++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<++ 
+++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]< 
-.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++. 
------.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-. 
-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>- 
]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-] 
<++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>++++ 
+++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<-----> 
-]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[< 
++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++ 
.>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.---- 
---.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>[ 
-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-] 
>[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]< 
<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]< 
<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+ 
<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++> 
-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..--- 
-----.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++ 
.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<- 
-.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-] 
<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[ 
<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++
++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+. 
>++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++ 
..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<] 


Brainfuck


Brainfuck was invented in 1993 by the Swiss programmer Urban Müller. He wanted to create a Turing-complete programming language with a small compiler. His original compiler has 240 bytes of C code, the version I wrote has 2.400 bytes of Pascal code ... (okay, I am ashamed ...).

As already noded, BF has eight different operators with which you are forced to create your programs. It works indeed, but as soon as you try to write non-trivial programs, you'll either turn completely mad or your brain will be fucked, which is quite the same ;-)


Here is my version of the Hello World program in Brainfuck:

>++>+++++++[<++++++++++>-]<.+++++++++>++[<++++++++++>-]<.+++++++..+++.-------
>++++++[<---------->-]<.------------.+++++>+++++[<++++++++++>-]<.++++>++[<+++
+++++++>-]<.+++.------.--------.+++>+++++++[<---------->-]<.

Brainfuck is quite a brilliant little programming language. As noted above and elsewhere, it operates in a similar manner to a basic Turing machine. A note on the name: understandably, Urban Müller now wishes he'd called it something different.

Below is the code for a Brainfuck interpreter written in Java. The usage is:

	java Brainfuck yourCode.b

Where yourCode.b is a file containing Brainfuck. Standard input and standard output are used for the ',' and '.'. To pipe a file into your program (or anyone else's), you can do this at a shell:

	cat yourFile | java Brainfuck yourCode.b 1

...I think.

The code could be better, but it could also be worse. It was written to be understandable, rather than terse - for that, see the writeup below. There you can see an interpreter done in 3 lines of obfuscated C. (Which is cool, but consider which one is easier to debug or maintain :-P) This would probably make for a good tournament of Perl Golf.

That said:

import java.io.InputStream;
import java.io.PrintStream;
import java.io.File;
import java.io.FileInputStream;

import java.io.IOException;

import java.util.ArrayList;
import java.util.Stack;

class Brainfuck {

    InputStream input;
    PrintStream output;

    ArrayList infiniteTape;
    int headPosition;

    Brainfuck( InputStream in, PrintStream out ) {
        input = in;
        output = out;

        infiniteTape = new ArrayList();

        for( int i = 0; i != 50; i++ ) infiniteTape.add( new Byte( (byte)0x00 ) );

        headPosition = 0;
    }

    void interpret( byte[] code ) throws IOException {

        int instructionPointer = 0;

        Stack nestedLoops = new Stack();

        while( instructionPointer != code.length ) switch( code[instructionPointer] ) {

            case '>' :
                headPosition++;
                if( headPosition >= infiniteTape.size() ) stretchTapeEnd();
                instructionPointer++;
                break;
            case '<' :
                headPosition--;
                if( headPosition <= 0 ) stretchTapeStart();
                instructionPointer++;
                break;
            case '+' :
                setSymbol( (byte)(getSymbol() + 0x01) );
                instructionPointer++;
                break;
            case '-' :
                setSymbol( (byte)(getSymbol() - 0x01) );
                instructionPointer++;
                break;
            case ',' :
                setSymbol( (byte)input.read() );
                instructionPointer++;
                break;
            case '.' :
                output.print( (char)getSymbol() );
                instructionPointer++;
                break;
            case '[' :
                if( getSymbol() != 0x00 ) {
                    nestedLoops.push( new Integer( ++instructionPointer ) );
                } else instructionPointer = skipLoop( code, instructionPointer );
                break;
            case ']' :
                if( nestedLoops.size() == 0 )
                  throw new IOException ("mismatched ]");

                if( getSymbol() != (byte)0x00 ) {
                    instructionPointer = ((Integer)nestedLoops.peek()).intValue();
                } else {
                    nestedLoops.pop();
                    instructionPointer++;
                }
                break;
            default : instructionPointer++; break;
        }
    }

    byte getSymbol() {
        Byte symbol = (Byte)infiniteTape.get( headPosition );
        return symbol.byteValue();
    }

    void setSymbol( byte value ) {
        Byte symbol = new Byte( value );
        infiniteTape.set( headPosition, symbol );
    }

    void stretchTapeEnd() {
        for( int i = 0; i != 20; i++ )
          infiniteTape.add( new Byte( (byte)0x00 ) );
    }

    void stretchTapeStart() {
        for( int i = 0; i != 20; i++ )
          infiniteTape.add( 0, new Byte( (byte)0x00 ) );
        headPosition += 20;
    }

    int skipLoop( byte[] code, int from ) {
        int subLoops = 0;

        do switch( code[++from] ) {
            case '[' : subLoops++; break;
            case ']' : subLoops--; break;
            default  : break;
        } while( subLoops != -1 );

        return ++from;
    }

    public static void main( String[] args ) throws IOException {

        byte[] code;

        if( args.length < 1 ) {
            System.out.println( "Usage: java Brainfuck file.b" );
            return;
        }

        File brainfuckFile = new File( args[0] );

        if( !brainfuckFile.exists() ) {
            System.out.println( args[0] + " does not exist" );
            return;
        }

        code = new byte[(int)brainfuckFile.length()];

        FileInputStream fileIn = new FileInputStream( brainfuckFile );

        for( int i = 0; i != code.length; i++ ) code[i] = (byte)fileIn.read();

        fileIn.close();

        Brainfuck interpreter = new Brainfuck( System.in, System.out );
        interpreter.interpret( code );

    }

}

And there you go. Now, you too can marvel at ''hello, world!'', and wonder just how on earth ccunning checked for the difference between singular and plural when counting bottles of beer on a wall. This is just the first step, of course; the logical progression would be to write a Brainfuck interpreter entirely in Brainfuck...

...but someone's already beaten me to it:

http://home.wxs.nl/~faase009/Ha_bf_inter.html

1: Thanks to ivarneli for the correction.

Three line C brainfuck interpreter
From http://www.catseye.mb.ca/esoteric/bf/

char m[9999],*n[99],*r=m,*p=m+5000,**s=n,d,c;main(){for(read(0,r,4000);c=*r;
r++)c-']'||(d>1||(r=*p?*s:(--s,r)),!d||d--),c-'['||d++||(*++s=r),d||(*p+=c==
'+',*p-=c=='-',p+=c=='>',p-=c=='<',c-'.'||write(2,p,1),c-','||read(2,p,1));}

Compile with: gcc abovecode.c -o bf
Use with: bf < source.bf

Log in or register to write something here or to contact authors.