Comment ce code génère-t-il la carte de l'Inde?

169

Ce code imprime la carte de l'Inde. Comment ça marche?

#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
la source
63
C'est juste obscurci C ... il y a des sociétés entières dédiées à ce genre de folie.
Mark
12
Sortie: codepad.org/ngiITeZ4
Andreas Rejbrand
2
#include "Stdio.h": Cela fonctionne-t-il sur tous les compilateurs? Je suis surpris de voir que vous pouvez obtenir du code fonctionnel avec des erreurs. Peut-être que c'est sur Windows (FS non sensible à la casse)
alternative
2
Pour plus de code amusant comme celui-ci, consultez [Le concours international de code C obscurci] [ ioccc.org/] .
DarkDust
12
Sachez simplement que le code est intentionnellement difficile à comprendre et qu'il n'y a pas grand-chose à gagner à le comprendre, en ce qui concerne l'apprentissage du C à partir d'un niveau débutant.
Tyler McHenry

Réponses:

154

La longue chaîne est simplement une séquence binaire convertie en ASCII. La première forinstruction bcommence à 10 et [b+++21]après la chaîne donne 31. Traitant la chaîne comme un tableau, offset 31 est le début des données «réelles» dans la chaîne (la deuxième ligne de l'exemple de code que vous avez fourni). Le reste du code parcourt simplement la séquence de bits, convertissant les 1 et les 0 en! Et en espace et en imprimant un caractère à la fois.

Version moins obscure:

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

L' étrange partie intelligente est dans les putchardéclarations. Prenez le premier putchar. ASCII 'Z'est 90 en décimal, donc 90/9 = 10 qui est un caractère de nouvelle ligne. Dans le second, le nombre décimal 33 est ASCII pour '!'. Basculer le bit de poids faible de 33 vous donne 32, qui est ASCII pour un espace. Cela provoque !l'impression si best impair, et un espace vierge à imprimer si best pair. Le reste du code est simplement là pour parcourir le "pointeur" adans la chaîne.

bta
la source
22
La chaîne n'est pas une séquence de bits (notez qu'il n'y a pas d'opérations de décalage de bits dans le code). C'est un codage de longueur d'exécution de l'image.
entre
89

Fondamentalement, la chaîne est un codage de longueur d'exécution de l'image: les caractères alternés dans la chaîne indiquent combien de fois dessiner un espace et combien de fois dessiner un point d'exclamation consécutivement. Voici une analyse des différents éléments de ce programme:

La chaîne encodée

Les 31 premiers caractères de cette chaîne sont ignorés. Le reste contient des instructions pour dessiner l'image. Les caractères individuels déterminent le nombre d'espaces ou de points d'exclamation à dessiner consécutivement.

Boucle extérieure pour

Cette boucle parcourt les caractères de la chaîne. Chaque itération augmente la valeur de bde un et affecte le caractère suivant de la chaîne à a.

Boucle for intérieure

Cette boucle dessine des caractères individuels et une nouvelle ligne chaque fois qu'elle atteint la fin de la ligne. Le nombre de caractères dessinés est de a - 64. La valeur de cpasse de 10 à 90 et se réinitialise à 10 lorsque la fin de ligne est atteinte.

le putchar

Cela peut être réécrit comme:

++c;
if (c==90) {       //'Z' == 90
    c = 10;        //Note: 10 == '\n'
    putchar('\n');
}
else {
    if (b % 2 == 0)
        putchar('!');
    else
        putchar(' ');
}

Il dessine le caractère approprié, selon qu'il best pair ou impair, ou une nouvelle ligne si nécessaire.

interjay
la source
1
Pourquoi les 31 premiers caractères sont ignorés?
Pankaj Mahato
3
@PankajMahato car bcommence à 10 et l'indice est (b++)+21, qui commence à 31.
entre le