Chinaunix首页 | 论坛 | 博客
  • 博客访问: 24880
  • 博文数量: 5
  • 博客积分: 30
  • 博客等级: 民兵
  • 技术积分: 17
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-16 22:21
个人简介

好人一枚

文章分类
文章存档

2013年(5)

我的朋友

分类: IT业界

2013-04-12 12:50:31

下面这段代码即为第19届 优胜作品:“A clock in one line”。

点击(此处)折叠或打开

  1. main(_){_^448&&main(-~_);putchar(--_%64?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}
输出结果如下:(当前时间)

它究竟是如何做到的呢?下面为你解读:

首先,将这段代码格式化:

点击(此处)折叠或打开

  1. main(_) {
  2.     _^448 && main(-~_);
  3.     putchar(--_%64
  4.         ? 32 | -~7[__TIME__-_/8%8][">'txiZ^(~z?"-48] >> ";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1
  5.         : 10);
  6. }


引入变量:

点击(此处)折叠或打开

  1. main(int i) {
  2.     if(i^448)
  3.         main(-~i);
  4.     if(--i % 64) {
  5.         char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
  6.         char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
  7.         putchar(32 | (b & 1));
  8.     } else {
  9.         putchar(10);
  10. // newline .
  11.     }
  12. }


根据补码的规则,可得-~i == i+1,所以:



点击(此处)折叠或打开

  1. main(int i) {
  2.     if(i != 448)
  3.         main(i+1);
  4.     i--;
  5.     if(i % 64 == 0) {
  6.         putchar('\n');
  7.     } else {
  8.         char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
  9.         char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
  10.         putchar(32 | (b & 1));
  11.     }
  12. }


另外,因为C语言中a[b]等同于b[a],同时在运用 -~=1+ 规则,可得:

点击(此处)折叠或打开

  1. main(int i) {
  2.     if(i != 448)
  3.         main(i+1);
  4.     i--;
  5.     if(i % 64 == 0) {
  6.         putchar('\n');
  7.     } else {
  8.         char a = (">'txiZ^(~z?"-48)[(__TIME__-i/8%8)[7]] + 1;
  9.         char b = a >> ";;;====~$::199"[(i*2&8)|i/64]/(i&2?1:8)%8;
  10.         putchar(32 | (b & 1));
  11.     }
  12. }

将递归转换成循环,同时再做简化:



点击(此处)折叠或打开

  1. // please don't pass any command-line arguments .
  2. main() {
  3.     int i;
  4.     for(i=447; i>=0; i--) {
  5.         if(i % 64 == 0) {
  6.             putchar('\n');
  7.         } else {
  8.             char t = __TIME__[7 - i/8%8];
  9.             char a = ">'txiZ^(~z?"[t - 48] + 1;
  10.             int shift = ";;;====~$::199"[(i*2&8) | (i/64)];
  11.             if((i & 2) == 0)
  12.                 shift /= 8;
  13.             shift = shift % 8;
  14.             char b = a >> shift;
  15.             putchar(32 | (b & 1));
  16.         }
  17.     }
  18. }


这样每次迭代会输出一个字符,每第64个字符会输出新的一行。

另外,它还使用数据表来设定输出形式,决定输出的是字符32(即字符空格)还是字符33(即字符 ! )。第一个表“>'txiZ^(~z?”是一组10位图,描述每个字符的外观;第二个表 “;;;====~$::199”的作用是,从位图中选择合适的位元来展示。

第二个表

我们先检查一下第二个表,“int shift = ";;;====~$::199"[(i*2&8) | (i/64)];”其中 i/64 是行数(从6到0);而 i*2&8 当且仅当i为4、5、6、7mod8时为8。

“if((i & 2) == 0) shift /= 8; shift = shift % 8”选择表的高8位(i%8=0、1、4、5)或者低8位(i=2、3、6、7)值。因此转换表最终看起来是这个样子:

点击(此处)折叠或打开

  1. row col val
  2. 6 6-7 0
  3. 6 4-5 0
  4. 6 2-3 5
  5. 6 0-1 7
  6. 5 6-7 1
  7. 5 4-5 7
  8. 5 2-3 5
  9. 5 0-1 7
  10. 4 6-7 1
  11. 4 4-5 7
  12. 4 2-3 5
  13. 4 0-1 7
  14. 3 6-7 1
  15. 3 4-5 6
  16. 3 2-3 5
  17. 3 0-1 7
  18. 2 6-7 2
  19. 2 4-5 7
  20. 2 2-3 3
  21. 2 0-1 7
  22. 1 6-7 2
  23. 1 4-5 7
  24. 1 2-3 3
  25. 1 0-1 7
  26. 0 6-7 4
  27. 0 4-5 4
  28. 0 2-3 3
  29. 0 0-1 7


或者显示为表格的形式:

点击(此处)折叠或打开

  1. 00005577
  2. 11775577
  3. 11775577
  4. 11665577
  5. 22773377
  6. 22773377
  7. 44443377


注意:作者在表格的前两位使用了null terminator。(真狡猾!)

第一个表

是预处理器定义的特殊的宏,它能扩展为一个字符串,内容为预处理器运行的时间,格式为“HH:MM:SS”,刚好占8个字符。注意:数字0-9的ASCII值为48-57,“:”的ASCII值为58。而每行输出64个字符,因此 __TIME__ 的每个字符有8个字符的空间。

“7 - i/8%8”是当前正在输出的 __TIME__ 的索引(其中“7-”是必须的,因为我们从 i 开始向下遍历)。因此 t 即 __TIME__ 要输出的字符。

a的值取决于t,对应关系如下:

点击(此处)折叠或打开

  1. 0 00111111
  2. 1 00101000
  3. 2 01110101
  4. 3 01111001
  5. 4 01101010
  6. 5 01011011
  7. 6 01011111
  8. 7 00101001
  9. 8 01111111
  10. 9 01111011
  11. : 01000000


每个数字都是一个位图,描述7段显示的字符。又因为是7位ASCII,所以高位会被清除,所以7位永远是空格,所以第二个表是这个样子:

点击(此处)折叠或打开

  1. 000055
  2. 11 55
  3. 11 55
  4. 116655
  5. 22 33
  6. 22 33
  7. 444433


举个例子,4即01101010(1、3、5、6位显示),输出如下:

点击(此处)折叠或打开

  1. ----!!--
  2. !!--!!--
  3. !!--!!--
  4. !!!!!!--
  5. ----!!--
  6. ----!!--
  7. ----!!--



理解了吗?现在我们再对输出做一些调整:

点击(此处)折叠或打开

  1. 00
  2. 11 55
  3. 11 55
  4.   66
  5. 22 33
  6. 22 33
  7.   44


可以编码为“?;;?==? '::799\x07”。

出于美观考虑,我们把对64位做一些修改(因为输出仅使用低6位,所以不会受到影响),于是就变成了“?{{?}}?gg::799G”(注意:第8位并没有被使用,因此我们还可以做更多的衍生创作)。

现在代码就变成了:

点击(此处)折叠或打开

  1. main(_){_^448&&main(-~_);putchar(--_%64?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>"?{{?}}?gg::799G"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}
输出结果如下:


如预期的一样,看来我们的想法并没有错。(CSDN 王然/编译)

原文出自:

阅读(1627) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~