Jak ten kod generuje mapę Indii?

169

Ten kod drukuje mapę Indii. Jak to działa?

#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
źródło
63
To tylko zaciemnione C ... są całe społeczeństwa oddane temu rodzajowi szaleństwa.
Mark
12
Wyjście: codepad.org/ngiITeZ4
Andreas Rejbrand,
2
#include "Stdio.h": Czy to działa na wszystkich kompilatorach? Jestem zaskoczony, że można uzyskać działający kod z błędami. Może to w systemie Windows (FS bez rozróżniania wielkości liter)
alternatywa
2
Więcej zabawnych kodów znajdziesz w [Międzynarodowy konkurs na zaciemniony kod C] [ ioccc.org/] .
DarkDust
12
Należy tylko pamiętać, że kod jest celowo trudny do zrozumienia i niewiele można zyskać na jego zrozumieniu, jeśli chodzi o naukę C na poziomie początkującym.
Tyler McHenry,

Odpowiedzi:

154

Długi ciąg to po prostu sekwencja binarna przekonwertowana na ASCII. Pierwsza forinstrukcja brozpoczyna się od 10, a następująca [b+++21]po łańcuchu daje 31. Traktując łańcuch jako tablicę, przesunięcie 31 jest początkiem „rzeczywistych” danych w ciągu (druga linia w podanym przykładzie kodu). Reszta kodu po prostu przechodzi w pętli przez sekwencję bitów, konwertując jedynki i zera na znaki! I białe znaki i wypisując po jednym znaku na raz.

Mniej zaciemniona wersja:

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

Dziwne mądry część znajduje się w putcharsprawozdaniu. Zrób pierwszy putchar. ASCII 'Z'to 90 dziesiętnie, więc 90/9 = 10, który jest znakiem nowej linii. W drugim dziesiętne 33 to ASCII dla '!'. Przełączenie dolnego bitu 33 daje 32, czyli ASCII dla spacji. Powoduje to, że !zostanie wydrukowane, jeśli bjest nieparzyste, a puste miejsce, jeśli bjest parzyste. Reszta kodu jest po prostu po to, by przejść „wskaźnik” aprzez łańcuch.

bta
źródło
22
Ciąg nie jest sekwencją bitów (zwróć uwagę, że w kodzie nie ma operacji przesunięcia bitów). Jest to kodowanie obrazu na całej długości.
interjay
89

Zasadniczo ciąg jest kodowaniem obrazu na całej długości : naprzemienne znaki w ciągu mówią, ile razy należy narysować spację i ile razy należy narysować po kolei znak wykrzyknika. Oto analiza różnych elementów tego programu:

Zakodowany ciąg

Pierwsze 31 znaków tego ciągu jest ignorowanych. Reszta zawiera instrukcje dotyczące rysowania obrazu. Poszczególne znaki określają, ile spacji lub wykrzykników należy narysować kolejno.

Zewnętrzna pętla

Ta pętla przechodzi przez znaki w ciągu. Każda iteracja zwiększa wartość o bjeden i przypisuje następny znak w ciągu a.

Wewnętrzna pętla

Ta pętla rysuje pojedyncze znaki i znak nowej linii za każdym razem, gdy osiągnie koniec wiersza. Liczba narysowanych znaków wynosi a - 64. Wartość czmienia się od 10 do 90 i resetuje do 10 po osiągnięciu końca linii.

Plik putchar

Można to przepisać jako:

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

Rysuje odpowiedni znak, w zależności od tego, czy bjest parzysty, czy nieparzysty, lub w razie potrzeby nową linię.

interjay
źródło
1
Dlaczego pierwsze 31 znaków jest ignorowanych?
Pankaj Mahato
3
@PankajMahato, ponieważ bzaczyna się od 10, a indeks jest (b++)+21, który zaczyna się od 31.
interjay