Aivojuttu | |
---|---|
Kieliluokka | esoteerinen |
Esiintyi | 1993 |
Tekijä | Urban Muller |
Kehittäjä | Urban Müller [d] |
Tiedostotunniste _ | .btai.bf |
Murteet | BrainSub, Brainfork, Brainloller, COW, Ook, Pbrain, Smallfuck, Spoon , LOLCODE , välilyönti , DoubleFuck , Feckfeck |
Vaikutettu | VÄÄRÄ |
Mediatiedostot Wikimedia Commonsissa |
Brainfuck on yksi esoteerisista ohjelmointikielistä , jonka Urban Müller keksi vuonna 1993 ja joka tunnetaan minimalismistaan . Kielen nimi voidaan kääntää venäjäksi aivopoistoksi , se on suoraan johdettu englanninkielisestä ilmaisusta brainfuck ( brain - brain, fuck - fuck ), eli harjoittaa hölynpölyä . Kielessä on kahdeksan komentoa, joista jokainen on kirjoitettu yhdellä merkillä. Brainfuck- ohjelman lähdekoodi on näiden merkkien sarja ilman ylimääräistä syntaksia.
Yksi Urban Mullerin motiiveista oli luoda kieli mahdollisimman pienellä kääntäjällä. Se oli osittain inspiraationa FALSE -kielestä , jolle oli olemassa 1024 tavun kääntäjä. On olemassa Brainfuck-kielen kääntäjiä, jotka ovat pienempiä kuin 200 tavua [1] . Ohjelmointia Brainfuck-kielellä on vaikea kirjoittaa, jota varten sitä joskus kutsutaan masokistien kieleksi. Mutta samalla Brainfuck on täysin luonnollinen, täydellinen ja yksinkertainen kieli, jota voidaan käyttää laskettavuuden käsitteen määrittelyssä .
Kone, jota ohjataan Brainfuck- komennoilla , koostuu järjestetystä solujoukosta ja osoittimesta nykyiseen soluun, joka muistuttaa Turingin koneen nauhaa ja päätä . Lisäksi se tarkoittaa laitetta, joka kommunikoi ulkomaailman kanssa (katso komennot . ja , ) tulovirran ja lähtövirran kautta.
Brainfuck-kieltä voidaan kuvata käyttämällä C-kielen vastineita :
Team Brainfuck | C ekvivalentti | Joukkueen kuvaus |
---|---|---|
Ohjelman aloitus | int i = 0; char arr[30000]; memset(arr, 0, sizeof(arr)); |
muistia on varattu 30 000 solulle, joiden alkuarvot ovat nolla |
> | i++; | siirtyä seuraavaan soluun |
< | i--; | siirtyä edelliseen soluun |
+ | arr[i]++; | lisää nykyisen solun arvoa yhdellä |
- | arr[i]--; | pienennä nykyisen solun arvoa yhdellä |
. | putchar(arr[i]); | tulosta arvo nykyisestä solusta |
, | arr[i] = getchar(); | syötä arvo ulkopuolelta ja tallenna nykyiseen soluun |
[ | while(arr[i]){ | jos nykyisen solun arvo on nolla, siirry ohjelman tekstissä eteenpäin vastaavaa ] -merkkiä seuraavaan merkkiin (mukaan lukien sisäkkäisyys) |
] | } | jos nykyisen solun arvo ei ole nolla, palaa ohjelmatekstin läpi merkkiin [ (ottaen huomioon sisäkkäisyyden) |
Ulkoisesta primitiivisyydestä huolimatta Brainfuckilla , jossa on ääretön joukko soluja, on Turingin täydellisyys , ja siksi se ei ole mahdollisuuksien suhteen huonompi kuin "oikeat" kielet, kuten C , Pascal tai Java .
Brainfuck soveltuu geneettisen ohjelmoinnin kokeisiin syntaksin yksinkertaisuuden ja vastaavasti lähdekoodin generoinnin vuoksi.
Mullerin kuvaamassa "klassisessa" Brainfuckissa solun koko on yksi tavu, solujen lukumäärä on 30 000. Alkutilassa osoitin on äärimmäisessä vasemmassa paikassa ja kaikki solut on täytetty nolilla. Solujen arvot kasvavat tai pienenevät modulo 256. Syöttö/tulostus tapahtuu myös tavu kerrallaan ottaen huomioon ASCII-koodauksen (eli syöttötoiminnon ( , ) seurauksena kirjain 1 kirjoitetaan nykyiseen soluun numerona 0x31 (49) ja 0x41 (65) sisältävälle solulle suoritettu tulostustoiminto ( . ) tulostavat latinalaisen A ). Muissa kieliversioissa solujen koko ja lukumäärä voivat olla erilaisia (suurempia). On versioita, joissa solujen arvo ei ole kokonaisluku (liukuluku).
Yhteensä 389 lausetta ja 1 muistisolu käytetty. Optimoitu ohjelma on huomattavasti lyhyempi - vain 111 lausetta, mutta 5 muistisolua. Ensimmäistä solua käytetään silmukkalaskurina 10 iteraatiolle, seuraavat solut sisältävät luvut 7, 10, 3 ja 1 , lisättynä tällä silmukalla arvoihin 70, 100, 30 ja 10 , summaus tapahtuu ennen tulostusta, toinen sana on rakennettu ensimmäisen jäänteistä:
++++++++++ [ > ++++++++ > ++++++++++ > +++ > + <<<< - ] > ++ . > + . +++++++ .. +++ . > ++ . << ++++++++++++++++ . > . +++ . ------ . -------- . > + . > .Ohjelman jäsentäminen:
Päälukujen täyttämisen kierto | |
++++++++++ | antaa solulle 0 arvo 10 |
[ | toista tässä sulussa kuvattuja komentoja, kunnes nykyisen solun arvo 0 ei ole yhtä suuri kuin nolla |
>+++++++ | solun lisäys 1 x 7 |
>++++++++++ | solun lisäys 2 x 10 |
>+++ | solun lisäys 3 x 3 |
>+ | solun lisäys 4 x 1 |
<<<<- | solu pienennetään 0 : lla |
] | tarkistaa, onko solu 0 nolla |
Ensimmäisen sanan tulos | |
>++. | solussa 1 lisäämällä 2 70:een ja tulostamalla ASCII-koodin 72, ts. kirjaimet " H ". |
>+. | lisää soluun 2 1 arvoon 100 = 101, tulosta kirjain " e " |
+++++++.. | samassa solussa lisäämällä 7 arvoon 101 = 108, tulostamalla " l " kahdesti |
+++. | samaan soluun lisätään 3 arvoon 108 = 111, tulostetaan " o " |
>++. | lisää soluun 3 2 arvoon 30 = 32, tulosta välilyönti |
Toisen sanan ulostulo solun uudelleenkäytöllä | |
<<+++++++++++++++. | lisää soluun 1 15 arvoon 72 = 87, tulosta " W " |
>. | solussa 2 on jo 111, tulosta heti " o " |
+++. | samassa solussa lisäämällä 3 arvoon 111 = 114, tulostamalla " r " |
------. | samassa solussa, vähennä 6 luvusta 114 = 108, tulosta " l " |
--------. | samassa solussa, vähennä 8 luvusta 108 = 100, tulosta " d " |
>+. | lisää soluun 3 1 arvoon 32 = 33, tulosta " ! » |
>. | solussa 4 on jo 10, tulosta heti rivinsyöttö |
Esimerkki Brainfuck-tulkista, joka on kirjoitettu Perlissä :
#!/usr/bin/perl open F , shift ; @code = grep { /[+-\.,\[\]><]/ } split '' , <F> ; for ( my $_ = 0 ; $_ < @code ; ++ $_ ) { ++ $cpu [ $i ] if $code [ $_ ] eq '+' ; -- $cpu [ $i ] jos $koodi [ $_ ] eq '-' ; -- $i jos $koodi [ $_ ] eq '<' ; ++ $i jos $koodi [ $_ ] eq '>' ; tulosta chr $cpu [ $i ] if $code [ $_ ] eq '.' ; $cpu [ $i ] = ord <STDIN> if $code [ $_ ] eq ',' ; if ( $koodi [ $_ ] eq '[' ) { if ( ! $cpu [ $i ]) { ++ $brc ; while ( $brc ) { ++ $_ ; ++ $brc jos $koodi [ $_ ] eq '[' ; -- $brc jos $koodi [ $_ ] eq ']' ; } } else { seuraava ; } } elsif ( $koodi [ $_ ] eq ']' ) { if ( ! $cpu [ $i ]) { seuraava ; } else { ++ $brc if $koodi [ $_ ] eq ']' ; while ( $brc ) { -- $_ ; -- $brc jos $koodi [ $_ ] eq '[' ; ++ $brc jos $koodi [ $_ ] eq ']' ; } -- $_ ; } } }Esimerkki Brainfuck-tulkista, joka on kirjoitettu C++ :lla:
#include <iostream> #include <fstream> #sisällytä <vektori> #include <iteraattori> int main ( int argc , char ** argv ) { std :: fstream- tiedosto ( argv [ 1 ], std :: ios :: in ); std :: istreambuf_iterator < char > fstart ( tiedosto ), fend ; std :: vektori < char > itape ( fstart , fend ); tiedosto . sulje (); std :: vektori < char > mtape ( 30000 , 0 ); std :: vektori < char >:: iteraattori m = mtape . alkaa (); std :: vektori < char >:: iteraattori i = itape . alkaa (); int b = 0 ; for (; i != itape . end (); ++ i ) { kytkin ( * i ){ tapaus '>' : if ( ++ m == mnauha . loppu ()) { mtape . työntö ( 0 ); m = -mnauha . _ loppu (); } tauko ; case '<' : -- m ; tauko ; tapaus '+' : ++* m ; tauko ; case '-' : --* m ; tauko ; tapaus '.' : std :: cout << * m ; tauko ; case ',' : std :: cin >> * m ; tauko ; tapaus '[' : jos ( * m ) jatkaa ; ++ b ; kun ( b ) kytkin ( *++ i ){ tapaus '[' : ++ b ; tauko ; tapaus ']' : -- b ; tauko ; } tauko ; tapaus ']' : jos ( !* m ) jatka ; ++ b ; kun ( b ) kytkin ( *-- i ){ tapaus '[' : -- b ; tauko ; tapaus ']' : ++ b ; tauko ; } --minä ; _ tauko ; } } }Jokainen Brainfuck- ohjelmoinnin aloittelija kohtaa välittömästi seuraavat ongelmat:
Nämä ongelmat voidaan ratkaista.
Merkitse @(k) k solun siirtymä oikealle, jos k>0, ja vasemmalle, jos k<0 Vastaavasti @(k) = >… k kertaa …> tai <… -k kertaa …<Brainfuckia ei käytetä lähes koskaan käytännön ohjelmointiin (lukuun ottamatta yksittäisten harrastajien työtä), ja sitä käytetään pääasiassa pulma- ja kilpailuongelmiin.
Huomautuksia: 1. Erityisesti mOO-komennon toiminnallisuutta varten sen komentojen sisäiset koodit [2] tuodaan COW-kieleen , taulukossa ne on merkitty erilliseen sarakkeeseen. 2. Joukkueen poissaolo ilmoitetaan poissaoloksi .
Aivojuttu | Ok! | LEHMÄ | COW koodi | Kuvaus |
] | Okei? Ok! | moo | 0 | Jakson loppu |
< | Okei? OK. | mOo | yksi | Edellinen solu |
> | OK. Okei? | moO | 2 | Seuraava solu |
ots. | ots. | mOO | 3 | Suorita arvo nykyisessä solussa komentona vastaavalla koodilla välillä 0 - 11; koodi 3 aiheuttaa silmukan |
ots. | ots. | Moo | neljä | Jos nykyisen solun arvo on nolla, kirjoita se näppäimistöltä; jos nykyisen solun arvo ei ole nolla, näytä se näytöllä |
- | Ok! Ok! | MOo | 5 | Nykyisen solun arvoa pienennetään yhdellä |
+ | OK. OK. | MoO | 6 | Nykyisen solun arvoa kasvatetaan yhdellä |
[ | Ok! Okei? | MO | 7 | Silmukan aloitus (COW:ssa on ominaisuus - silmukan ensimmäinen komento ohitetaan) |
[-] | ots. | OOO | kahdeksan | Nollaa nykyisen solun arvon |
ots. | ots. | MMM | 9 | Jos rekisteri on tyhjä, kopioi nykyisen solun arvo siihen, muussa tapauksessa kopioi rekisterin sisältö soluun ja tyhjennä rekisteri |
. | Ok! OK. | OOM | kymmenen | Näyttää nykyisen solun arvon |
, | OK. Ok! | oho | yksitoista | Kysy nykyisen solun arvo |
Toinen kuvaus tämän kielen monista murteista löytyy esoteeristen kielten wiki-tietosanakirjasta [3]
Ohjelmointikielet | |
---|---|
|