国际c语言混乱编码大赛,国际C语言混乱代码大赛优胜作品详解之“A clock in one line”...

下面这段代码即为第19届 IOCCC(国际混乱C语言代码大赛)优胜作品:“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

2

3

4

5

6

7

!!  !!!!!!              !!  !!!!!!              !!  !!!!!!

!!  !!  !!              !!      !!              !!  !!  !!

!!  !!  !!              !!      !!              !!  !!  !!

!!  !!!!!!    !!        !!      !!    !!        !!  !!!!!!

!!      !!              !!      !!              !!  !!  !!

!!      !!              !!      !!              !!  !!  !!

!!  !!!!!!              !!      !!              !!  !!!!!!

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

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

1

2

3

4

5

6

main(_) {

_^448 && main(-~_);

putchar(--_%64

? 32 | -~7[__TIME__-_/8%8][">'txiZ^(~z?"-48] >>";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1

: 10);

}

引入变量:

1

2

3

4

5

6

7

8

9

10

11

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

}

}

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

1

2

3

4

5

6

7

8

9

10

11

12

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));

}

}

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

1

2

3

4

5

6

7

8

9

10

11

12

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));

}

}

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

// 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));

}

}

}

这样每次迭代会输出一个字符,每第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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

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

或者显示为表格的形式:

1

2

3

4

5

6

7

00005577

11775577

11775577

11665577

22773377

22773377

44443377

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

第一个表

__TIME__是预处理器定义的特殊的宏,它能扩展为一个字符串,内容为预处理器运行的时间,格式为“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

2

3

4

5

6

7

8

9

10

11

0 00111111

1 00101000

2 01110101

3 01111001

4 01101010

5 01011011

6 01011111

7 00101001

8 01111111

9 01111011

: 01000000

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

1

2

3

4

5

6

7

000055

11  55

11  55

116655

22  33

22  33

444433

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

1

2

3

4

5

6

7

----!!--

!!--!!--

!!--!!--

!!!!!!--

----!!--

----!!--

----!!--

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

1

2

3

4

5

6

7

00

11  55

11  55

66

22  33

22  33

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

输出结果如下:

1

2

3

4

5

6

7

!!              !!                              !!

!!  !!              !!  !!  !!  !!              !!  !!  !!

!!  !!              !!  !!  !!  !!              !!  !!  !!

!!      !!              !!      !!

!!  !!  !!          !!  !!      !!              !!  !!  !!

!!  !!  !!          !!  !!      !!              !!  !!  !!

!!              !!                              !!

如预期的一样,看来我们的想法并没有错。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值