Worst Abuse of the C Preprocessor

Cプリプロセッサの最悪の悪用

受賞者:Mark Schnitzius and David Van Brackle

引用元:https://www.ioccc.org/1995/vanschnitz.c

審査員・作者による説明:https://github.com/ioccc-src/winner/blob/main/1995/vanschnitz.hint

動作

ハノイの塔の解を表示する。デフォルトではディスク5枚。

$ gcc vanschnitz.c -o vanschnitz

$ ./vanschnitz
Move disk 1 from peg 1 to peg 2
Move disk 2 from peg 1 to peg 3
Move disk 1 from peg 2 to peg 3
Move disk 3 from peg 1 to peg 2
Move disk 1 from peg 3 to peg 1
Move disk 2 from peg 3 to peg 2
Move disk 1 from peg 1 to peg 2
Move disk 4 from peg 1 to peg 3
Move disk 1 from peg 2 to peg 3
Move disk 2 from peg 2 to peg 1
Move disk 1 from peg 3 to peg 1
Move disk 3 from peg 2 to peg 3
Move disk 1 from peg 1 to peg 2
Move disk 2 from peg 1 to peg 3
Move disk 1 from peg 2 to peg 3
Move disk 5 from peg 1 to peg 2
Move disk 1 from peg 3 to peg 1
Move disk 2 from peg 3 to peg 2
Move disk 1 from peg 1 to peg 2
Move disk 3 from peg 3 to peg 1
Move disk 1 from peg 2 to peg 3
Move disk 2 from peg 2 to peg 1
Move disk 1 from peg 3 to peg 1
Move disk 4 from peg 3 to peg 2
Move disk 1 from peg 1 to peg 2
Move disk 2 from peg 1 to peg 3
Move disk 1 from peg 2 to peg 3
Move disk 3 from peg 1 to peg 2
Move disk 1 from peg 3 to peg 1
Move disk 2 from peg 3 to peg 2
Move disk 1 from peg 1 to peg 2

ディスクの枚数はコンパイル時に指定できる。

$ gcc vanschnitz.c -o vanschnitz -Dn=3

$ ./vanschnitz
Move disk 1 from peg 1 to peg 2
Move disk 2 from peg 1 to peg 3
Move disk 1 from peg 2 to peg 3
Move disk 3 from peg 1 to peg 2
Move disk 1 from peg 3 to peg 1
Move disk 2 from peg 3 to peg 2
Move disk 1 from peg 1 to peg 2

解説

Cプリプロセッサによってハノイの塔を解いている。

#include __FILE__によって再帰することでループを行い、最終的にprintfを1つ呼び出すだけのmain関数になる。 例えばディスク3枚の設定(-Dn=3)でプリプロセスをした結果を整形したらこうなる。

main(){
  printf(
    "Move disk %d from peg %d to peg %d\n"
    "Move disk %d from peg %d to peg %d\n"
    "Move disk %d from peg %d to peg %d\n"
    "Move disk %d from peg %d to peg %d\n"
    "Move disk %d from peg %d to peg %d\n"
    "Move disk %d from peg %d to peg %d\n"
    "Move disk %d from peg %d to peg %d\n"
    ,1,1,2
    ,1
    +1
    ,1,3
    ,1,2,3
    ,1
    +2
    ,1,2
    ,1,3,1
    ,1
    +1
    ,3,2
    ,1,1,2
  );
}

このとおり、ハノイの塔の解自体はプリプロセス時にすべて特定してしまうので、プリプロセッサで解いていると言える。

コードはとてもいい感じに整形されている。 大体マクロ定義文ばかりで、定義はほぼ4文字。 識別子はbdpqを組み合わせた4文字ばかりで非常に読みにくい。