Jazyk Brainfuck
Programovací jazyk Brainfuck patří mezi ezoterické jazyky, určené k pobavení a zamyšlení programátorů. Navrhl jej v roce 1993 švýcarský programátor Urban Müller a obsahuje pouze 8 příkazů, kde každý z nich je reprezentován právě jedním ASCII znakem. Neznámé znaky jsou ignorovány. Brainfuck je však i přesto Turingovsky úplný a má tedy formálně stejné schopnosti jako ostatní programovací jazyky, například C++ nebo Java.
Seznam příkazů
Programovací jazyk Brainfuck obsahuje celkem 8 příkazů. Má k dispozici pole buněk o zadané velikosti (obvykle 30000), které je na počátku vynulováno. Každá buňka může nabývat hodnot 0–255 (rozsah je tedy jeden bajt). Aktuální buňku určuje tzv. datový ukazatel.
| Příkaz | Význam |
|---|---|
| < | Přesune datový ukazatel o jednu buňku vlevo |
| > | Přesune datový ukazatel o jednu buňku vpravo |
| + | Inkrementuje hodnotu v aktuální buňce |
| - | Dekrementuje hodnotu v aktuální buňce |
| . | Vypíše hodnotu v aktuální buňce (obvykle jako odpovídající znak ASCII) |
| , | Načte hodnotu na vstupu do aktuální buňky (obvykle ASCII hodnotu zadaného znaku) |
| pravá hranatá závorka | Je-li hodnota v aktuální buňce rovna 0, přesune instrukční ukazatel za odpovídající levou závorku |
| levá hranatá závorka | Je-li hodnota v aktuální buňce různá od 0, přesune instrukční ukazatel na odpovídající pravou závorku |
Program „Hello World!“
Triviální verze
+++++ +++++ +++++ +++++ +++++
+++++ +++++ +++++ +++++ ++ .
+++++ +++++ +++++ +++++ +++++
++++ .
+++++ ++ ..
+++ .
----- ----- ----- ----- -----
----- ----- ----- ----- -----
----- ----- ----- ----- -----
----- ----- .
+++++ +++++ +++++ +++++ +++++
+++++ +++++ +++++ +++++ +++++
+++++ +++++ +++++ +++++ +++++
+++++ +++++ +++++ +++ .
----- --- .
+++ .
----- - .
----- --- .
----- ----- ----- ----- -----
----- ----- ----- ----- -----
----- ----- ----- -- .
----- ----- ----- ----- .
--- .
zdrojový kód (Brainfuck) - zobrazit (516 znaků)
Optimalizovaná verze
Využitím cyklů lze kód značně zkrátit.
++++++>+++>+<<<<-]>++.>+
.+++++++..+++.>++.<<++++
+++++++++++.>.+++.------
.--------.>+.>.
zdrojový kód (Brainfuck) - zobrazit (115 znaků)
Jednoduché programy
Nulování aktuální buňky
zdrojový kód (Brainfuck) - zobrazit (3 znaků)
Vyhledání první nenulové buňky
Dopředné hledání (fast forward):
zdrojový kód (Brainfuck) - zobrazit (4 znaků)
Zpětné hledání (rewind):
zdrojový kód (Brainfuck) - zobrazit (4 znaků)
Sčítání
Nechť buňka #0 obsahuje první sčítanec a buňka #1 druhý. Po skončení následující cyklu bude v buňce #0 nula a v buňce #1 součet.
zdrojový kód (Brainfuck) - zobrazit (6 znaků)
Interpretr (Java)
Třída v jazyce Java, která provádí interpretaci programů v jazyce Brainfuck, vypadá následovně:
/**
* Interpretr jazyka Brainfuck.
* @author Vojtěch Hordějčuk
*/
public class Interpreter
{
/**
* Třída představující datovou buňku.
*/
private static class Cell
{
/**
* hodnota buňky
*/
private int data;
/**
* ukazatel na předchozí buňku
*/
private Cell previous;
/**
* ukazatatel na další buňku
*/
private Cell next;
/**
* Vytvoří novou buňku s výchozí hodnotou
*/
public Cell ()
{
this.data = 0;
this.previous = null;
this.next = null;
}
/**
* Ověří, zda je buňka nulová.
* @return TRUE právě když je buňka nulová
*/
public boolean isZero ()
{
return (this.data == 0);
}
/**
* Vypíše hodnotu buňky na standardní výstup jako ASCII symbol.
*/
public void print ()
{
System.out.print ((char) this.data);
}
/**
* Nastaví novou hodnotu buňky.
* @param value nová hodnota buňky
*/
public void set (final int value)
{
if (value >= 0 && value <= 255)
{
this.data = value;
}
else
{
System.err.println ("Cell value out of range (0 to 255).");
System.exit (-10);
}
}
/**
* Dekrementuje hodnotu v buňce.
*/
public void decrement ()
{
if (this.data > 0)
{
this.data --;
}
else
{
System.err.println ("Cannot decrease the value (min = 0).");
System.exit (-11);
}
}
/**
* Inkrementuje hodnotu v buňce.
*/
public void increment ()
{
if (this.data < 255)
{
this.data ++;
}
else
{
System.err.println ("Cannot increase the value (max = 255).");
System.exit (-12);
}
}
/**
* Vrátí předchozí buňku, kterou v případě potřeby vytvoří.
* @return předchozí buňka
*/
public Cell getPrevious ()
{
if (this.previous == null)
{
this.previous = new Cell ();
this.previous.next = this;
}
return this.previous;
}
/**
* Vrátí následující buňku, kterou v případě potřeby vytvoří.
* @return následující buňka
*/
public Cell getNext ()
{
if (this.next == null)
{
this.next = new Cell ();
this.next.previous = this;
}
return this.next;
}
};
/**
* výchozí datová buňka
*/
private Cell head;
/**
* scanner pro zpracování standardního vstupu
*/
final Scanner scanner;
/**
* Vytvoří nový interpretr Brainfucku.
*/
public Interpreter ()
{
// vytvořit výchozí datovou buňku
this.head = new Cell ();
// vytvořit scanner
this.scanner = new Scanner (System.in);
}
/**
* Spustit zadaný program v jazyce Brainfuck.
* @param program pole znaků, kde znaky jsou jednotlivé instrukce
* @return TRUE právě když program skončil úspěšně
*/
public boolean start (final char[] program)
{
// zkontrolovat parametry
if (program.length < 1)
{
System.out.println ("The program is empty.");
return true;
}
// inicializovat ukazatel
int instructionPointer = 0;
// inicializovat scanner
this.scanner.reset ();
// spustit provádění instrukce
while (instructionPointer < program.length)
{
switch (program[instructionPointer])
{
case '+':
// inkrementace aktuální buňky
this.head.increment ();
instructionPointer ++;
break;
case '-':
// dekrementace aktuální buňky
this.head.decrement ();
instructionPointer ++;
break;
case '<':
// posun o buňku vlevo
this.head = this.head.getPrevious ();
instructionPointer ++;
break;
case '>':
// posun o buňku vpravo
this.head = this.head.getNext ();
instructionPointer ++;
break;
case ',':
// načíst vstup do aktuální buňky
String input;
do
{
System.out.print ("Input: ");
input = this.scanner.nextLine ();
if (input.length () == 1)
{
break;
}
System.out.println ("Invalid input. Type one character only and press ENTER.");
}
while (true);
this.head.set ((int) input.charAt (0));
instructionPointer ++;
break;
case '.':
// vypsat aktuální buňku na výstup jako ASCII
this.head.print ();
instructionPointer ++;
break;
case '[':
// je-li hodnota aktuální buňky nulová, přesunout instrukční ukazatel za odpovídající "]"
if (this.head.isZero ())
{
int depth = 0;
int ictemp = instructionPointer + 1;
while (ictemp < program.length - 1)
{
if (program[ictemp] == '[')
{
depth ++;
}
else if (program[ictemp] == ']')
{
if (depth == 0)
{
instructionPointer = ictemp + 1;
break;
}
else
{
depth --;
}
}
ictemp ++;
}
if (depth != 0)
{
System.err.println ("Invalid parenthesis.");
return false;
}
}
else
{
instructionPointer ++;
}
break;
case ']':
// je-li hodnota aktuální buňky různá od nuly, přesunout instrukční ukazatel na odpovídající "["
if (this.head.isZero ())
{
instructionPointer ++;
}
else
{
int depth = 0;
int ictemp = instructionPointer - 1;
while (ictemp > 0)
{
if (program[ictemp] == '[')
{
if (depth == 0)
{
instructionPointer = ictemp;
break;
}
else
{
depth --;
}
}
else if (program[ictemp] == ']')
{
depth ++;
}
ictemp --;
}
if (depth != 0)
{
System.err.println ("Invalid parenthesis.");
return false;
}
}
break;
default:
// neznámé znaky budou přeskočeny
instructionPointer ++;
break;
}
}
return true;
}
}
zdrojový kód (Java) - zobrazit (6853 znaků)