¿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;
}

63
Es solo C ofuscado ... hay sociedades enteras dedicadas a este tipo de locura.
Mark


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.


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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.