Most Pointed Reaction

もっとも集中した反応

受賞者:Don Yang

引用元:https://www.ioccc.org/2015/yang/prog.c

審査員・作者による説明:https://www.ioccc.org/2015/yang/hint.html

動作

メッセージを標準入力に与えると、アスキーアートなC言語コードを出力する。

$ gcc -std=c90 -o prog prog.c -lm

$ echo Hello | ./prog
                                                              #include<stdio.h>
typedef int O;void o(O _){putchar(_);}O main(){O*_[512],**p=_,**d,b,q;for(b=0;b
++<512;p=_+q)_[q=(p-_+1)*9%512]=(O*)p;o((d=************************************
****************************************************(O*************************
*****************************************************************)p)-p);o((p=**
*******************************************************************************
*******************************************************************************
*******************************************************************************
      ******************         **********************************************
        **************            *********************************************
          **********              *********************************************
            ******                ************(O*******************************
             ****                **********************************************
              *                 ***********************************************
                                ***********************************************
                              *************************************************
*                            **************************************************
**                         ****************************************************
                             **************************************************
                                   ********************************************
                                       *************)d)-d);o(p-(d=*************
                                         **************************************
                                          *************************************
                                           ***********    *********************
                                           *******          *******************
     ***                                  ******            *******************
********                              ********              *******************
********                              *******               *******************
********                               ****                 *******************
********              *                 **                 ********************
********             ***                                  *********************
*********            *****                              ***********************
*********           *******                            ************************
**********         **********                        **************************
************     ****(O****                            ************************
*********************                                        ******************
*****************                                                **************
**************                                                      ***********
*************                                                        **********
************                                                          *********
************                                                          *********
 ************                  ***              ****                 **********
   **************            *****              **********       **************
     **********              *****              *******************************
       ******                *****              *******************************
        ****                ******              *******************************
         **                 *******             *******************************
                           ********            ********************************
                         *********)            p));o((p=***********************
                        ************          *(O******************************
                      ********)d)-d);o      ((d=*******************************
                         ******************************************************
                              *************************************************
                                  *********************************************
                                    *******************************************
                                     ******************************************
                                      ****************    *********************
                                      ************          ****************(O*
 **              ***                 ***********            *******************
***              *****              **********              *******************
***              *****                *******               *******************
***              *****                 ****                 *******************
***              ******                 **                 ********************
***             ********                                  *********************
****            **********                              ***********************
*****          ************                            ************************
******        ***************                        **************************
*****)p     )-p);o(d-(p=***                            ************************
*********************                                        ******************
*****************                                                **************
**************                                                      ***********
*************                                                        **********
************                                                          *********
************                                                          *********
 ************                  ***              ****                 ****(O****
   **************            *****              **********       **************
     **********              *****              *******************************
       ******                *****              *******************************
        ****                ******              *******************************
         **                 *******             ***************************)d))
                           ;return+            0;}

これを保存してコンパイル・実行すると、元のメッセージが出てくる。

$ echo Hello | ./prog > tmp.c

$ gcc -o tmp tmp.c

$ ./tmp
Hello

アスキーアートは、どういうC/C++の仕様としてコンパイルしたかに依存して変わる。

C89/C90としてコンパイルした場合は、上記と同じ、ヒトデの形。

$ gcc -std=c90 -o prog_c90 prog.c -lm

$ echo A | ./prog_c90
                                                              #include<stdio.h>
typedef int O;void o(O _){putchar(_);}O main(){O*_[512],**p=_,**d,b,q;for(b=0;b
++<512;p=_+q)_[q=(p-_+1)*9%512]=(O*)p;o((d=************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
******************************************** ************(O*************** ****
*****************************************         *******************         *
****************************************            **************            *
****************************************              **********              *
****************************************                *******               *
*****************************************                ****                 *
******************************************                 *                 **
*******************************************                                 ***
********************************************                               ****
*********************************************                            ******
*******************)p)-p);o((p=****************                         *******
*********************************************                             *****
***************************************
***********************************
*********************************
********************************
*******************************
*******************************
 ************(O****         ****                 ****             ****
   **************            *******      ***********             ***********
     **********              ************************             *************
       ******                ************************             *************
        ****                *************************             *************
         **                 *************************             *************
                           **************************            **************
                         *****************)d)-d);{;}{;           }return+0;}

C99の場合は、ヒトデに目が入る。

$ gcc -std=c99 -o prog_c99 prog.c -lm

$ echo A | ./prog_c99
                                                              #include<stdio.h>
typedef int O;void o(O _){putchar(_);}O main(){O*_[512],**p=_,**d,b,q;for(b=0;b
++<512;p=_+q)_[q=(p-_+1)*9%512]=(O*)p;o((d=************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*************************************************   ***************************
***********************************************         ******************
**********************************************            **************
*************(O*******************************              **********
**********************************************                *******
***********************************************                *****
************************************************                **
*************************************************
**************************************************
***************************************************
*****************************************************                         *
***************************************************
**************************************)p)-p);
o((p=************************************                     *    *
***************************************
**************************************
*************************************
*************************************
 ******************         **********                 ****             ****
   **************            *************      ***********             *******
     **********              ******(O**********************             *******
       ******                ******************************             *******
        ****                *******************************             *******
         **                 *******************************             *******
                           ********************************            ********
                         ***********************************           ********
                        *************************************         *********
                      *****)d)-d);return+0;}

C++98の場合は、団子の形。

$ g++ -O3 -std=c++98 -o prog_cpp98 prog.c -lm

$ echo A | ./prog_cpp98
                                                              #include<stdio.h>
typedef int O;void o(O _){putchar(_);}O main(){O*_[512],**p=_,**d,b,q;for(b=0;b
++<512;p=_+q)_[q=(p-_+1)*9%512]=(O*)p;o((d=************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
********************************************************(O*********************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
********************************                  *****************************
************)p)-p);o((p=***                           *************************
************************                                 **********************
**********************                                     ********************
*********************                                        ******************
********************                                          *****************
*******************                                            ****************
*******************                             *    *         ****************
******************                              *    *         **(O************
******************                                             ****************
*******************                                            ****************
*********************                                        ******************
*************************                                **********************
*******************************                   *****************************
*************************************************************)d)-d);return+0;}

C++11の場合は、ただの円。

$ g++ -O3 -std=c++11 -o prog_cpp11 prog.c -lm

$ echo A | ./prog_cpp11
                                                              #include<stdio.h>
typedef int O;void o(O _){putchar(_);}O main(){O*_[512],**p=_,**d,b,q;for(b=0;b
++<512;p=_+q)_[q=(p-_+1)*9%512]=(O*)p;o((d=************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
********************************************************(O*********************
*******************************************************************************
************              *****************************************************
********                      *************************************************
*****                            **********************************************
***                                ********************************************
*                                    ******************************************
                                      *****************************************
                                       ****************************************
                                        ***************************************
                                        ******)p)-p);o((p=*********************
                                        ***************************************
                                         **************************************
                                         **************************************
                                        ***************************************
                                        ***************************************
                                        ***************************************
                                       *********************************(O*****
                                      *****************************************
*                                    *****************************
***                                ***************************
*****                            **************************
********                      ****************************
************              ******************************
*******************************************************
******************)d)-d);return+0;}

C11の場合は、アスキーアートを消す。

$ gcc -std=c11 -o prog_c11 prog.c -lm

$ echo A | ./prog_c11
                                                              #include<stdio.h>
typedef int O;void o(O _){putchar(_);}O main(){O*_[512],**p=_,**d,b,q;for(b=0;b
++<512;p=_+q)_[q=(p-_+1)*9%512]=(O*)p;o((d=************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
********************************************************(O*********************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*************************************************************************)p)-p)
;o((p=*************************************************************************
*******************************************************************************
*******************************************************************************
*******************************************************(O**********************
*******************************************************************************
*******************************************************************************
*******************************************************************************
*****************************)d)-d);return+0;}

解説

コード形状はCLANNADの伊吹風子。 ヒトデが好きという設定のため、それに合わせて、ヒトデのアスキーアートが出力される。 また、出力にポインタ参照の*が多数含まれているのは、sea star(ヒトデ)とC star(ポインタ参照)を掛けた洒落。

C/C++のバージョンを見分けるトリックは次の通り。

2 //* */2
- 1

見落としがちだが、生成コードも実は結構興味深い。 先頭の2行で、512要素のポインタの配列の中で、ポインタを512回たどると元の位置にもどる輪を作っている。 文字ごとに***...*でポインタを何度もたどり、配列先頭からの差の整数をASCIIコードとして出力する、というコードになっている。

実行のたびにアスキーアートが変わるのは、time()をシードとした乱数ではなく、ASLRをシードとして使っているとのこと。 賢い。cygwinではASLRが効かないので、コマンドライン引数でシードを指定することもできる。

同作者の慣習として、コードに自分自身のCRC32が埋め込まれている(3行目)。 また、開発の様子を撮影したと称するspoiler.htmlも添付されている。

賞名は[[2015/endoh1]]と対称的になっている。