Wie generiert dieser Code die Karte von Indien?

169

Dieser Code druckt die Karte von Indien. Wie funktioniert es?

#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
quelle
63
Es ist nur verschleiert C ... es gibt ganze Gesellschaften, die sich dieser Art von Wahnsinn widmen.
Mark
12
Ausgabe: codepad.org/ngiITeZ4
Andreas Rejbrand
2
#include "Stdio.h": Funktioniert das auf allen Compilern? Ich bin überrascht zu sehen, dass Sie Arbeitscode mit Miscaps erhalten können. Vielleicht ist es unter Windows (nicht zwischen Groß- und Kleinschreibung unterscheiden)
Alternative
2
Für mehr Spaßcode wie diesen siehe [The International Obfuscated C Code Contest] [ ioccc.org/] .
DarkDust
12
Seien Sie sich nur bewusst, dass der Code absichtlich schwer zu verstehen ist und es nicht viel bringt, ihn herauszufinden, wenn es darum geht, C von einem Anfängerlevel zu lernen.
Tyler McHenry

Antworten:

154

Die lange Zeichenfolge ist einfach eine in ASCII konvertierte Binärsequenz. Die erste forAnweisung bbeginnt bei 10, und [b+++21]nachdem die Zeichenfolge 31 ergibt. Wenn Sie die Zeichenfolge als Array behandeln, ist Offset 31 der Beginn der "echten" Daten in der Zeichenfolge (die zweite Zeile im von Ihnen bereitgestellten Codebeispiel). Der Rest des Codes durchläuft einfach die Bitsequenz, konvertiert die Einsen und Nullen in! Und Leerzeichen und druckt jeweils ein Zeichen.

Weniger verschleierte Version:

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

Der seltsam kluge Teil ist in den putcharAussagen. Nimm den ersten putchar. ASCII 'Z'ist eine Dezimalzahl von 90, also 90/9 = 10, was ein Zeilenumbruchzeichen ist. In der zweiten ist die Dezimalstelle 33 ASCII für '!'. Wenn Sie das niederwertige Bit von 33 umschalten, erhalten Sie 32, was für ein Leerzeichen ASCII ist. Dies führt !dazu, dass gedruckt wird, wenn dies bungerade ist, und dass ein Leerzeichen gedruckt wird, wenn bes gerade ist. Der Rest des Codes ist einfach da, um den "Zeiger" adurch die Zeichenfolge zu führen.

bta
quelle
22
Die Zeichenfolge ist keine Bitfolge (beachten Sie, dass der Code keine Bitverschiebungsoperationen enthält). Es ist eine Lauflängencodierung des Bildes.
Interjay
89

Grundsätzlich handelt es sich bei der Zeichenfolge um eine Lauflängencodierung des Bildes: Wechselnde Zeichen in der Zeichenfolge geben an, wie oft ein Leerzeichen und wie oft nacheinander ein Ausrufezeichen gezeichnet werden soll. Hier ist eine Analyse der verschiedenen Elemente dieses Programms:

Die codierte Zeichenfolge

Die ersten 31 Zeichen dieser Zeichenfolge werden ignoriert. Der Rest enthält Anweisungen zum Zeichnen des Bildes. Die einzelnen Zeichen bestimmen, wie viele Leerzeichen oder Ausrufezeichen nacheinander gezeichnet werden sollen.

Außen für Schleife

Diese Schleife geht über die Zeichen in der Zeichenfolge. Jede Iteration erhöht den Wert von bum eins und weist das nächste Zeichen in der Zeichenfolge zu a.

Innen für Schleife

Diese Schleife zeichnet einzelne Zeichen und eine neue Zeile, wenn sie das Zeilenende erreicht. Die Anzahl der gezeichneten Zeichen beträgt a - 64. Der Wert von cgeht von 10 auf 90 und wird auf 10 zurückgesetzt, wenn das Zeilenende erreicht ist.

Das putchar

Dies kann wie folgt umgeschrieben werden:

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

Es zeichnet das entsprechende Zeichen, je nachdem, ob bgerade oder ungerade ist, oder bei Bedarf eine neue Zeile.

Interjay
quelle
1
Warum werden die ersten 31 Zeichen ignoriert?
Pankaj Mahato
3
@PankajMahato weil bbeginnt um 10 und der Index ist (b++)+21, der um 31 beginnt.
Interjay