Brainfuck | |
---|---|
Jazyková třída | esoterický |
Objevil se v | 1993 |
Autor | Urban Muller |
Vývojář | Urban Müller [d] |
Přípona souboru | .bnebo.bf |
Dialekty | BrainSub, Brainfork, Brainloller, COW, Ook, Pbrain, Smallfuck, Spoon , LOLCODE , Whitespace , DoubleFuck , Feckfeck |
Byl ovlivněn | NEPRAVDIVÉ |
Mediální soubory na Wikimedia Commons |
Brainfuck je jeden z esoterických programovacích jazyků , vynalezený Urbanem Müllerem v roce 1993 , známý pro svůj minimalismus . Název jazyka lze do ruštiny přeložit jako odstranění mozku , je přímo odvozen z anglického výrazu brainfuck ( mozek - mozek, fuck - fuck ), tedy zaplétat se do nesmyslů . Jazyk má osm příkazů, z nichž každý je napsán jedním znakem. Zdrojový kód programu Brainfuck je sekvence těchto znaků bez jakékoli další syntaxe.
Jedním z motivů Urbana Mullera bylo vytvořit jazyk s co nejmenším překladačem. Částečně byl inspirován jazykem FALSE , pro který existoval 1024bytový kompilátor. Existují překladače jazyka Brainfuck menší než 200 bajtů [1] . Programování v jazyce Brainfuck se píše obtížně, pro což se mu někdy říká jazyk pro masochisty. Ale zároveň je Brainfuck zcela přirozený, úplný a jednoduchý jazyk a lze jej použít při definování pojmu vyčíslitelnosti .
Stroj, ovládaný příkazy Brainfuck , sestává z uspořádané sady buněk a ukazatele na aktuální buňku, připomínající pásku a hlavu Turingova stroje . Kromě toho zahrnuje zařízení pro komunikaci s vnějším světem (viz příkazy . a , ) prostřednictvím vstupního toku a výstupního toku.
Jazyk Brainfuck lze popsat pomocí ekvivalentů jazyka C :
Tým Brainfuck | C ekvivalent | Popis týmu |
---|---|---|
Spuštění programu | int i = 0; char arr[30000]; memset(arr, 0, sizeof(arr)); |
paměť je alokována pro 30 000 buněk s nulovými počátečními hodnotami |
> | i++; | přesunout do další buňky |
< | i--; | přesunout do předchozí buňky |
+ | arr[i]++; | zvýšit hodnotu v aktuální buňce o 1 |
- | arr[i]--; | snížit hodnotu v aktuální buňce o 1 |
. | putchar(arr[i]); | vytisknout hodnotu z aktuální buňky |
, | arr[i] = getchar(); | zadejte hodnotu zvenčí a uložte ji do aktuální buňky |
[ | while(arr[i]){ | pokud je hodnota aktuální buňky nula, posuňte se v textu programu dopředu na znak následující za odpovídajícím ] (včetně vnoření) |
] | } | pokud hodnota aktuální buňky není nula, vraťte se přes text programu ke znaku [ (s přihlédnutím k vnoření) |
Navzdory vnější primitivitě má Brainfuck s nekonečnou sadou buněk Turingovu úplnost , a proto není z hlediska potenciálu horší než „skutečné“ jazyky jako C , Pascal nebo Java .
Brainfuck je vhodný pro experimenty v genetickém programování díky jednoduchosti syntaxe, a tedy i generování zdrojového kódu.
V "klasickém" Brainfuck popsaném Mullerem je velikost buňky jeden bajt, počet buněk je 30 000. V počátečním stavu je ukazatel na pozici úplně vlevo a všechny buňky jsou vyplněny nulami. Hodnoty buněk se zvyšují nebo snižují modulo 256. Vstup/výstup probíhá také bajt po bajtu, přičemž se bere v úvahu kódování ASCII (to znamená, že v důsledku operace vstupu ( , ) bude znak 1 zapsán do aktuální buňky jako číslo 0x31 (49) a výstupní operace ( . ) provedená na buňce obsahující 0x41 (65) vytiskne latinku A ). V jiných jazykových variantách může být velikost a počet buněk jiný (větší). Existují verze, kde hodnota buněk není celé číslo (s plovoucí desetinnou čárkou).
Celkem bylo použito 389 výpisů a 1 paměťová buňka. Optimalizovaný program je znatelně kratší – pouze 111 příkazů, ale 5 paměťových buněk. První buňka se používá jako počítadlo smyček pro 10 iterací, další buňky obsahují čísla 7, 10, 3 a 1 , zvětšená o tuto smyčku na 70, 100, 30 a 10 , k součtu dojde před tiskem, druhé slovo je postavený z pozůstatků prvního:
++++++++++ [ > +++++++ > ++++++++++ > +++ > + <<<< - ] > ++ . > + . +++++++ .. +++ . > ++ . << +++++++++++++++++ . > . +++ . ------ . -------- . > + . > .Analýza programu:
Cyklus vycpávání hlavních čísel | |
++++++++++ | přiřadit buňce 0 hodnotu 10 |
[ | opakujte příkazy popsané touto závorkou, dokud hodnota aktuální buňky 0 nebude rovna nule |
>+++++++ | zvýšení buňky o 1 x 7 |
>++++++++++ | zvýšení buňky o 2 x 10 |
>+++ | zvýšení buňky 3x3 |
>+ | přírůstek buňky 4x1 |
<<<<- | zmenšení buňky 0 o 1 |
] | kontrola, zda je buňka 0 nula |
Výstup prvního slova | |
>++. | v buňce 1 , přidání 2 k 70 a vytištění ASCII kódu 72, tzn. písmena " H ". |
>+. | v buňce 2 přidejte 1 k 100 = 101, vytiskněte písmeno " e " |
+++++++.. | ve stejné buňce přidáním 7 k 101 = 108, vytištění " l " dvakrát |
+++. | ve stejné buňce přidání 3 k 108 = 111, tisk " o " |
>++. | v buňce 3 přidejte 2 k 30 = 32, vytiskněte mezeru |
Výstup druhého slova s opětovným použitím buňky | |
<<+++++++++++++++. | v buňce 1 přidejte 15 k 72 = 87, vytiskněte " W " |
>. | buňka 2 již má 111, okamžitě vytiskněte " o " |
+++. | ve stejné buňce přidání 3 k 111 = 114, tisk " r " |
------. | ve stejné buňce odečtěte 6 od 114 = 108, vytiskněte " l " |
--------. | ve stejné buňce odečtěte 8 od 108 = 100, vytiskněte " d " |
>+. | v buňce 3 přidejte 1 k 32 = 33, vytiskněte " ! » |
>. | buňka 4 již má 10, okamžitě vytiskněte posun řádku |
Příklad tlumočníka Brainfuck napsaného v Perlu :
#!/usr/bin/perl open F , shift ; @code = grep { /[+-\.,\[\]><]/ } rozdělení '' , <F> ; for ( my $_ = 0 ; $_ < @code ; ++ $_ ) { ++ $cpu [ $i ] if $code [ $_ ] eq '+' ; -- $cpu [ $i ] if $code [ $_ ] eq '-' ; -- $i if $code [ $_ ] eq '<' ; ++ $i if $code [ $_ ] eq '>' ; print chr $cpu [ $i ] if $code [ $_ ] eq '.' ; $cpu [ $i ] = ord <STDIN> if $code [ $_ ] eq ',' ; if ( $code [ $_ ] eq '[' ) { if ( ! $cpu [ $i ]) { ++ $brc ; while ( $brc ) { ++ $_ ; ++ $brc if $code [ $_ ] eq '[' ; -- $brc if $code [ $_ ] eq ']' ; } } else { další ; } } elsif ( $kód [ $_ ] eq ']' ) { if ( ! $cpu [ $i ]) { další ; } else { ++ $brc if $code [ $_ ] eq ']' ; while ( $brc ) { -- $_ ; -- $brc if $code [ $_ ] eq '[' ; ++ $brc if $code [ $_ ] eq ']' ; } -- $_ ; } } }Příklad překladače Brainfuck napsaného v C++ :
#include <iostream> #include <fstream> #include <vektor> #include <iterátor> int main ( int argc , char ** argv ) { std :: soubor fstream ( argv [ 1 ], std :: ios :: in ); std :: istreambuf_iterator < char > fstart ( soubor ), fend ; std :: vector < char > itape ( fstart , fend ); soubor . zavřít (); std :: vector < char > mtape ( 30000 , 0 ); std :: vector < char >:: iterátor m = mtape . začít (); std :: vector < char >:: iterator i = itape . začít (); int b = 0 ; for (; i != itape . end (); ++ i ) { přepínač ( * i ) { případ '>' : if ( ++ m == mtape . end ()) { mtape . zatlačení ( 0 ); m = -mtape . _ konec (); } zlomit ; případ '<' : -- m ; zlomit ; případ '+' : +** m ; zlomit ; případ '-' : --* m ; zlomit ; případ '.' : std :: cout << * m ; zlomit ; case ',' : std :: cin >> * m ; zlomit ; případ '[' : if ( * m ) pokračovat ; ++ b ; zatímco ( b ) přepínač ( *++ i ){ případ '[' : ++ b ; zlomit ; case ']' : -- b ; zlomit ; } zlomit ; případ ']' : if ( !* m ) pokračovat ; ++ b ; zatímco ( b ) přepínač ( *-- i ){ case '[' : -- b ; zlomit ; případ ']' : ++ b ; zlomit ; } --i ; _ zlomit ; } } }Každý začátečník programování Brainfuck okamžitě narazí na následující problémy:
Tyto problémy lze vyřešit.
Označte @(k) posun o k buněk doprava, pokud k>0, a doleva, pokud k<0 V souladu s tím @(k) = >… k krát …> nebo <… -k krát …<Brainfuck se téměř vůbec nepoužívá k praktickému programování (s výjimkou práce jednotlivých nadšenců) a používá se hlavně na hádanky a soutěžní problémy.
Poznámky: 1. Speciálně pro funkčnost příkazu mOO jsou vnitřní kódy jeho příkazů [2] zavedeny do jazyka COW , v tabulce jsou uvedeny v samostatném sloupci. 2. Nepřítomnost týmu je označena jako nepřítomnost .
Brainfuck | OK! | KRÁVA | COW kód | Popis |
] | OK? OK! | bučení | 0 | Konec cyklu |
< | OK? OK. | bučení | jeden | Předchozí buňka |
> | OK. OK? | bučení | 2 | Další buňka |
ots. | ots. | bučení | 3 | Proveďte hodnotu v aktuální buňce jako příkaz s odpovídajícím kódem z rozsahu 0 - 11; kód 3 způsobí smyčku |
ots. | ots. | Bučení | čtyři | Pokud je hodnota aktuální buňky nula, zadejte ji z klávesnice; pokud hodnota aktuální buňky není nula, zobrazte ji na obrazovce |
- | OK! OK! | Bučení | 5 | Hodnota aktuální buňky se sníží o 1 |
+ | OK. OK. | Bučení | 6 | Hodnota aktuální buňky se zvýší o 1 |
[ | OK! OK? | MO | 7 | Spuštění smyčky (COW má funkci - první příkaz smyčky je přeskočen) |
[-] | ots. | OOO | osm | Obnoví hodnotu v aktuální buňce |
ots. | ots. | MMM | 9 | Pokud je registr prázdný, zkopírujte do něj hodnotu aktuální buňky, jinak zkopírujte obsah registru do buňky a vymažte registr |
. | OK! OK. | OOM | deset | Zobrazení hodnoty aktuální buňky |
, | OK. OK! | oom | jedenáct | Dotaz na hodnotu aktuální buňky |
Další popis mnoha dialektů tohoto jazyka lze nalézt ve wiki encyklopedii esoterických jazyků [3]
Programovací jazyky | |
---|---|
|