Impulzus

 
A Budapesti Műszaki és Gazdaságtudományi Egyetem Villamosmérnöki és Informatikai Kar Hallgatói Képviseletének lapja
Random cikkajánló

Téma

" téma az utcán hevert. Nem feküdt, hanem szó szerint elterült – már amennyire egy téma elterülhet."

A tegnap szörnyű

Unalom

„Nem emberek. Én tudom. Orvos vagyok, genetikus."

Eltévedni jó dolog

"Lesz egy hótúránk várfoglalással, meg eltévedéssel."

Majoros Péter

Irónia

avagy Re: A Schönherz Kolesz ajtaja...

Mi kérünk elnézést!

Itt jártunk: szélcsatorna

Különösen az olajválság adott jelentős lökést a nyugati fejlesztéseknek. Igen, nagy cégek kicsiny hazánkban végezték az autókhoz képest hátrafelé mozgó talajt szimuláló futószalaggal az első szélcsatornás tesztjeiket.

Egyetemes álom

"...kísért a BME, még mindig álmodom róla."

KSzK

Idióta programnyelvek 1. rész: a Brainfuck

Vannak nyelvek, amiket gyakorlatilag mindenki ismer legalább alapvető szintaxis szintjén, aki komolyabban foglalkozik a számítógépekkel: majd mindenki Pascalon tanult meg programozni, a nyílt forrású szoftverek 99%-át C-ben írták, a C++-t és a Java-t unalomig sulykolják minden OOP-oktatás során, szép technológiai buzzwordök a PHP és a Perl (mellesleg aki ismeri a C-t, az egy-két óra alatt megtanulja őket). Léteznek viszont ezeknél nagyságrendekkel érdekesebb (és legtöbbször teljesen elborult), ám méltatlanul elhanyagolt nyelvek. Tágítsuk a spektrumot, szélesítsük a horizontot, bővítsük a szemléletet meg hasonlók: tessék ledöbbenni, hogy mikben képesek az emberek programozni...

Aki túl van a FoNy-on, már biztosan találkozott vele, de valószínűleg a többiek is hallotak a Turing-gépről. Azért csak nagy vonalakban: a gép lényege, hogy van egy olvasó/író feje és egy mozgatható szalag alatta. Tud a szalagon léptetni, róla olvasni vagy írni és vannak belső állapotai, és az igazán szép benne az, hogy elviekben minden algoritmizálható probléma megoldható vele. Ehemm, igen, nos, érdemes eljátszani vele, jó kis agytorna (no meg Bach tanár úr kegyetlenebb vizsgáiban az utolsó feladat). Elméleti jelentősége az automataelmélet terén óriási, de hogy valaki ténylegesen erre tervezze meg valamely megoldandó feladatát, igen kevéssé valószínű (értsd: hülyeség). Ennek egy gyakorlati megvalósítására alkotta meg egy perverzebb pillanatában 1993 körül Urban Müller a legidegtépőbb programozási nyelvet, amit valaha írtak: a Brainfuckot. Pontosan annyit tud, mint egy Turing-gép, néhány apró "kényelmi" bővítéssel. Ez a csodálatos nyelv az alábbi nehezen megjegyezhető jelkészlettel bír:

< ill. > balra ill. jobbra léptet

+ ill. - növeli ill. csökkenti az aktuális pozíción álló

értéket

. ill. , kiírja/beír az aktuális pozíciót/pozícióra

[ és ] bővítés ciklusszervezéshez, elágazáshoz

(Ez ténylegesen úgy működik, hogy ]-nél ha az épp aktuális pozíción nemnulla érték áll, megkeresi a [-párját, és oda visszalép, [-nél ha nulla áll, megkeresi a ]-párját, és odalép.)

Igen, ez nyolc karakter. És igen, mivel ezekkel teljesen lefedi a Turing-gép lehetőségeit, minden számítási probléma megoldható ennyivel (a Neten fellelhető egy precíz bizonyítás is a nyelv "Turing-teljességéről"). Mielőtt bármi további fejtegetésbe belemennék, szeretnék idemásolni egy "Hello world!"-programot:

Tanulságos. Kezdj el próbálkozni vele, az első egy órában rettenetesen addiktív a dolog, az ember két-három szövegszerkesztő-ablakban forrasztgatja a különböző verziókat, egy negyedikben tartja az összehozott egyszerűbb összeadó-/szorzó-/feltételesen elágazó-sémákat és nagyon büszke magára, amikor két-három sor erejéig még kezelni tudja ezt a borzalmat. Aztán amikor az 5-6 C-kódsornyi hosszhoz kezd közelíteni a program, elkezdi érezni, miért is így hívják a nyelvet... egyszerűen kisül tőle az agya, hogy tökegyforma karakterek sorát próbálja átlátni...

Nézzünk csak végig, hogy hozzunk össze néhány egyszerűbb programrészletet! Kell még a BF fejlesztéshez tudni, hogy a szalag elemei kezdetben nullák, a hossza pedig megvalósítástól függ, általában kb. 32k (nem ez fog keresztbe tenni...). Talán a legegyszerűbb a nullázó rutin:

[-]

Ez addig lép vissza a csökkentő parancsra, amíg nem nulla áll az adott helyen. Bonyolítsuk meg egy picit:

[ > + < – ]

Jobbra lép, ott megnöveli az értéket, visszalép, ott csökkenti, és ha ott nem nulla, belekezd megint – azaz átmásolja eggyel jobbra az aktuális pozíción található "számot". Most csináljunk valami gyakorlatiasabbat, egy if-elágazást (a to(a) legyen az, hogy odalép az "a" helyre). Tehát:

to(a) [ feltételes utasítás to(a) [-] ]

Ez eddig könnyű volt, nyilvánvalóan egyszer lefut, ha "a" nem volt nulla. Hogy lesz ebből else is? Legyen két if-ünk, amiből a második (ami az else-nek fog megfelelni) pontosan akkor fog lefutni, ha az első nem. Állítsunk be egy átmeneti változót egyre az egész előtt, és az első if belsejében (ami akkor fut le, ha az eredeti érték "igaz" volt) nullázzuk ki, a második if pedig ezt az értéket vizsgálja:

to(a) < [-] + > [ feltételes utasítás to(a) < [-] > [-] ] < [ else-utasítások to(a) < [-] ]

Menjünk ezen végig lépésről lépésre! Odalép "a"-hoz, a tőle balra található mezőt kinullázza, majd beállítja egyre, ez lesz a temp-adatunk. Utána következik a fent látott if-séma, azzal a többlettel, hogy a lezárása előtt kinullázza a temp-mezőt is (hisz "a" igaz volt, az else-ágnak már nem szabad lefutnia!). Végül egyet balra lép a tempre, és ha nem futott le az if-ág és az nem lett kinullázva, elindul arra is egy normális if-séma. Kezd szép lenni, nem?

Mi kell még egy program megírásához? Nos, igen, kéne valamiféle ciklus is. Kezdjük a do-while-lal, az nagyon egyszerű:

to(t) [-] + [ ciklusmag to(a) ] to(t) [-]

Itt "t" egy segédváltozó, "a" a feltételes változó, az elején "t"-t beállítjuk egyre, hogy biztosan belépjen a ciklusba (a do-while hátultesztelő), lefut a ciklusmag, a végén megvizsgálja, hogy "a" nemnulla-e, ha igen, visszalép. A végén csak visszanullázza "t"-t a szépség kedvéért. A "for" ennek csak speciális esete:

to(a) +++ [ ciklusmag to(a) – ]

(A mintapélda háromszor fut le.) Beállítunk egy mezőt az iterációk számára, jön egy [, majd a belső parancsok után visszalépünk az említett pozícióra, lecsökkentjük eggyel, és ha nem nulla, újrakezdjük. Kis szépséghiba, hogy a ciklus során a ciklusváltozó "ellentettje" lesz a-ban (visszafele számol), de ez körbejárható már.

Lehetne folytatni tovább a nyelvi elemek megtervezését, de azokat inkább a "kedves Olvasóra bízzuk ujjgyakorlat gyanánt". Egy jótanács: ne kezdj bele direkt "<>-+"-beirogatással nagyobb BF-projektbe, mert bele fogsz őrülni. Találj inkább ki valami primitív makró-nyelvet olyan bejegyzésekkel, mint itt volt a "to", és dobj össze egy Perl- vagy Python-scriptet, ami ezeket átfordítja Brainfuck-kóddá! Lehet találni ilyesmit a Neten, de azokat kb. annyi idő megérteni, mint írni egy sajátot.

Nem tudom, mikor indulhatott a Brainfuck-láz, de amikor három-négy éve először futottam össze a nyelvvel, már akkor is jópár oldal foglalkozott vele, lehetett találni tutorialokat, mintapéldákat. Mostanra viszont teljesen elszálltak néhányan, a teljesség igénye nélkül pár elborultabb Brainfuck-alkotás: BF'C fordító BF-ben, BF' .NET-fordító, Pi-számoló, GUI-s BF debugger, BF Apache-modul (írj CGI-t az oldaladhoz Brainfuckban!). Ha van kedved hozzá, megtalálhatod a közösséged.

gyp