Brainfuck

De la Wikipedia, enciclopedia liberă.
Salt la navigare Salt la căutare

Brainfuck (literalmente „dracu-ți creierul”) este un limbaj ezoteric de programare pentru computer creat de Urban Müller în jurul anului 1993 . Limbajul este uneori numit Brainf * ck , Brainf *** sau chiar doar BF pentru a evita ofensarea sensibilității altora.

Structura limbajului

Scopul lui Müller a fost de a crea un limbaj de programare complet simplu pentru o mașină Turing care ar putea fi implementată cu cel mai mic compilator posibil. Limba constă din opt instrucțiuni. Versiunea 2 a compilatorului original, scrisă pentru Amiga 68000 , ocupă doar 240 de octeți . A fost inspirat de limbajul FALS , un alt limbaj de programare ezoteric , al cărui compilator a ocupat 1024 de octeți.

După cum sugerează și numele, programele scrise în Brainfuck tind să fie greu de înțeles. Cu toate acestea, Brainfuck este un limbaj complet Turing și poate fi utilizat pentru a implementa orice algoritm executabil cu o mașină Turing . Ignorând dificultatea enormă în programarea anumitor algoritmi cu Brainfuck, este cu siguranță posibil să scrieți codul aferent.

Limbajul se bazează pe un model foarte simplu format dintr-o matrice de octeți zero inițializată, un pointer de matrice (inițializat pentru a indica primul octet al matricei) și fluxuri de doi octeți pentru intrare și ieșire.

Instrucțiuni

Instrucțiunile de limbă sunt opt, fiecare constă dintr-un singur caracter și sunt:

Caracter Sens
> creșteți indicatorul
< scade indicatorul
+ creșteți octetul adresat de indicator
- diminuează octetul adresat de indicator
. ieșire din octetul adresat de pointer (ASCII)
, intrare în octetul adresat de pointer (ASCII)
[ sare înainte la instrucțiune după ] corespunzătoare dacă octetul adresat de indicator este zero
] sare înapoi la instrucțiune după [ dacă octetul adresat de indicator nu este zero

Alternativ, ] poate fi înțeles ca „săriți înapoi la [ ” corespunzător. Astfel, este mai scurt, dar mai puțin simetric și mai puțin eficient în timp. Cu toate acestea, cele două versiuni produc un comportament echivalent cu fiecare program Brainfuck.

O a treia versiune echivalentă slab considerată este: [ înseamnă "sări înainte la corespondent ] " și ] înseamnă "sări înapoi la instrucțiunea care urmează corespondentului [ dacă octetul la indicator nu este zero".

Sursele pentru Brainfuck pot fi transcodate în C folosind următorul tabel de substituție, presupunând că ptr este de tip unsigned char* :

Brainfuck C.
> ++ptr;
< --ptr;
+ ++(*ptr);
- --(*ptr);
. putchar(*ptr);
, *ptr = getchar();
[ while (*ptr) {
] }

Exemple

Buna lume !

Următorul cod arată „Hello World!” pe ecran și înfășurați cursorul

 ++++++++++
[
> +++++++> ++++++++++> +++> + <<<< -
]
> ++. Bucla inițială (după imprimarea unui H)
> +. Și
+++++++. L
. L
+++. sau
> ++.
<< +++++++++++++++++.
>.
+++.
------.
--------.
> +.
>.

Pentru a menține lista lizibilă, o nouă linie este pornită după fiecare punct, reprezentând comanda de ieșire. Literele H , e , l , l și o au fost inserate în cod doar ca comentarii . Brainfuck ia în considerare toate caracterele, cu excepția + - <> [],. ca comentarii, astfel încât să nu fie necesară o sintaxă specială pentru a indica un comentariu.

Bucla de pe prima linie stabilește valoarea inițială a matricei: a[1] = 70 (lângă valoarea ASCII pentru caracterul „H”, 72), a[2] = 100 (lângă „e”, 101), a[3] = 30 (aproape de '', 32) și a[4] = 10 ( linie nouă , linie nouă ). Bucla funcționează înmulțind valoarea a[0] , 10 , salvând rezultatul în celelalte celule. La sfârșitul buclei, indicatorul către matrice este zero. >++ mărește indicatorul cu unul, indicând a[1] care este 70 , apoi adaugă două la acea valoare, rezultând 72 fiind valoarea pentru caracterul ASCII al literei majuscule H. Punctul de la capătul liniei indică ieșirea, determinând afișarea acesteia.

Următoarea linie mută indicatorul în matrice cu o poziție în sus, apoi adaugă una. a[2] este acum 101 , o „e” minusculă, care este apoi afișată cu instrucțiunea de ieșire.

Deoarece litera „l” este a șaptea literă după „e”, pentru a afișa „o adăugăm șapte ( +++++++ ) la indicatorul curent și afișăm ieșirea de două ori.

„o” este a treia literă după „l”, astfel încât să incrementăm valoarea matricei de trei ori și să obținem rezultatul.

Restul programului continuă exact așa cum s-a descris până acum. Pentru spațiu și literă mare, sunt selectați indicatori diferiți, care sunt apoi incrementați sau decrementați după cum este necesar.

Simplu

Buclă simplă

 , [.,]

O buclă continuă care preia textul de intrare de la tastatură și îl scrie pe ecran. Rețineți că se presupune că celula este setată la 0 atunci când o comandă ' , ' este executată după sfârșitul intrării (uneori numită sfârșitul fișierului sau „EOF”); implementările diferă în acest punct. Pentru implementările care setează celula la -1 sau EOF sau care nu modifică valoarea celulei, acest program ar trebui să fie scris " ,+[-.,+] " Sau " ,[.[-],] " respectiv.

Manipularea indicatorului

 >, [.>,]

O versiune a ultimului exemplu care salvează, de asemenea, toate intrările dintr-o matrice pentru utilizare ulterioară, mutând pointerul de fiecare dată.

Adăuga

 [-> + <]

Aceasta adaugă locația curentă (distructiv, este zero) la următoarea locație.

Declarații condiționate

 , ---------- [----------------------., ----------]

Acest exemplu va prelua intrarea cu litere mici de la tastatură și o va transforma în majuscule. Pentru a ieși, apăsați tasta Enter.

În primul rând, vom introduce primul caracter folosind comanda , si scade imediat 10 din el. (Multe, dar nu toate, programele Brainfuck folosesc 10 pentru a indica tasta de returnare a transportului.) Dacă utilizatorul apasă enter, instrucțiunea loop ( [ ) va sări după sfârșitul buclei, deoarece vom seta primul octet la zero. Dacă caracterul introdus nu era 10, vom presupune că a fost o literă mică și vom introduce bucla, în care vom scădea încă 22 din ea, pentru un total de 32, care este diferența dintre o literă ASCII minusculă și majusculă scrisoare corespunzătoare.

Mai târziu îl vom afișa. Acum inserăm următorul caracter și scădem din nou 10. Dacă acest caracter ar fi o linie , ieșim din buclă; în caz contrar, ne vom întoarce la începutul buclei, vom scădea încă 22, o vom afișa și așa mai departe. Când ieșim din buclă, programul se termină, deoarece nu mai există comenzi.

Copiați un octet

Brainfuck nu include nicio operațiune de copiere a octeților. Acest lucru trebuie făcut cu constructe de bucle și operatori aritmetici. Mutarea unui octet este destul de simplă; mutarea valorii [0] la [1] se poate face după cum urmează:

 [-> + <]

Cu toate acestea, acest lucru resetează valoarea [0] la 0. Putem reseta valoarea [0] după copiere profitând de capacitatea de a copia o valoare în două locuri la un moment dat. Copierea valorii [0] în ambele [1] și [2] este simplă:

 [-> +> + <<]

Putem profita de acest lucru pentru a restabili valoarea [0]. Prin urmare, putem copia nedistructiv [0] în [1] (folosind [2] ca variabilă temporară) după cum urmează:

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

Complexe

Sumă

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

Acest program adaugă două numere dintr-o singură cifră și afișează rezultatul corect dacă este format și dintr-o singură cifră:

 4 + 3

7

(Acum lucrurile încep să devină puțin mai complicate. Ne putem referi la octeții din matrice ca [0], [1], [2] și așa mai departe.)

Primul număr este inserat în [0] și 48 este scăzut pentru a obține cifra corespunzătoare (codurile ASCII pentru numerele de la 0 la 9 sunt de fapt cele de la 48 la 57). Acest lucru se face punând un 6 în [1] și folosind o buclă pentru a scădea 8 din [0] numărul corespunzător de ori. (Aceasta este o metodă obișnuită de adunare sau scădere de numere mari.) Apoi, punem semnul sumă în [1]; introduceți în cele din urmă al doilea număr, suprascriind simbolul sumă.

Următorul ciclu [<+>-] face treaba reală, mutând al doilea număr peste primul, adăugându-le împreună și punând la zero [1]. La fiecare buclă, adaugă una la [0] și scade una din 1; deci [1] este în cele din urmă resetată la zero, iar suma adăugată la [0] este exact cea eliminată din [1]. O valoare returnată este apoi inserată în [1]. (Nu verificăm posibile erori la intrare.)

Apoi, indicatorul este mutat înapoi la [0], care este afișat. ([0] este acum un + (b + 48), deoarece nu am corectat b; această valoare este identică cu (a + b) + 48, ceea ce dorim.) Acum indicatorul este mutat în [1] , care conține rezultatul; este afișat în cele din urmă, terminând algoritmul

Multiplicare

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

Ca și exemplul anterior, dar face multiplicare, nu adunare.

Primul număr este inserat în [0], asteriscul și apoi al doilea număr este inserat în [1], iar ambele numere sunt corectate scăzând 48 din ele.

Acum intrăm în ciclul principal de multiplicare. Ideea de bază este că de fiecare dată prin aceasta scădem una din [0] și adăugăm [1] la totalul de rulare deținut în [2]. În special: primul ciclu intern se mută [1] la ambele [2] și [3], în timp ce se resetează [1]. (Aceasta este metoda de bază a înmulțirii unui număr.) Prima buclă interioară se deplasează [3] înapoi în [1], reducând la zero [3]. Apoi unul este scăzut din [0], iar bucla exterioară este terminată. La ieșirea din această buclă, [0] este zero, [1] continuă să conțină al doilea număr și [2] conține produsul celor două numere. (Am fost atenți să păstrăm primul număr, am putea adăuga unul la [4] de fiecare dată prin bucla exterioară, apoi să mutăm valoarea de la [4] înapoi la [1] mai târziu.)

Acum adăugăm 48 la produs, introducem un rezultat în [3], afișăm produsul folosind caracterele ASCII și apoi afișăm rezultatul pe care l-am stocat.

cometariu

Deoarece fiecare locație a matricei este specificată ca un octet, comanda - este de prisos și ar putea fi înlocuită cu 255 + comenzi. În mod similar, dacă matricea ar fi finită și circulară, <ar putea fi înlocuit cu comenzi (dimensiunea matricei - 1)>. Cu toate acestea, dimensiunea matricei trebuie să fie nelimitată pentru ca limba să fie completă Turing , altfel ar avea un număr finit de stări. (Tocmai din acest motiv nici măcar un PC modern nu este Turing - complet în sens strict).

Limbaje de programare similare

O listă de limbi similare:

Elemente conexe

linkuri externe

Informatică Portal IT : accesați intrările Wikipedia care se ocupă cu IT