obfuscated - c obfuscation winner
¿Cómo genera este código el mapa de India? (2)
Básicamente, la cadena es una codificación de longitud de ejecución de la imagen: los caracteres alternos en la cadena indican cuántas veces se debe dibujar un espacio y cuántas veces se debe dibujar un signo de admiración consecutivamente. Aquí hay un análisis de los diferentes elementos de este programa:
La cadena codificada
Los primeros 31 caracteres de esta cadena se ignoran. El resto contiene instrucciones para dibujar la imagen. Los personajes individuales determinan cuántos espacios o signos de exclamación dibujarán consecutivamente.
Bucle externo
Este ciclo revisa los caracteres en la cadena. Cada iteración aumenta el valor de b
en uno, y asigna el siguiente carácter en la cadena a a
.
Lazo interno
Este ciclo dibuja caracteres individuales y una línea nueva cada vez que llega al final de la línea. La cantidad de caracteres dibujados es a - 64
. El valor de c
va de 10 a 90 y se restablece a 10 cuando se alcanza el final de la línea.
El putchar
Esto puede ser reescrito como:
++c;
if (c==90) { //''Z'' == 90
c = 10; //Note: 10 == ''/n''
putchar(''/n'');
}
else {
if (b % 2 == 0)
putchar(''!'');
else
putchar('' '');
}
Dibuja el carácter apropiado, dependiendo de si b
es par o impar, o una nueva línea cuando sea necesario.
Este código imprime el mapa de India. ¿Como funciona?
#include <stdio.h>
main()
{
int a,b,c;
int count = 1;
for (b=c=10;a="- FIGURE?, UMKC,XYZHello Folks,/
TFy!QJu ROo TNn(ROo)SLq SLq ULo+/
UHs UJq TNn*RPn/QPbEWS_JSWQAIJO^/
NBELPeHBFHT}TnALVlBLOFAkHFOuFETp/
HCStHAUFAgcEAelclcn^r^r//tZvYxXy/
T|S~Pn SPm SOn TNn ULo0ULo#ULo-W/
Hq!WFs XDt!" [b+++21]; )
for(; a-- > 64 ; )
putchar ( ++c==''Z'' ? c = c/ 9:33^b&1);
return 0;
}
La cadena larga es simplemente una secuencia binaria convertida a ASCII. El primero for
enunciado hace que b
comience en 10, y el [b+++21]
después de que el renglón ceda 31. Tratando el hilo como un conjunto, el desplazamiento 31 es el comienzo de los datos "reales" en el hilo (el segundo línea en la muestra de código que proporcionó). El resto del código simplemente recorre la secuencia de bits, convirtiendo los 1 y 0 en! Y espacio en blanco e imprimiendo un carácter a la vez.
Versión menos ofuscada:
#include "stdio.h"
int main (void) {
int a=10, b=0, c=10;
char* bits ="TFy!QJu ROo TNn(ROo)SLq SLq ULo+UHs UJq TNn*RPn/QPbEWS_JSWQAIJO^NBELPeHBFHT}TnALVlBLOFAkHFOuFETpHCStHAUFAgcEAelclcn^r^r//tZvYxXyT|S~Pn SPm SOn TNn ULo0ULo#ULo-WHq!WFs XDt!";
a = bits[b];
while (a != 0) {
a = bits[b];
b++;
while (a > 64) {
a--;
if (++c == ''Z'') {
c /= 9;
putchar(c);
} else {
putchar(33 ^ (b & 0x01));
}
}
}
return 0;
}
La extraña parte inteligente está en las declaraciones de putchar
. Toma el primer putchar
. ASCII ''Z''
es 90 en decimal, entonces 90/9 = 10 que es un carácter de nueva línea. En el segundo, el decimal 33 es ASCII para ''!''
. Alternar el bit de orden inferior de 33 le da 32, que es ASCII por un espacio. Esto causa !
para imprimir si b
es impar, y un espacio en blanco para imprimir si b
es par. El resto del código simplemente está ahí para pasar el "puntero" a
través de la cadena.