Kirjautuminen

Tunnus
Salasana

Haku

Pikalinkit

Kilpailu

Ohjelmoi tekoäly!
Päättyy 10.8. klo 20:00!

Opasarkisto: Brainfuck: Brainfuck

Kirjoittaja: Metabolix. Vuosi: 2006.

Brainfuck on yksinkertainen, rajoittunut ja tehoton ohjelmointikieli, jolla on turha odottaa saavansa aikaan oikeastaan mitään hyödyllistä. Sillä voi kaikesta huolimatta hämmästyttää muita ja viihdyttää aivojaan: koodi ei juuri koskaan ole selkeää, ja pienetkin asiat vaativat suuren määrän koodia, josta ei voi nopealla vilkaisulla ymmärtää käytännössä mitään.

Mistä kääntäjä?

Brainfuck-tietoa sekä kunnollisia tulkkeja ja kääntäjiä löytyy Internetistä suhteellisen niukasti. Ohjelmointiputkassa on kuitenkin JavaScriptilla toteutettu Brainfuck-tulkki, jolla kaikkia oppaan koodeja voi helposti testata. Koodivinkkeihin on päätynyt myös eräs C-kielinen toteutus. Tulkki on helppo tehdä itsekin, jos osaa jotain toista ohjelmointikieltä: kaikki tarvittava Brainfuckista kerrotaan tässä oppaassa.

Perusteet

Brainfuck-ohjelman käytössä on yleensä 30000 muistipaikkaa, jotka ovat kooltaan yleensä yhden tavun; joissain toteutuksissa määrä tai koko voi kuitenkin poiketa tästä. Kussakin muistipaikassa on yksi kokonaisluku, ohjelman alussa aina nolla. Kielen perusoperaatiot ovat käsiteltävän muistipaikan vaihtaminen (merkit < ja >), arvon muuttaminen yhdellä (merkit + ja -), paikassa olevan arvon tulostaminen ASCII-merkkinä (.) ja merkin lukeminen muistipaikkaan (,) sekä silmukka ([]), jota toistetaan niin kauan, kuin silmukan alussa valittuna olevan muistipaikan arvo on nollasta poikkeava. Kieli koostuu ainoastaan näistä kahdeksasta merkistä, ja kaikki muut merkit jätetään huomiotta. Kommentteja voi siis vapaasti kirjoittaa koodin sekaan, kunhan ne eivät vahingossa sotke oikeaa koodia.

Muistipaikan vaihto: merkit < ja >

Suurempi kuin ja pienempi kuin -merkit on hyvä käsittää nuolina vasemmalle ja oikealle. Ne vaihtavat valittua muistipaikkaa yhden jompaankumpaan suuntaan. Jos näin päädytään 30000 tavun muistitaulun ulkopuolelle, ohjelma voi toteutuksesta riippuen kaatua tai hypätä taulukon vastakkaiseen reunaan. Aluksi on valittuna vasemmanpuoleisin muistipaikka. Jokainen voi itse päättää, onko se ensimmäinen vai nollas muistipaikka, mutta tässä oppaassa sitä kutsutaan nollanneksi.

Tämä yksinkertainen ohjelma siirtyy ensin kolme muistipaikkaa eteenpäin ja sitten kolme taaksepäin eli takaisin lähtöpisteeseensä.

>>> <<<

Arvon muuttaminen: merkit + ja -

Plus- ja miinus-merkit korottavat tai vastaavasti laskevat valitun muistipaikan arvoa yhdellä. Koska muistipaikka on tavun kokoinen, se sisältää arvon väliltä [-128, 127] tai vaihtoehtoisesti [0, 255], miten kukin sen haluaa tulkita. Arvoalueen ylittyessä muistipaikka pyörähtää ympäri. Ohjelman aluksi kaikki muistipaikat on asetettu nollaan.

Tämä ohjelma asettaa ohjelman ensimmäisiin muistipaikkoihin arvot 0, 1, 2 ja 3. Arvoa 0 ei toki tarvitse erikseen asettaa.

> + > ++ > +++

Tiedonsiirto: merkit . ja ,

Piste tulostaa muistipaikan arvon, ja pilkku lukee sen. Muistipaikat ovat tavun kokoisia, joten yksi muistipaikka on yksi merkki. Arvo tulostuukin vastaavana merkkinä, joka voi riippua käytettävästä merkistöstä. Tyypillisesti A-kirjain on lukuarvoltaan 65, numero 0 puolestaan on 48.

Näin pyydetään käyttäjältä neljä merkkiä ja tulostetaan ne takaisin käänteisessä järjestyksessä:

,>,>,>,
.<.<.<.

Silmukka: merkit [ ja ]

Hakasulut määrittävät silmukan. Alun hakasulun kohdalla tarkistetaan aina, onko valittu muistipaikka nolla. Jos se on, hypätään silmukan yli. Jos ei, suoritetaan silmukka. Silmukan lopettavasta hakasulusta hypätään takaisin alun hakasulkuun. Usein on tarkoituksenmukaista palata silmukan lopuksi samaan muistipaikkaan, josta lähdettiin; silmukka ei tee sitä omin avuin.

Tämä esimerkkiohjelma tulostaa luvut nollasta yhdeksään. Ensin asetetaan nollapaikan arvoksi kymmenen: silmukka pitää suorittaa kymmenen kertaa. Sitten asetetaan ykköspaikan arvoksi numeron nolla ASCII-koodi eli 48. Silmukassa vähennetään aina nollapaikkaa, tulostetaan ykköspaikan arvo ja korotetaan sitä. Kymmenennen kerran jälkeen nollapaikassa on nolla, joten silmukka loppuu.

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

Lukujen yhteenlasku

Yhteenlasku on työlästä puuhaa. Koska muistipaikan arvoa ei saa mitenkään kokonaisuudessaan siirrettyä kerralla, se pitää siirtää toiseen paikkaan ykkönen kerrallaan. Yhteenlasku onnistuu siirtämällä näin kahden muistipaikan arvot samaan muistipaikkaan. Tässä pienessä esimerkissä lasketaan yhteen kolmonen ja nelonen. Ensin siis laitetaan nollapaikkaan kolme ja ykköspaikkaan neljä. Sitten silmukassa vähennetään nollapaikasta ja lisätään kakkos- ja nelospaikkoihin, kunnes nollapaikka on nolla. Näin alkuperäinen arvo on yhä muistissa mutta nollapaikan sijaan kahdessa muussa. Seuraavaksi siirretään ykköspaikan arvo kakkos- ja kolmospaikkoihin, minkä jälkeen kakkospaikan arvo on seitsemän, kolmospaikan neljä ja nelospaikan kolme. Lopuksi jokaiseen näistä lisätään nollan ASCII-arvo 48, jotta saadaan aikaan tulostuskelpoista materiaalia, nimittäin Pikku Kakkosen postilokeron numero.

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

Mutkikkaampi esimerkki

Tässä on yksinkertainen ohjelma, joka laskee Fibonaccin lukuja ja tulostaa ne oktaalimuodossa. Ohjelmassa on C++-tyylisiä kommentteja. Koska Brainfuck käsittelee koodista kaikki tuntemansa merkit, kaikki plussat ja miinukset on täytynyt ilmaista kommenteissa muulla tavalla.

// Tulostetaan 1 ja 1
// Ykkönen nollapaikkaan ja välilyönti paikkaan m13
// Tulostetaan "1 1"
++++++++++++++++ ++++++++++++++++ ++++++++++++++++ + .
>>>>>>>>>>>>> ++++++++++++++++ ++++++++++++++++ .
<<<<<<<<<<<<< .

[-]                 // Nollapaikkaan nolla
+++++               // Montako kertaa lasketaan kaksi lukua?
>+ >+ <<            // m1 = 1   ja   m2 = 1

[->                 // while (m0)   valitaan m1

// Lukujen liikkeet; & tarkoittaa plussaa
// m1     m2     m3
// a      b
// a&b           b
//        a&b    a & 2b
// a&b           a & 2b
// a&b    a & 2b

>[-<+>>+<]          // m1 &= m2   ja   m3 &= m2   ja   m2 = 0
<[->+>>+<<<]        // m2 &= m1   ja   m4 &= m1   ja   m1 = 0
>>>[-<<<+>>>]       // m1 &= m4   ja   m4 = 0
<[-<+>]>            // m2 &= m3   ja   m3 = 0

// Siirretään luvut sopivasti oktaalimuotoon muuttamista varten
>[-]>[-]>[-]>[-]             // m5 m6 m7 m8 = 0
>[-]>[-]>[-]>[-]             // m9 m10 m11 m12 = 0
<<<<<<<<<<<[->>>>+>+<<<<<]   // m5 = m6 = m1   ja   m1 = 0
>>>>>[-<<<<<+>>>>>]          // m1 = m6   ja   m6 = 0
<<<<[->>>>>>>+>+<<<<<<<<]    // m9 = m10 = m2   ja   m2 = 0
>>>>>>>>[-<<<<<<<<+>>>>>>>>] // m2 = m10   ja   m10 = 0
<<<<<                        // valitaan m5

// Muunnetaan m5 oktaaleiksi paikkoihin m6 m7 m8 ja tulostetaan
// (m6 = m5)   ja   (m7 = 4 * m5)   ja   (m8 = 32 * m5)   ja   (m5 = 0)
// Eli (m8 / 32 = m5 mod 8)   ja   (m7 / 4 = m5 mod 64)
[->+>++++>++++++++++++++++++++++++++++++++<<<]
// (m5 = m7 / 4)   ja   (m6 = m6 miinus m7 / 4)   ja   (m7 = 0)
>>[----<<+>->]
// (m7 = m8 / 32)   ja   (m8 = 0)
>[--------------------------------<+>]
// (m8 = m7)   ja   (m5 = m5 miinus m7)   ja   (m7 = 0)
<[->+<<<->>]
// (m7 = m6 / 8)   ja   (m6 = 0)
<[-------->+<]
// (m6 = m5 / 8)   ja   (m5 = 0)
<[-------->+<]
// (m5 = m7 / 8)   ja   (m7 = 0)
>>[--------<<+>>]
// tulostettavaan muotoon
++++++++++++++++++++++++++++++++++++++++++++++++
[-<<+>+>>+<]
// Tulostetaan väli m13:stä ja sitten oktaaliluku
>>>>>>.<<<<<<
<<.>.>>.

// Sama toiselle luvulle paikoissa m9 m10 m11 m12
>[->+>++++>++++++++++++++++++++++++++++++++<<<]
>>[----<<+>->]
>[--------------------------------<+>]
<[->+<<<->>]
<[-------->+<]
<[-------->+<]
>>[--------<<+>>]
++++++++++++++++++++++++++++++++++++++++++++++++
[-<<+>+>>+<]
>>.<<
<<.>.>>.

// Takaisin paikkaan m0 ja silmukan alkuun
<<<<<<<<<<<
<]

Tässä on vielä sama koodi tiiviimmässä muodossa:

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

Koodivinkki Fibonaccin sarja sisältää yksinkertaisemmin vain lukujen laskennan ilman muunnosta oktaalimuotoon.

Loppusanat

Siinä oli Brainfuck. Se on erittäin vaikea kieli, jos sillä haluaa todella saada jotakin aikaan. Erityisen hyvin se soveltuu aivojumppaan, koska yksinkertaisiakin asioita joutuu pähkäilemään melkoisesti.

Lisätietoa sekä runsaasti linkkejä löytyy mm. esoteerisiin kieliin erikoistuneelta sivustolta esolangs.org.

Lauri Kenttä, 26.8.2006

Kommentit

BlueByte [27.08.2006 19:10:47]

Lainaa #

liekö turhempaa kieltä olemas

M2tias [27.08.2006 22:26:02]

Lainaa #

Varmasti on, mutta kukaan ei halua tehdä opastakaan niille.

BlueByte [28.08.2006 17:57:38]

Lainaa #

liekö turhempaa opasta olemas?

FooBat [28.08.2006 21:44:38]

Lainaa #

Kieli on itsessään varsin yksinkertainen, mutta jos sillä haluaa tehdä jotain isompaa, pitää yleensä turvautua jonkinlaisiin makrolaajennuksiin.
http://www.iwriteiam.nl/Ha_bf_intro.html
http://www.cs.tufts.edu/~couch/bfmacro/

Makrojen avulla bf-ohjelmointi näyttää jo varsin siedettävältä, mutta siinä tietenkin menetetään hiukan haasteellisuutta.

arcatan [01.09.2006 15:45:13]

Lainaa #

Vaadin seuraavaksi Malebolge-opasta!

moptim [01.09.2006 21:05:05]

Lainaa #

Se on Malbolge, ja voi olla kivakin idea. Chef olisi myös kiva...

Jorgga [02.09.2006 20:39:49]

Lainaa #

Mielenkiintosta koodia :/ kuka tollasen vois oppii? :O

Juhko [02.09.2006 21:22:32]

Lainaa #

aika mz:ttaa

Metabolix [04.09.2006 06:45:29]

Lainaa #

FooBatin linkit ovatkin varsin mainioita apuvälineitä, lisäsin ne oppaaseen. Kiitokset niistä.

hmmp [19.09.2006 16:45:50]

Lainaa #

Ihana kieli. Ei ainakaan tuota ongelmia muistaa käskyjä. :D

moptim [27.09.2006 19:51:40]

Lainaa #

Metabolix (Brainfuck-opakseen) kirjoitti:

Brainfuck on erittäin yksinkertainen, rajoittunut ja melko tehoton ohjelmointikieli.

turing täydellinen

Quirzo [27.09.2006 21:43:35]

Lainaa #

No huh huh. Onpas siinä jännä ohjelmointikieli

pienipoika [03.10.2006 23:48:04]

Lainaa #

ahahah :D ihan hauska. voikos tällä tehdä mitään tekstinkäsittelyä välimuistissa kummempaa? :P

pienipoika [03.10.2006 23:51:30]

Lainaa #

sattuisikos tälle kielelle muuten olemaan kääntäjää? ettei tarvitsisi aina tulkin kanssa sählätä? :P

pienipoika [03.10.2006 23:55:00]

Lainaa #

ei hitto kyllä repee perse ton vikan esimerkin kanssa :D

tesmu [24.11.2006 17:40:52]

Lainaa #

win32: http://koodataan.aineissa.com/brain_win32.txt
*nix: http://koodataan.aineissa.com/brain.txt
http://koodataan.aineissa.com/b .txt
Siinä oma tulkki kutsun sitä b++ koska siinä on pirusti enemmän ominaisuuksia ku aidossa alkuperäisessä brainfuckissa... syntaksilista ei ole tällähetkellä ajantasalla mutta tänään ajattelin korjata asian... Tässä haaste tehkää minun tulkilla alkuperäinen brainfuck tulkki ^^

Codeprofile [10.12.2006 18:26:29]

Lainaa #

Löytyyköhän tästä maailmasta enään vaikeempaa kieltä?!

Toi nimi muuten sopii sille.

renni [12.01.2007 20:46:28]

Lainaa #

Jos haasteellista kieltä etsitte niin Whitespace on myös mielenkiintoinen. Koodi on ainakin nättiä luettavaa. :)

Dude [04.08.2007 14:57:31]

Lainaa #

Mitä tuolla tekee?

Metabolix [04.08.2007 15:28:09]

Lainaa #

Hajottaa päänsä. :) Ja luultavasti kehittää työmuistiaan.

aegis [04.09.2007 16:37:45]

Lainaa #

Codeprofile kirjoitti:

Löytyyköhän tästä maailmasta enään vaikeempaa kieltä?!

Löytyy. Malbolge.

groovyb [13.12.2007 19:46:32]

Lainaa #

This Malbolge program displays "Hello, world."

(=<`:9876Z4321UT.-Q+*)M'&%$H"!~}|Bzy?=|{z]KwZY44Eq0/{mlk**
hKs_dG5[m_BA{?-Y;;Vb'rR5431M}/.zHGwEDCBA@98\6543W10/.R,+O<

näin. ei mikään paha kieli.

täältä (http://www.99-bottles-of-beer.net/language-malbolge-375.html) löytyy malbogeksi kirjoitettuna "99 bottles of beer" -laulun sanat.

Sami [25.01.2008 22:11:16]

Lainaa #

Heh, tämä sivu näköjään pääsi MBnetin päivän linkiksi tänään. :)

vehkis91 [07.07.2008 20:08:39]

Lainaa #

Tää ainakin on vaikea kieli...

Tommittaja [29.12.2008 13:25:15]

Lainaa #

tässä linkissä on laulun sanat kirjoitettu sillä Malbolgella.. =)

http://www.99-bottles-of-beer.net/language-malbolge-995.html

Hankalaa...

JAMSUO93 [08.01.2009 16:36:42]

Lainaa #

on aika kauhea ohjelmointikieli toi brainfuck ja mikä nimikin!!!

janijohannes [14.03.2009 14:53:53]

Lainaa #

Ihan vain vinkkinä, kertolasku brainfuckilla:

>+++
[->+++[-
  >+ 3*3
<]<]
>>>++++++++++
[-<+++++>]
<--. // 3*3=9

Eki Lehtimäki [29.01.2010 00:03:28]

Lainaa #

Mainio kieli ja erinomainen opas! Kiitoksia.

Innostuin googlettamaan aihetta vähän lisää ja löysin kaksi linkkiä joista on suuri apu brainfuck-tiedon, -kääntäjien ja -tulkkien niukkuuteen:

http://esolangs.org/wiki/Brainfuck
http://www.dmoz.org/Computers/Programming/Languages/Brainfuck/

Ensimmäinen sisältää hyvin kirjoitettua tietoa kielestä ja kattavan linkkilistan, jälkimmäinen taas linkkejä tulkkeihin ja kääntäjiin.

Kirjoita kommentti

Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.

Muista lukea keskustelun ohjeet.
Tietoa sivustosta