Mari kita hapuskannya.
Indentasi:
main(_) {
_^448 && main(-~_);
putchar(--_%64
? 32 | -~7[__TIME__-_/8%8][">'txiZ^(~z?"-48] >> ";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1
: 10);
}
Memperkenalkan variabel untuk mengurai kekacauan ini:
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
}
}
Perhatikan bahwa -~i == i+1
karena dua-pelengkap. Karena itu, kita punya
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));
}
}
Sekarang, perhatikan bahwa a[b]
itu sama denganb[a]
, dan terapkan -~ == 1+
perubahan itu lagi:
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));
}
}
Mengubah rekursi menjadi loop dan menyelinap dengan sedikit penyederhanaan:
// 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));
}
}
}
Ini menghasilkan satu karakter per iterasi. Setiap karakter ke-64, itu menghasilkan baris baru. Kalau tidak, ia menggunakan sepasang tabel data untuk mencari tahu apa yang akan dihasilkan, dan menempatkan karakter 32 (spasi) atau karakter 33 (a !
). Tabel pertama ( ">'txiZ^(~z?"
) adalah satu set 10 bitmap yang menggambarkan penampilan setiap karakter, dan tabel kedua ( ";;;====~$::199"
) memilih bit yang sesuai untuk ditampilkan dari bitmap.
Tabel kedua
Mari kita mulai dengan memeriksa tabel kedua int shift = ";;;====~$::199"[(i*2&8) | (i/64)];
,. i/64
adalah nomor baris (6 hingga 0) dan i*2&8
8 iff i
adalah 4, 5, 6 atau 7 mod 8.
if((i & 2) == 0) shift /= 8; shift = shift % 8
memilih digit oktal tinggi (untuk i%8
= 0,1,4,5) atau digit oktal rendah (untuk i%8
= 2,3,6,7) dari nilai tabel. Tabel shift akhirnya tampak seperti ini:
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
atau dalam bentuk tabel
00005577
11775577
11775577
11665577
22773377
22773377
44443377
Perhatikan bahwa penulis menggunakan terminator nol untuk dua entri tabel pertama (licik!).
Ini dirancang setelah tampilan tujuh segmen, dengan 7
s sebagai blank. Jadi, entri dalam tabel pertama harus menentukan segmen yang menyala.
Tabel pertama
__TIME__
adalah makro khusus yang didefinisikan oleh preprocessor. Itu mengembang ke konstanta string yang berisi waktu di mana preprocessor dijalankan, dalam bentuk "HH:MM:SS"
. Perhatikan bahwa itu berisi persis 8 karakter. Perhatikan bahwa 0-9 memiliki nilai ASCII 48 hingga 57 dan :
memiliki nilai ASCII 58. Outputnya adalah 64 karakter per baris, sehingga menyisakan 8 karakter per karakter __TIME__
.
7 - i/8%8
dengan demikian indeks __TIME__
yang saat ini sedang output ( 7-
diperlukan karena kita beralih i
ke bawah). Jadi, t
adalah karakter __TIME__
sebagai keluaran.
a
akhirnya sama dengan yang berikut dalam biner, tergantung pada input t
:
0 00111111
1 00101000
2 01110101
3 01111001
4 01101010
5 01011011
6 01011111
7 00101001
8 01111111
9 01111011
: 01000000
Setiap angka adalah bitmap yang menggambarkan segmen yang menyala di layar tujuh segmen kami. Karena semua karakter 7-bit ASCII, bit tinggi selalu dihapus. Dengan demikian, 7
dalam tabel segmen selalu dicetak sebagai kosong. Tabel kedua terlihat seperti ini dengan 7
s sebagai blank:
000055
11 55
11 55
116655
22 33
22 33
444433
Jadi, misalnya, 4
adalah 01101010
(bit 1, 3, 5, dan 6 set), yang dicetak sebagai
----!!--
!!--!!--
!!--!!--
!!!!!!--
----!!--
----!!--
----!!--
Untuk memperlihatkan bahwa kami benar-benar memahami kode, mari sesuaikan outputnya sedikit dengan tabel ini:
00
11 55
11 55
66
22 33
22 33
44
Ini dikodekan sebagai "?;;?==? '::799\x07"
. Untuk tujuan artistik, kami akan menambahkan 64 ke beberapa karakter (karena hanya 6 bit rendah yang digunakan, ini tidak akan mempengaruhi output); ini memberi "?{{?}}?gg::799G"
(perhatikan bahwa karakter ke-8 tidak digunakan, sehingga kita dapat benar-benar membuatnya menjadi apa pun yang kita inginkan). Menempatkan tabel baru kami di kode asli:
main(_){_^448&&main(-~_);putchar(--_%64?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>"?{{?}}?gg::799G"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}
kita mendapatkan
!! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !!
seperti yang kami harapkan. Ini tidak sekokoh aslinya, yang menjelaskan mengapa penulis memilih untuk menggunakan tabel yang dia lakukan.
printf("%d", _);
ke awalmain
cetakan: pastebin.com/HHhXAYdJ