Programmare con Arte n° 1

Da MelugWiki.

Jump to: navigation, search

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?!

thanks to: peteru && emitrax.
foobar fiblan
Personal tools