"The Pragmatic Programmer" -kirjassa (jos et ole lukenut sitä, lopeta tämän artikkelin lukeminen ja tee se nyt!) sanotaan, että joka vuosi pitäisi oppia yksi uusi ohjelmointikieli.
Vaikka jotkut saattavat väittää, että se on liikaa vaivaa, voimme kaikki olla yhtä mieltä siitä, että se voi olla hyvä ajatus. Uuden kielen valitseminen opeteltavaksi ei ole niin helppoa. Emmehän halua käyttää aikaamme johonkin, jota emme ehkä koskaan käytä käytännössä? Mutta ehkä joskus meidän pitäisi tehdä poikkeus ja opetella jotain ihan vain huvin vuoksi? Haluan esitellä teille Brainfuck-kielen. Se on kieli, jonka voi oppia muutamassa minuutissa, joten ei ole ongelmaa, että sijoittaisit liikaa aikaasi turhaan. Voin myös luvata, että minkä tahansa ongelman ratkaiseminen Brainfuck-kielellä stimuloi aivojasi (kaikki v*ttuilut ovat vain bonusta ;)). Aloitetaan!Wikipedian mukaan:
Brainfuck on esoteerinen ohjelmointikieli jonka Urban Müller perusti vuonna 1993. Kieli koostuu vain kahdeksasta yksinkertaisesta komennosta ja käskyosoittimesta. Vaikka kieli on täysin Turing-pääteinen, sitä ei ole tarkoitettu käytännön käyttöön vaan ohjelmoijien haastamiseksi ja huvittamiseksi.
Kielen yleiskatsaus
Kuvittele äärettömän pitkä nauha (tai nauha), joka koostuu soluista, joista jokainen on alustettu arvoon 0. Lisäksi on liikkuva datan osoitin, joka osoittaa aluksi ensimmäiseen soluun. Lisäksi on kaksi tavuvirtaa syötettä ja tulostusta varten. Ohjeet suoritetaan peräkkäin, yksi kerrallaan. Kone pysähtyy viimeisen käskyn suorittamisen jälkeen.
Komento
Mitä se tekee?
>
siirtää datan osoitin seuraavaan soluun oikealla.
<
siirtää datan osoitin seuraavaan soluun vasemmalla.
+
nykyisen solun arvon lisääminen
–
nykyisen solun arvon pienentäminen
.
tulostaa osoitetun solun tavun ASCII-muodossa. koodi
,
Lue yksi tavu stdinistä ja tallenna sen arvo nykyiseen soluun.
[
jos nykyinen solu on 0, hyppää vastaavaan soluun ]
]
hyppää vastaavaan [
Kaikki muut merkit kuin ><+-.,[] jätetään huomiotta.
Tarkastellaan yksinkertaista esimerkkiä:
,+.
Sitä tulkitaan seuraavasti:
lue yksi tavu ja tallenna se nykyiseen soluun (solu0).
nykyisen solun arvon lisääminen (cell0 = cell0 + 1).
kirjoittaa nykyisen solun sisällön ulostuloon
Tuloksena yksi merkki luetaan syötteestä ja seuraava merkki tulostetaan ASCII-taulukosta.
Tulkki / kääntäjä
Ennen kuin kirjoitamme hyödyllisiä (?) ohjelmia Brainfuckilla, tarvitsemme tulkin tai kääntäjän. AFAIK, virallista sellaista ei ole, mutta se ei ole ongelma. Internetissä on kymmeniä epävirallisia. Voin suositella näitä kahta:
"Hello World!" pitäisi olla ensimmäinen ohjelma, jonka kirjoitamme uutta kieltä opetellessamme. Sen kirjoittaminen Brainfuck-kielellä on kuitenkin hieman vaikeampaa kuin muilla kielillä. Meidän on aloitettava jostain helpommasta... Kirjoitetaan ohjelma, joka tulostaa näytölle yhden kirjaimen "H" (niin jännittävää :D):
Miten se toimii? Se asettaa nykyisen solun arvon 72:ksi (72 askelta) ja tulostaa sen näytölle käyttämällä "." (H:n koodi on 72 ASCII:ssä). Nyt tiedät, mitä meidän pitäisi tehdä tulostaaksemme "Hello World!" näytölle, mutta ennen sitä teemme pienen refaktoroinnin. Kaikkien näiden "+"-merkkien kirjoittaminen vaatii liikaa kirjoittamista ja laskemista. Voimme lyhentää sitä käyttämällä [ ja ] silmukointia varten. Asettaaksemme arvon 72:een voimme esimerkiksi tehdä silmukan, joka kasvattaa arvoa 7 kertaa 10:llä. Näin saamme arvon 70. Lisäämällä 2 saadaan 72. Se näyttää tältä:
++++++++++ # set cell0 to 10
[ # Silmukka, kunnes solu0 on 0.
- # pienennä cell0
> # siirrä datan osoitin oikealle (solu1).
+++++++ # lisää solua1 7:llä.
# siirrä datan osoitin oikealle (solu1).
++ # kasvaa 2:lla
. # tulosta tulos
Olen lisännyt kommentteja tehdäkseni selväksi, miten kaikki toimii. Sama ohjelma ilman kommentteja:
++++++++++[->+++++++++.
Eikö se olekin kaunis? 🙂 .
Hei maailma!
Palataan takaisin "Hello World!" -ohjelmaamme. Voisimme asettaa ensimmäisen solun arvoksi 72 (H) ja tulostaa sen, asettaa toisen solun arvoksi 101 (e) ja tulostaa sen, asettaa kolmannen solun arvoksi 108 ja tulostaa sen ja niin edelleen. Tässä on tämän algoritmin toteutus:
Joo, vain 1120 tavua tulostamaan "Hello World!"... Mutta voimme tehdä parempaa! Sen sijaan, että käytämme uutta solua jokaista merkkiä varten, käytämme vain yhtä. Kirjoittaaksemme kirjaimen "e" (101) voimme käyttää uudelleen solun 0 (72) arvoa. Voimme kasvattaa sitä yhdellä 29 kertaa (101 - 72). Tulos on seuraava:
Se on vain 106 tavua ja se tulostaa uuden rivin loppuun! Hämmästyttävää.
Merkkijonon kääntäminen
Nyt olemme valmiita kirjoittamaan jotain haastavampaa. Kirjoitetaan ohjelma, joka lukee syötteen rivin ja tulostaa sen käänteisessä järjestyksessä. Ensimmäinen ongelma on lukea merkkejä ja pysähtyä uuden rivin merkkiin. Muista, että ei ole tauko, jos tai muita vastaavia lausuntoja. Meidän on käytettävä [ ja ]. Aloitetaan ohjelmalla, joka lukee kaikki syötteen merkit ja sijoittaa ne peräkkäisiin soluihin:
,[>,]
Se alkaa ensimmäisen merkin lukemisesta ja jatkuu viimeiseen merkkiin asti. , operaatio palaa 0. Se kuitenkin pyörii ikuisesti toteutuksessa, joka palauttaa jotain muuta kuin O osoitteessa EOF (kieli ei määrittele tätä käyttäytymistä). Miten voimme siis pysähtyä uuden rivin merkin kohdalla? Tässä on temppu:
+[++++++++++>,----------]
Aloitamme solun0 arvolla 1 varmistaaksemme, että silmukka suoritetaan vähintään kerran. Silmukassa kasvatamme nykyisen solun arvoa 10:llä, siirretään datan osoitin seuraavaan soluun, luetaan yksi merkki ja vähennetään sen arvoa 10:llä. Tällä tavoin, jos luetaan uusi rivimerkki (10 ASCII:ssä), ohjelma pysähtyy seuraavaan iteraatioon, muuten sen arvo palautetaan lisäämällä 10.
Tämän vaiheen jälkeen solumme näyttävät tältä:
11 C1 C2 C3 0* 0 0 0
Cn on n:s merkki syötteestä ja * on nykyisen datan osoittimen sijainti. Nyt meidän on aloitettava datan osoittimen siirtäminen vasemmalle ja tulostettava kaikki solut, kunnes saavutamme arvon 11. Tässä on minun näkemykseni tehtävästä:
Kun törmäsin Brainfuckiin, esoteeriseen ohjelmointikieleen, pidin sitä aluksi vain kikkailuna tai vitsinä. Tämä omituinen ja, kuten monet saattavat väittää, mielettömän vaikea kieli vaikutti minusta vain huvitukseksi tarkoitetulta. Mutta ajan myötä käsitykseni Brainfuckista muuttui dramaattisesti.
Brainfuckin arvoituksellinen luonne haastaa sinut ja saa sinut laajentamaan näkemystäsi seuraavista asioista ohjelmointikielet. Tämä esoteerinen kieli antaa sinulle mahdollisuuden arvostaa totuttujen korkean tason kielten kauneutta ja tarpeellisuutta. Se tuo esiin abstraktioiden, asianmukaisten nimeämiskäytäntöjen ja organisoidun muistin sijoittelun merkityksen ohjelmointikielten alalla. Tätä Brainfuck, jonka minimalistinen rakenne koostuu vain kahdeksasta yksinkertaisesta komennosta, ei tarjoa.
Brainfuck on Turingin täydellinen kieli, joka korostaa entisestään selkeän ja johdonmukaisen lähdekoodin merkitystä. Huolimatta siitä, että se on tunnustettu yhdeksi haastavimmista esoteerisista kielistä kirjoittaa ohjelmia, se ironisesti loistaa aloittelijan suosikkikielenä kaikille, jotka haluavat luoda oman Brainfuck-kääntäjän tai Brainfuck-tulkin. Syynä on sen komentosarjan yksinkertaisuus ja se, että se ei vaadi monimutkaista jäsennystä.
Brainfuck-ohjelman luominen on ainutlaatuista kahdella tavalla. Ensinnäkin sinun on sopeuduttava yhden muistin osoittimen käyttöön, mikä pakottaa sinut ajattelemaan lähdekoodia eri tavalla. Toiseksi sinulla on "nollavaihtoehto" eli mahdollisuus palauttaa muistisolu nollaan, mikä on ominaisuus, joka ei ole yleinen muissa virallisissa ohjelmointikielissä.
Oppimisen kannalta Brainfuckissa on enemmän kuin mitä silmä näkee. Kun aikaa on riittävästi ja ajattelutapa on oikea, on mahdollista kirjoittaa sama ohjelma monin eri tavoin eri Brainfuck-koodeja käyttäen. Tämän matkan loppupuolella on kyse kekseliäisyydestä ja uusien, luovien tapojen löytämisestä sen kuuden symbolin hyödyntämiseen.
Vaikka Brainfuck-tulkit ovatkin minimalistisia, ne antavat sinulle syvällisen käsityksen siitä, miten koodi toimii, mitä ohjelma tulostaa ja mikä on Turingin täydellisen kielen taustalla oleva mekaniikka. Loppujen lopuksi Brainfuck ei ole vain yksi esoteerinen ohjelmointikieli. Se on aivan uusi ulottuvuus, erilainen näkemys siitä, miten näemme, ymmärrämme ja kirjoitamme ohjelmia.