Как этот код генерирует карту Индии? - PullRequest
166 голосов
/ 20 августа 2010

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

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

Ответы [ 2 ]

154 голосов
/ 20 августа 2010

Длинная строка - это просто двоичная последовательность, преобразованная в 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 через строку.

89 голосов
/ 20 августа 2010

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

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

Первые 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 четным или нечетным, или при необходимости новой строкой.

...