Cプリプロセッサの最悪の悪用
xxxxxxxxxx
#ifndef pdbq
#ifndef n
#define n 05
#endif pqbd
#define dpqb __FILE__
#define ppbd "Move disk %d from peg %d to peg %d\n"
#define pdbq
#if n&01
#define dqbp
#endif bpdq
#if n&02
#define dbpq
#endif pbdq
#if n&04
#define pbqd
#endif qbpb
#if n>>3
#define bqdp
#endif pbbq
main(){ pdbq
printf( pdbq
#include dpqb
#define qbdp
#include dpqb
);} qbdp
#else dpdp
#ifdef dqbp
#define bdpq
#endif bpdd
#ifdef dbpq
#define bdpq
#endif pqpb
#ifdef pbqd
#define bdpq
#endif pdpp
#ifdef bqdp
#define bdpq
#endif pdpp
#ifdef bdpq
#undef bdpq
#ifndef dqbp
#define dqbp
#ifndef dbpq
#define dbpq
#ifndef pbqd
#define pbqd
#ifndef bqdp
#define bqdp
#else dbqb
#undef bqdp
#endif qdqb
#else pdbq
#undef pbqd
#endif qdbp
#else pqbb
#undef dbpq
#endif pqbd
#else bbpp
#undef dqbp
#endif ppqb
#include dpqb
#ifndef dqbp
#ifndef dbpq
#ifndef pbqd
#ifndef bqdp
#define bdpq
#endif pbpp
#endif qpdp
#endif ddpb
#endif qppb
#ifdef bdpq
#undef bdpq
#ifndef qbdp
pdbq ppbd
#else qbbd
#ifdef pqdb
,1,2,3 pqdb
#undef pqdb
#define qdbp
#else bdbb
#ifdef qdbp
,1,3,1 qdbp
#undef qdbp
#else bdbd
,1,1,2 pdbq
#define pqdb
#endif qppq
#endif pqpb
#endif bpdd
#else pqpq
#ifndef qbdp
pdbq ppbd
#else qqqb
,1 pdbq
#ifdef dqbp
+1 dqbp
#endif qqdb
#ifdef dbpq
+2 dbpq
#endif ppqb
#ifdef pbqd
+4 pbqd
#endif pqpp
#ifdef bqdp
+8 bqdp
#endif bbpb
#ifdef pqdb
#ifdef dqbp
,1,3 dqbp
#else pddp
,3,1 pdbq
#endif qpqq
#else dbqb
#ifdef qdbp
#ifdef dqbp
,2,1 dqbp
#else pqdb
,1,2 pdbq
#endif dbdp
#else pdpp
#ifdef dqbp
,3,2 dqbp
#else pdbb
,2,3 pdbq
#endif pqpp
#endif qbdp
#endif pqpp
#endif pdbp
#endif pqdp
#include dpqb
#ifdef dqbp
#undef dqbp
#ifdef dbpq
#undef dbpq
#ifdef pbqd
#undef pbqd
#ifdef bqdp
#undef bqdp
#else qddb
#define bqdp
#endif ppqp
#else bddq
#define pbqd
#endif ddbq
#else bbdb
#define dbpq
#endif qqbd
#else ddbq
#define dqbp
#endif qbdb
#endif qbdb
#endif qbpp
引用元: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文字。
識別子はb
、d
、p
、q
を組み合わせた4文字ばかりで非常に読みにくい。