Как этот код генерирует карту Индии?

169

Этот код печатает карту Индии. Как это работает?

#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
источник
63
Это просто запутанный C ... есть целые общества, посвященные этому виду безумия.
Mark
12
Вывод: codepad.org/ngiITeZ4
Андреас Рейбранд
2
#include "Stdio.h": это работает на всех компиляторах? Я удивлен, увидев, что вы можете получить рабочий код с ошибками. Может быть, на Windows (не с учетом регистра)
альтернатива
2
Более интересный код, подобный этому, можно найти в [Международном конкурсе кодов с запутанным кодом C] [ ioccc.org/] .
DarkDust
12
Просто имейте в виду, что код преднамеренно сложен для понимания, и мало что можно извлечь из его выяснения, насколько это касается изучения C на уровне новичка.
Тайлер МакГенри

Ответы:

154

Длинная строка - это просто двоичная последовательность, преобразованная в ASCII. Первый forоператор bначинается с 10, а [b+++21]после строки возвращается 31. Обрабатывая строку как массив, смещение 31 является началом «реальных» данных в строке (вторая строка в предоставленном вами примере кода). Остальная часть кода просто перебирает последовательность битов, конвертируя 1 и 0 в! И пробелы и печатая по одному символу за раз.

Менее запутанная версия:

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

Странно умная часть в putcharотчетности. Возьми первый putchar. ASCII 'Z'- это 90 в десятичном виде, поэтому 90/9 = 10, что является символом новой строки. Во втором десятичное 33 является ASCII для '!'. Переключение младшего бита 33 дает 32, что является ASCII для пробела. Это приводит !к печати, если bона нечетная, и пустому пространству для печати, если bона четная. Остальная часть кода просто для того, чтобы пройти «указатель» aчерез строку.

ВТА
источник
22
Строка не является битовой последовательностью (обратите внимание, что в коде нет операций сдвига битов). Это кодирование изображения по длине прогона.
междурядный
89

По сути, строка представляет собой кодировку длины строки : чередующиеся символы в строке говорят, сколько раз рисовать пробел и сколько раз подряд восклицательный знак. Вот анализ различных элементов этой программы:

Кодированная строка

Первые 31 символ этой строки игнорируются. Остальные содержат инструкции по рисованию изображения. Отдельные символы определяют, сколько пробелов или восклицательных знаков можно нарисовать последовательно.

Наружный для петли

Этот цикл перебирает символы в строке. Каждая итерация увеличивает значение bна единицу и присваивает следующий символ в строке a.

Внутренний цикл

Этот цикл рисует отдельные символы и символ новой строки всякий раз, когда он достигает конца строки. Количество символов обращено это a - 64. Значение cизменяется от 10 до 90 и сбрасывается до 10 при достижении конца строки.

putchar

Это может быть переписано как:

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

Он рисует соответствующий символ, в зависимости от того, bявляется ли он четным или нечетным, или перевод строки, когда это необходимо.

interjay
источник
1
Почему первые 31 символ игнорируются?
Панкадж Махато
3
@PankajMahato, потому что bначинается с 10, а индекс (b++)+21начинается с 31.
Межджай