¿Cómo genera este código el mapa de la India?

169

Este código imprime el mapa de la 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;
}
narayanpatra
fuente
63
Es solo C ofuscado ... hay sociedades enteras dedicadas a este tipo de locura.
Mark
12
Salida: codepad.org/ngiITeZ4
Andreas Rejbrand
2
#include "Stdio.h": ¿Funciona en todos los compiladores? Me sorprende ver que puede obtener código de trabajo con errores de tapa. Tal vez esté en Windows (FS sin mayúsculas y minúsculas)
alternativa
2
Para obtener un código más divertido como ese, consulte [El concurso internacional de códigos C ofuscados] [ ioccc.org/] .
DarkDust
12
Solo tenga en cuenta que el código es intencionalmente difícil de entender, y no hay mucho que ganar al descifrarlo, en lo que respecta a aprender C desde el nivel de principiante.
Tyler McHenry

Respuestas:

154

La cadena larga es simplemente una secuencia binaria convertida a ASCII. La primera fordeclaración bcomienza en 10, y [b+++21]después de que la cadena produce 31. Tratando la cadena como una matriz, el desplazamiento 31 es el comienzo de los datos "reales" en la cadena (la segunda línea en el ejemplo de código que proporcionó). El resto del código simplemente recorre la secuencia de bits, convirtiendo los 1 y 0 en! Y espacios 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 putchardeclaraciones. Toma el primero 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 para un espacio. Esto hace !que se imprima si bes impar y que se imprima un espacio en blanco si bes par. El resto del código simplemente está ahí para recorrer el "puntero" a através de la cadena.

bta
fuente
22
La cadena no es una secuencia de bits (tenga en cuenta que no hay operaciones de desplazamiento de bits en el código). Es una codificación de longitud de ejecución de la imagen.
Interjay
89

Básicamente, la cadena es una codificación de longitud de ejecución de la imagen: los caracteres alternos en la cadena dicen cuántas veces dibujar un espacio y cuántas veces dibujar un signo de exclamació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 caracteres individuales determinan cuántos espacios o signos de exclamación dibujar de forma consecutiva.

Exterior para lazo

Este bucle pasa sobre los caracteres de la cadena. Cada iteración aumenta el valor de ben uno y asigna el siguiente carácter de la cadena a a.

Interior para bucle

Este bucle dibuja caracteres individuales y una nueva línea cada vez que llega al final de la línea. El número de caracteres dibujados es a - 64. El valor de cva de 10 a 90 y se restablece a 10 cuando se alcanza el final de la línea.

los putchar

Esto se puede reescribir 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 bes par o impar, o una nueva línea cuando sea necesario.

interjay
fuente
1
¿Por qué se ignoran los primeros 31 caracteres?
Pankaj Mahato
3
@PankajMahato porque bcomienza a las 10 y el índice es (b++)+21, que comienza a las 31.
Interjay