C, 59 bytes
i;f(char*s){while(*s&3?*s&9||(i+=i+*s%5):putchar(i),*s++);}
¡Números mágicos, números mágicos en todas partes!
(Además, ¿C más corto que Python, JS, PHP y Ruby? ¡Inaudito!)
Esta es una función que toma una cadena como entrada y salida a STDOUT.
Tutorial
La estructura básica es:
i; // initialize an integer i to 0
f(char*s){
while(...); // run the stuff inside until it becomes 0
}
Aquí, las "cosas dentro" son un montón de código seguido de ,*s++, donde el operador de coma devuelve solo el valor de su segundo argumento. Por lo tanto, esto se ejecutará a través de la cadena y se establecerá *sen cada carácter, incluido el byte NUL final (ya que postfix ++devuelve el valor anterior), antes de salir.
Echemos un vistazo al resto:
*s&3?*s&9||(i+=i+*s%5):putchar(i)
Despegando el ternario y cortocircuito ||, esto se puede expandir a
if (*s & 3) {
if (!(*s & 9)) {
i += i + *s % 5;
}
} else {
putchar(i);
}
¿De dónde vienen estos números mágicos? Aquí están las representaciones binarias de todos los personajes involucrados:
F 70 01000110
B 66 01000010
i 105 01101001
z 122 01111010
u 117 01110101
32 00100000
\0 0 00000000
Primero, necesitamos separar el espacio y NUL del resto de los personajes. La forma en que funciona este algoritmo mantiene un acumulador del número "actual" e imprime cada vez que llega a un espacio o al final de la cadena (es decir '\0'). Al notar eso ' 'y '\0'son los únicos caracteres que no tienen ninguno de los dos bits menos significativos establecidos, podemos bit a bit Y el carácter 0b11para obtener cero si el carácter es espacio o NUL y no cero de lo contrario.
Profundizando, en la primera rama "si", ahora tenemos un personaje que es uno de ellos FBizu. Elegí solo actualizar el acumulador en Fsy Bs, por lo que necesitaba alguna forma de filtrar el izus. Convenientemente, Fy Bambos tienen solo el segundo, tercer o séptimo conjunto de bits menos significativo, y todos los otros números tienen al menos otro conjunto de bits. De hecho, todos tienen el primer o cuarto bit menos significativo. Por lo tanto, podemos bit a bit AND con 0b00001001, que es 9, que de lo contrario producirá 0 para Fand By no cero.
Una vez que hemos determinado que tenemos un Fo B, podemos asignarlos a 0y 1respectivamente tomando su módulo 5, porque Fes 70y Bes 66. Entonces el fragmento
i += i + *s % 5;
es solo una forma de decir golf
i = (i * 2) + (*s % 5);
que también se puede expresar como
i = (i << 1) | (*s % 5);
que inserta el nuevo bit en la posición menos significativa y cambia todo lo demás en 1.
"¡Pero espera!" Podrías protestar. "Después de imprimir i, ¿cuándo vuelve a restablecerse a 0?" Bueno, putchararroja su argumento a un unsigned char, que resulta ser de 8 bits de tamaño. Eso significa que todo lo que pasa del octavo bit menos significativo (es decir, la basura de las iteraciones anteriores) se descarta, y no debemos preocuparnos por eso.
¡Gracias a @ETHproductions por sugerir reemplazar 57con 9, guardando un byte!