Nous allons de dissimuler.
Indentation:
main(_) {
_^448 && main(-~_);
putchar(--_%64
? 32 | -~7[__TIME__-_/8%8][">'txiZ^(~z?"-48] >> ";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1
: 10);
}
L'introduction de variables de 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 que -~i == i+1
car des deux-complément de. 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 qu' a[b]
est le même que b[a]
, et d'appliquer l' -~ == 1+
de changer à nouveau:
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));
}
}
La conversion de la récursivité à une boucle et de 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));
}
}
}
Cette fonction génère un personnage par itération. Tous les 64e de caractère, elle génère un saut de ligne. Sinon, il utilise une paire de tables de données à la figure ce qu'à la sortie, et met l'un des personnages 32 (espace) ou le caractère de 33 !
). Le premier tableau (">'txiZ^(~z?"
) est un ensemble de 10 bitmaps décrire l'apparence de chaque personnage, et la seconde table (";;;====~$::199"
) sélectionne le bit correspondant à l'affichage de l'image bitmap.
La seconde table
Commençons par l'examen de la deuxième table, int shift = ";;;====~$::199"[(i*2&8) | (i/64)];
. i/64
est le numéro de la ligne (6 à 0) et i*2&8
8 iff i
4, 5, 6 ou 7 mod 8.
if((i & 2) == 0) shift /= 8; shift = shift % 8
sélectionne soit le haut chiffre octal ( i%8
= 0,1,4,5) ou le faible chiffre octal ( i%8
= 2,3,6,7) de la valeur de la table. La maj de la table 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 null pour les deux premières entrées de la table (sournois!).
Ceci est conçu d'après un à sept segments d'affichage, avec 7
s comme des blancs. Ainsi, les entrées dans le premier tableau doit définir les segments être éclairé.
La première table
__TIME__
est un spécial macro définie par le préprocesseur. Il se développe à une constante de chaîne contenant l'heure à laquelle le préprocesseur a été exécuté, sous la forme "HH:MM:SS"
. Observer qu'il contient exactement 8 caractères. Notez que 0-9 ont des valeurs ASCII 48 par 57 :
a la valeur ASCII 58. La sortie est de 64 caractères par ligne, de sorte que les feuilles de 8 caractères par caractères d' __TIME__
.
7 - i/8%8
est donc l'indice d' __TIME__
qui est actuellement en cours de sortie ( 7-
est nécessaire parce que nous sommes une itération i
à la baisse). Donc, t
est le caractère de l' __TIME__
en cours de sortie.
a
finit par égaler le suivant en binaire, en fonction de 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 allumés dans nos sept segments d'affichage. Car les personnages sont tous ASCII 7 bits, le bit élevé est toujours désactivée. Ainsi, 7
dans le segment de la table de toujours s'imprime comme un vide. La deuxième table ressemble à ceci avec l' 7
s comme blancs:
000055
11 55
11 55
116655
22 33
22 33
444433
Ainsi, par exemple, 4
est 01101010
(les bits 1, 3, 5, et 6), qui s'imprime comme
----!!--
!!--!!--
!!--!!--
!!!!!!--
----!!--
----!!--
----!!--
Montrer que nous sommes vraiment à comprendre le code, nous allons régler la sortie un peu avec ce tableau:
00
11 55
11 55
66
22 33
22 33
44
C'est codée en tant que "?;;?==? '::799\x07"
. Pour artistiques, nous allons ajouter de 64 à quelques-uns des caractères (puisque seule la faible 6 bits sont utilisés, ce qui n'affecte pas la sortie), ce qui permet d' "?{{?}}?gg::799G"
(à noter que la 8ème caractère est utilisé, alors, nous pouvons faire ce que nous voulons). Mise en application de 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);}
nous obtenons
!! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !!
tout comme nous nous y attendions. Ce n'est pas aussi solide à la recherche de l'original, ce qui explique pourquoi l'auteur a choisi d'utiliser le tableau qu'il a fait.