Désobscurcissons-le.
Indentation:
main(_) {
_^448 && main(-~_);
putchar(--_%64
? 32 | -~7[__TIME__-_/8%8][">'txiZ^(~z?"-48] >> ";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1
: 10);
}
Présentation de variables pour démêler ce gâchis:
main(int i) {
if(i^448)
main(-~i);
if(--i % 64) {
char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
putchar(32 | (b & 1));
} else {
putchar(10); // newline
}
}
Notez cela à -~i == i+1cause du complément à deux. Par conséquent, nous avons
main(int i) {
if(i != 448)
main(i+1);
i--;
if(i % 64 == 0) {
putchar('\n');
} else {
char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
putchar(32 | (b & 1));
}
}
Maintenant, notez que a[b]c'est la même choseb[a] et appliquez à -~ == 1+nouveau la modification:
main(int i) {
if(i != 448)
main(i+1);
i--;
if(i % 64 == 0) {
putchar('\n');
} else {
char a = (">'txiZ^(~z?"-48)[(__TIME__-i/8%8)[7]] + 1;
char b = a >> ";;;====~$::199"[(i*2&8)|i/64]/(i&2?1:8)%8;
putchar(32 | (b & 1));
}
}
Convertir la récursivité en boucle et se faufiler dans un peu plus de simplification:
// please don't pass any command-line arguments
main() {
int i;
for(i=447; i>=0; i--) {
if(i % 64 == 0) {
putchar('\n');
} else {
char t = __TIME__[7 - i/8%8];
char a = ">'txiZ^(~z?"[t - 48] + 1;
int shift = ";;;====~$::199"[(i*2&8) | (i/64)];
if((i & 2) == 0)
shift /= 8;
shift = shift % 8;
char b = a >> shift;
putchar(32 | (b & 1));
}
}
}
Cela génère un caractère par itération. Chaque 64ème caractère, il sort une nouvelle ligne. Sinon, il utilise une paire de tableaux de données pour déterminer ce qu'il faut sortir et met soit le caractère 32 (un espace) soit le caractère 33 (a !). Le premier tableau ( ">'txiZ^(~z?") est un ensemble de 10 bitmaps décrivant l'apparence de chaque caractère, et le second tableau ( ";;;====~$::199") sélectionne le bit approprié à afficher dans le bitmap.
Le deuxième tableau
Commençons par examiner la deuxième table, int shift = ";;;====~$::199"[(i*2&8) | (i/64)];. i/64est le numéro de ligne (6 à 0) et i*2&8est 8 ssi i4, 5, 6 ou 7 mod 8.
if((i & 2) == 0) shift /= 8; shift = shift % 8sélectionne soit le chiffre octal haut (pour i%8= 0,1,4,5), soit le chiffre octal bas (pour i%8= 2,3,6,7) de la valeur du tableau. La table de décalage finit par ressembler à ceci:
row col val
6 6-7 0
6 4-5 0
6 2-3 5
6 0-1 7
5 6-7 1
5 4-5 7
5 2-3 5
5 0-1 7
4 6-7 1
4 4-5 7
4 2-3 5
4 0-1 7
3 6-7 1
3 4-5 6
3 2-3 5
3 0-1 7
2 6-7 2
2 4-5 7
2 2-3 3
2 0-1 7
1 6-7 2
1 4-5 7
1 2-3 3
1 0-1 7
0 6-7 4
0 4-5 4
0 2-3 3
0 0-1 7
ou sous forme de tableau
00005577
11775577
11775577
11665577
22773377
22773377
44443377
Notez que l'auteur a utilisé le terminateur nul pour les deux premières entrées de table (sournois!).
Ceci est conçu après un affichage à sept segments, avec 7s comme blancs. Ainsi, les entrées du premier tableau doivent définir les segments qui s'allument.
Le premier tableau
__TIME__est une macro spéciale définie par le préprocesseur. Il se développe en une constante de chaîne contenant l'heure à laquelle le préprocesseur a été exécuté, sous la forme "HH:MM:SS". Notez qu'il contient exactement 8 caractères. Notez que 0-9 ont des valeurs ASCII 48 à 57 et :une valeur ASCII 58. La sortie est de 64 caractères par ligne, ce qui laisse 8 caractères par caractère de __TIME__.
7 - i/8%8est donc l'indice de ce __TIME__qui est actuellement en cours de sortie (le 7-est nécessaire parce que nous itérons ivers le bas). Donc, tc'est le caractère d' __TIME__être sorti.
afinit par égaler ce qui suit en binaire, selon l'entrée t:
0 00111111
1 00101000
2 01110101
3 01111001
4 01101010
5 01011011
6 01011111
7 00101001
8 01111111
9 01111011
: 01000000
Chaque numéro est un bitmap décrivant les segments qui sont allumés dans notre affichage à sept segments. Comme les caractères sont tous en ASCII 7 bits, le bit haut est toujours effacé. Ainsi, 7dans la table des segments, l'impression est toujours vide. Le deuxième tableau ressemble à ceci avec le 7s en blanc:
000055
11 55
11 55
116655
22 33
22 33
444433
Ainsi, par exemple, 4est 01101010(bits 1, 3, 5 et 6 définis), qui s'imprime comme
----!!--
!!--!!--
!!--!!--
!!!!!!--
----!!--
----!!--
----!!--
Pour montrer que nous comprenons vraiment le code, ajustons un peu la sortie avec ce tableau:
00
11 55
11 55
66
22 33
22 33
44
Ceci est codé comme "?;;?==? '::799\x07". À des fins artistiques, nous ajouterons 64 à quelques-uns des caractères (puisque seuls les 6 bits les plus faibles sont utilisés, cela n'affectera pas la sortie); cela donne "?{{?}}?gg::799G"(notez que le 8ème caractère n'est pas utilisé, nous pouvons donc en faire ce que nous voulons). Mettre notre nouvelle table dans le code d'origine:
main(_){_^448&&main(-~_);putchar(--_%64?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>"?{{?}}?gg::799G"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}
on a
!! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !!
comme nous nous y attendions. Ce n'est pas aussi solide que l'original, ce qui explique pourquoi l'auteur a choisi d'utiliser le tableau qu'il a fait.
printf("%d", _);au début desmainimpressions: pastebin.com/HHhXAYdJ