Programmare con Arte n° 1
Da MelugWiki.
Brainfuck
by foobar fiblan
A volte si esagera, e si arriva a fottersi il cervello: Brain Fuck! L'uomo non riuscirà mai a capire cosa realmente vuol dire semplicità. Se vi dicessi che esiste un linguaggio di programmazione con solo 1 byte di comandi (8 comandi) ed un compilatore con meno di 200 byte ci credereste?
Si chiama Brain Fuck, il nome dice tutto! Gli 8 comandi? Sono questi:
> Increment the pointer. < Decrement the pointer. + Increment the byte at the pointer. - Decrement the byte at the pointer. . Output the byte at the pointer. , Input a byte and store it in the byte at the pointer. [ Jump forward past the matching ] if the byte at the pointer is zero. ] Jump backward to the matching [ unless the byte at the pointer is zero.
The pointer
Ecco, una cosa che vi farà immenso piacere: Brainfuck si basa su un unico puntatore: "The Pointer"! A questo punto, credo che, almeno metà della gente intenzionata a leggere questa pagina non continuerà più a farlo, ricordando l'odio verso i puntatori!
The pointer è libero di muoversi su un array di 30000 bytes settati tutti inizialmente a zero ed è inizializzato a puntare, scusate il gioco di parole, all'inizio dell'array stesso. Per muoverlo useremo '<','>'.
Dificile a crederci ma questo linguaggio, grazie alle 8 istruzioni, è "Turing-complete" quindi, teroricamente, possiamo implementare di tutto. In realtà un linguaggio più "fuck", da cui in parte Brain Fuck deriva, è P`` che ha solo 6 istruzioni, ma lasciamolo perdere (per ora). Se volessimo fare dei confronti con il C, tanto per capire meglio il significato degli 8 comandi, ecco una tabella comparativa, considerate p definito come "puntatore ad un byte (char *p)":
> corrisponde a ++p;
< corrisponde a --p;
+ corrisponde a ++*p;
- corrisponde a --*p;
. corrisponde a putchar(*p);
, corrisponde a *p = getchar();
[ corrisponde a while (*p) {
] corrisponde a }
Stampiamo MeluG
Ok! Passo ad un esempio, così smettete immediatamente di leggere, non è per voi quest'articolo. Brain fuck è una forma d'arte di programmazione difficile da capire. A differenza dell'obfuscated C, visto nell'articolo precedente, brainfuck è qualcosa fra l'arte ed il delirio. E voi siete pronti al delirio? Ecco l'esempio:
++ ++ +++++ + + [ >+++
+ + + + > + + +
+ + +++ + > + + +++
+ + + + + > + +
+ + +++++ ++<<< <-]>. -----
->++.
>--.
>----.
<<<.
<++++++++++.
Copiate il codice, compilate ed eseguite. Il compilatore potete scaricarlo qui (nell'header trovate le istruzioni per crearlo): http://www.muppetlabs.com/~breadbox/software/tiny/bf.asm.txt Ma come è possibile? Partiamo dal presupposto che il codice di sopra è equivalente a questo:
+++++++++++[>+++++++>+++++++++>++++++++++>+++++++++++<<<<-]>.------>++.>--.>----.<<<.<++++++++++.
Riscriviamolo in un formato piu' leggibile:
01 +++++++++++ 02 [ 03 >+++++++ 04 >+++++++++ 05 >++++++++++ 06 >+++++++++++ 07 <<<<- 08 ] 09 >. 10 ------ 11 >++. 12 >--. 13 >----. 14 <<<. 15 <++++++++++.
Cosi' è molto semplice!? No? Per quelli con il void *cervello faccio seguire una c-like spiegazione:
char *p;
p=calloc(30000, sizeof( char));
01 *p=11;
02 while (*p) {
03 ++p;*p+=7;
04 ++p;*p+=9;
05 ++p;*p+=10;
06 ++p;*p+=11;
07 --p;--p;--p;--p;*p-=1;
08 }
09 ++p;putchar(*p);//'M'
10 *p-=6;//p[1]='G'
11 ++p;*p+=2;putchar(*p);//'e'
12 ++p;*p-=2;putchar(*p);//'l'
13 ++p;*p-=4;putchar(*p);//'u'
14 --p;--p;--p;putchar(*p);//'G'
15 --p;*p+=10;putchar(*p);//'\n'
Non vi piacciono i puntatori vero? Ok lo scrivo meglio, ma ricordate che non volete impegnarvi:
char *p;
p=calloc(30000,sizeof(char));
01 p[0]=11;
02 while (p[0]){
03 p[1]+=7;
04 p[2]+=9;
05 p[3]+=10;
06 p[4]+=11;
07 p[0]-=1;
08 }
09 putchar(p[1]);//'M'
10 p[1]-=6;//p[1]='G'
11 p[2]+=2;putchar(p[2]);//'e'
12 p[3]-=2;putchar(p[3]);//'l'
13 p[4]-=4;putchar(p[4]);//'u'
14 putchar(p[1]);//'G'
15 p[0]+=10;putchar(p[0]);//'\n'
Ora 'GNUrant avete capito Brain fuck?!
foobar fiblan