引用元:https://www.ioccc.org/1988/westley.c
審査員・作者による説明:https://github.com/ioccc-src/winner/blob/main/1988/westley.hint
動作
円周率を計算する。
$ gcc -traditional-cpp -o westley westley.c
$ ./westley
3.141
解説
円の形状のコードで円周率を計算する。IOCCCの中ではかなり有名な作品。westleyの2作目。
1行目の_-_-_-_
は次のように展開される。
-F<00||--F-OO--;--F<00||--F-OO--;--F<00||--F-OO--;--F<00||--F-OO--;
ひとつめだけ-F<00||--F-OO--
、ふたつめ以降は--F<00||--F-OO--
になっているところがポイント(先頭のマイナスの数が違う)。
このコードの実行中、F
はゼロか負になっている。
よって、ひとつめでは-F<0
は偽となり、--F-OO--
が実行されてともに1ずつ減る。
ふたつめ以降は、--F<0
が真となるので、--F-OO--
は実行されない。
ただし、条件式のほうでF
が1減ることに注意。
まとめるとこの1行は、OO
を1減らし、F
をアンダースコアの数(≒横幅)だけ減らす効果がある。
コード全体としては、OO
は行数だけ減るので、コードが描く円の直径(に-1をかけたもの)に相当する。
また、F
が減る量は円の面積(に-1をかけたもの)に相当する。
よって、円の面積の公式により、(-OO/2) * (-OO/2) * π ≒ -F
と言える。
このプログラムは4 * F / OO / OO
を計算することで、円周率を出力している。
OO
は00
と紛らわしくなっており、FOO
はメタ構文変数にかけていると思われる。
westley.hintにあるように、オリジナルのコードを動かすには
#define _ -a
-_
を--a
と解釈するコンパイラが必要。
-traditional-cpp
をつければコンパイルできるが、この問題が解決されたwestley.fix.cも用意されている。