1. Conceptos básicos
Para entender Brainfuck debes imaginar una variedad infinita de celdas inicializadas por 0
cada una.
...[0][0][0][0][0]...
Cuando se inicia el programa Brainfuck, apunta a cualquier celda.
...[0][0][*0*][0][0]...
Si mueve el puntero hacia la derecha, >
lo está moviendo de la celda X a la celda X + 1
...[0][0][0][*0*][0]...
Si aumenta el valor de la celda +
, obtiene:
...[0][0][0][*1*][0]...
Si vuelve a aumentar el valor de la celda +
, obtiene:
...[0][0][0][*2*][0]...
Si disminuye el valor de la celda -
, obtiene:
...[0][0][0][*1*][0]...
Si mueve el puntero hacia la izquierda <
, está moviendo el puntero de la celda X a la celda X-1
...[0][0][*0*][1][0]...
2. Entrada
Para leer el carácter se usa la coma ,
. Lo que hace es: lee el carácter de la entrada estándar y escribe su código ASCII decimal en la celda real.
Eche un vistazo a la tabla ASCII . Por ejemplo, el código decimal de !
es 33
, mientras que a
es97
.
Bueno, imaginemos que la memoria de su programa BF se ve así:
...[0][0][*0*][0][0]...
Suponiendo que la entrada estándar significa a
, si usa el ,
operador de coma , lo que hace BF es leer a
el código ASCII decimal 97
en la memoria:
...[0][0][*97*][0][0]...
Generalmente quieres pensar de esa manera, sin embargo, la verdad es un poco más compleja. La verdad es que BF no lee un carácter sino un byte (cualquiera que sea ese byte). Déjame mostrarte un ejemplo:
En linux
$ printf ł
huellas dactilares:
ł
que es un carácter polaco específico. Este carácter no está codificado por codificación ASCII. En este caso, es la codificación UTF-8, por lo que solía ocupar más de un byte en la memoria de la computadora. Podemos probarlo haciendo un volcado hexadecimal:
$ printf ł | hd
que muestra:
00000000 c5 82 |..|
Los ceros están compensados. 82
es el primero y el c5
segundo byte que representa ł
(en el orden en que los leemos).|..|
es una representación gráfica que no es posible en este caso.
Bueno, si pasa ł
como entrada a su programa BF que lee un solo byte, la memoria del programa se verá así:
...[0][0][*197*][0][0]...
¿Por qué 197
? Bueno, 197
decimal es c5
hexadecimal. ¿Te parece familiar? Por supuesto. Es el primer byte de ł
!
3. Salida
Para imprimir el carácter se usa el punto. .
Lo que hace es: Suponiendo que tratamos el valor real de la celda como un código ASCII decimal, imprime el carácter correspondiente en la salida estándar.
Bueno, imaginemos que la memoria de su programa BF se ve así:
...[0][0][*97*][0][0]...
Si usa el operador de punto (.) Ahora, lo que hace BF es imprimir:
una
Porque a
el código decimal en ASCII es 97
.
Entonces, por ejemplo, un programa BF como este (97 más 2 puntos):
++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++ ..
Aumentará el valor de la celda a la que apunta hasta 97 y lo imprimirá 2 veces.
Automóvil club británico
4. Bucles
En BF, el bucle consta de un comienzo [
y un final de bucle ]
. Puede pensar que es como en C / C ++, donde la condición es el valor real de la celda.
Eche un vistazo al programa BF a continuación:
++[]
++
incrementa el valor real de la celda dos veces:
...[0][0][*2*][0][0]...
Y []
es como while(2) {}
, entonces es un bucle infinito.
Digamos que no queremos que este bucle sea infinito. Podemos hacer por ejemplo:
++[-]
Entonces, cada vez que un bucle se repite, disminuye el valor real de la celda. Una vez que el valor real de la celda 0
finaliza el ciclo:
...[0][0][*2*][0][0]... loop starts
...[0][0][*1*][0][0]... after first iteration
...[0][0][*0*][0][0]... after second iteration (loop ends)
Consideremos otro ejemplo de bucle finito:
++[>]
Este ejemplo muestra que no hemos terminado el ciclo en la celda en la que comenzó el ciclo:
...[0][0][*2*][0][0]... loop starts
...[0][0][2][*0*][0]... after first iteration (loop ends)
Sin embargo, es una buena práctica terminar donde comenzamos. Por qué ? Porque si el bucle termina otra celda que comenzó, no podemos asumir dónde estará el puntero de la celda. Para ser honesto, esta práctica hace que la cogida de cerebro sea menos cogida de cerebro.