Como esse código gera o mapa da Índia?

169

Este código imprime o mapa da Índia. 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
fonte
63
É apenas ofuscado C ... há sociedades inteiras dedicadas a esse tipo de loucura.
Mark
12
Saída: codepad.org/ngiITeZ4
Andreas Rejbrand
2
#include "Stdio.h": isso funciona em todos os compiladores? Estou surpreso ao ver que você pode obter código de trabalho com erros de digitação. Talvez seja no Windows (FS que não diferenciam maiúsculas de minúsculas)
alternativa
2
Para um código mais divertido como esse, consulte [Concurso Internacional de Código C Ofuscado] [ ioccc.org/] .
precisa saber é o seguinte
12
Esteja ciente de que o código é intencionalmente difícil de entender, e não há muito a ganhar com isso, no que diz respeito à aprendizagem de C no nível de iniciante.
Tyler McHenry

Respostas:

154

A cadeia longa é simplesmente uma sequência binária convertida em ASCII. A primeira forinstrução binicia em 10 e, [b+++21]depois que a sequência produz 31. Tratando a sequência como uma matriz, o deslocamento 31 é o início dos dados "reais" na sequência (a segunda linha no exemplo de código que você forneceu). O restante do código simplesmente percorre a sequência de bits, convertendo o 1 e o 0 em! E o espaço em branco e imprimindo um caractere de cada vez.

Versão 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;
}

A parte estranha e inteligente está nas putchardeclarações. Pegue o primeiro putchar. ASCII 'Z'é 90 em decimal, então 90/9 = 10, que é um caractere de nova linha. No segundo, o decimal 33 é ASCII para '!'. Alternar o bit de baixa ordem de 33 fornece 32, que é ASCII para um espaço. Isso faz !com que seja impresso se bfor ímpar e um espaço em branco a ser impresso se bfor par. O restante do código está simplesmente lá para percorrer o "ponteiro" apela string.

bta
fonte
22
A sequência não é uma sequência de bits (observe que não há operações de deslocamento de bits no código). É uma codificação de duração da imagem.
interjay
89

Basicamente, a sequência é uma codificação de duração da imagem: Caracteres alternativos na sequência dizem quantas vezes desenhar um espaço e quantas vezes desenhar um ponto de exclamação consecutivamente. Aqui está uma análise dos diferentes elementos deste programa:

A cadeia codificada

Os primeiros 31 caracteres dessa sequência são ignorados. O restante contém instruções para desenhar a imagem. Os caracteres individuais determinam quantos espaços ou pontos de exclamação serão desenhados consecutivamente.

Loop externo

Este loop passa por cima dos caracteres na string. Cada iteração aumenta o valor de bum e atribui o próximo caractere na sequência a a.

Interno para loop

Esse loop desenha caracteres individuais e uma nova linha sempre que chega ao final da linha. O número de caracteres desenhados é a - 64. O valor de cvai de 10 a 90 e redefine para 10 quando o final da linha é atingido.

o putchar

Isso pode ser reescrito como:

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

Desenha o caractere apropriado, dependendo se bé par ou ímpar, ou uma nova linha quando necessário.

interjay
fonte
1
Por que os primeiros 31 caracteres são ignorados?
Pankaj Mahato
3
@PankajMahato porque bcomeça às 10 e o índice é (b++)+21, que começa às 31.
interjay 6/06/14