最高の位置独立コード
xxxxxxxxxx
main(i)??<char c??(81??)??(81??);for(i=0;gets(*(c+i)); i++);A(i,c);J(i-1,c);??>
/* { /KC 0000 K } */
S(c,r,i)char*c; ??<printf("|");for(;*(c+i); i++)putchar(T(*(c+i),r));U(c,i);??>
char* B,*r; X(c,k)??<return isupper(c)?0:V(*(r+k),B); ??>
J(i,c,j)char*c; ??<for(j=t(i,0) ; j+j<i; j++)L(c,j,i-j); M(i,c); ??>
U(c,i)char*c; ??<while(i++<80)printf(" "); puts("|"); ??>
A(i ,c,j ,k) char *c; ??< for(j= -1; ++j<i; )for (k =j; k<i; )D(c ,j, k++); ??>
R(c,r) char *c; ??< printf( "/%-80s|??/n" ,c); for (; r< 13; r++)S (c,r,0); ??>
t(a,b)??<return a;??>
M(i,c)char c??(81??)??(81??);??<i++;while(i--)t(1,0)?puts(*(c+i)):P(*(c+i));??>
char*d= "yyzzyzz zz z0y000 zz 00yzz00y00yzz Brian Westley zyy00yy0yy 0" ; ; ;
#define t(a,b) t(b,a)
char* K;Y (c ,r) ??< int i=V ( tolower (c) ,K); return(i <0)?1 :Z(c ,r, i); ??>
char*m= "7831734578 9547693564569528334164263z284106579 52626423135477"; ; ; ;
P(c)char*c; ??<Q(1,0); R(c,1 ); Q(0,0); ??>
char* d,*m,*B; Z(c,i,k)??<return W(i, V(*(d+k), B),V(*( m+k),B) ,X(c, k)); ??>
char*K= "gh$j|lm'pq&rv<x>z#);@_winky,.%/+*!=3-284106579 (:obfuscated??/?" ; ;
L(c,i,j)char c??(81??)??(81??);??<G(* (c+i),*(c+j));??>
char*r= "008y8yy8yyyyz8z8z88888z0yyz888 8888 88y00zz00z0088";
D(c,i,j) char c??(81??)??(81??);??<E(*(c+i),*(c+j));??>
E(r,s)char*r,*s; ??< if(t( 0,1)&& F(r,s)<0)G(r,s); ??>
H()??<static i=0; if (!i) ??< time(&i); srand(i); ??> return rand()-rand(); ??>
F(r,s)char*r,*s; ??<return t(0,1)?H():strcmp(r,s); ??>
T(c,r) ??< return Y(c, r)?'??(' :' '; ??>
G(r,s)char*r,*s; ??<char t??( 81??); strcpy(t,r); strcpy(r,s); strcpy(s,t); ??>
W(r,a,b,c)??<return r==a||r==b||r==c; ??>
Q(t,i)??< printf(t?" ":"|"); for(; i<80; i++) printf("_"); puts(t?"_":"|"); ??>
char*B=" yz0123456789";
V(c,k,i) char*k; ??<for (i=0; *(k+i) &&*(k+i)!=c; i++); return *(k+i)?i:-1; ??>
引用元:https://www.ioccc.org/2001/westley.c
審査員・作者による説明:https://github.com/ioccc-src/winner/blob/main/2001/westley.hint
元プログラムの動作は、入力を行単位でランダムにシャッフルして表示する。
$ gcc -trigraphs -o westley westley.c
$ echo -e '1\n2\n3' | ./westley
1
3
2
$ echo -e '1\n2\n3' | ./westley
2
3
1
$ echo -e '1\n2\n3' | ./westley
2
1
3
元のソースコード自身をシャッフルしてもコンパイルできる。 そして、シャッフル結果に依存してさまざまな挙動をするプログラムになる(変わらない場合もある)。
次はただのcatになった例。
$ ./westley < westley.c > tmp.c
$ gcc -trigraphs -o tmp tmp.c
$ echo -e '2\n1\n3' | ./tmp
2
1
3
次は行反転コマンドになった例。
$ ./westley < westley.c > tmp.c
$ gcc -trigraphs -o tmp tmp.c
$ echo -e '1\n2\n3' | ./tmp
3
2
1
次はsortになった例。
$ ./westley < westley.c > tmp.c
$ gcc -trigraphs -o tmp tmp.c
$ echo -e '2\n1\n3' | ./tmp
1
2
3
$ echo -e '3\n2\n1' | ./tmp
1
2
3
そして、パンチカード風に出力するものになった例。
$ echo "Hello, world" | ./tmp
_________________________________________________________________________________
/Hello, world |
|[[[[[ [[[[ |
| [[[ [[[[ |
| [ [ [ [ |
| |
| |
| [[ [ [ |
| [ |
| [ |
| [ [[ |
| |
|[ [ |
| [ |
|________________________________________________________________________________|
$ echo '&-0123456789ABCDEFGHIJKLMNOPQR/STUVWXYZ:#@'"'"'=".<(+|./t*);,%_>?abcmnoxyz^[]{}\' | ./tmp
_________________________________________________________________________________
/&-0123456789ABCDEFGHIJKLMNOPQR/STUVWXYZ:#@'=".<(+|./t*);,%_>?abcmnoxyz^[]{}\ |
|[ [[[[[[[[[ [[[[[[[ [[[[[[ [[[[[[ |
| [ [[[[[[[[[ [ [[[[ [[[[[[[[[[[[ |
| [ [[[[[[[[[ [ [[ [[[[ [[[ [[[[[[[[[ |
| [ [ [ [ [ [ [ [[[[[[ |
| [ [ [ [ [ [ [ [[[[[[ |
| [ [ [ [ [ [[ [ [ [ [ [[[[[[ |
| [ [ [ [ [ [ [ [ [ [ [[[[[[ |
| [ [ [ [ [ [ [ [ [ [ [[[[[[ |
| [ [ [ [ [[ [ [ [ [ [[[[[[ |
| [ [ [ [ [ [ [ [ [[[[[[ |
| [ [ [ [ [[[[[[[[[[[[ [[[[[[[[ [ [[[[[[ |
| [ [ [ [ [ [[[[[[[ |
|________________________________________________________________________________|
westley.cは空行やコメント行を除いて実質28行なので、その順列の数は28! = 304,888,344,611,713,860,501,504,000,000で、このいずれもビルド可能になっている。そして、挙動で分類すると12種類になる。12種類の内訳は組み合わせ。
組み合わせなので、ソートしつつ反転してパンチカード風に表示するコマンドも出てくることがある。
このコードの着想は、パンチカードの扱いにあるとのこと。 パンチカードの束をうっかり床に落とすと、順番がわからなくなって大変なことになる。 しかしC言語は行の順番を変えても意味が変わらないように書くことができる(落下耐性がある)ので便利、というネタ。
このコードは行をシャッフルすることで、パンチカードの落下をシミュレーションする。 そして自分自身を落としても(シャッフルしても)動く。 なんなら、順番を変えたら違う意味で動くようにも書けたので書いた。
実際にシャッフルで所望の挙動を得るのは大変なので、ちょっと便利な工夫がされている。
sort westley.c
をしたら、行の順序はいじらずにパンチカード風表示をするだけのコードが得られるsort -b westley.c
をしたら、行の反転だけをするコードが得られる(-b
は行頭の空白を無視してソートするオプション)パンチカードはASCIIではなくEBCDICという古い文字コードで表現される。
EBCDICでは一部の文字("^[]{}\"
など)が使えないので、コードはこれらを避けて書かれている。
そのためにトライグラフを多用しており、gcc -ansi
かgcc -trigraphs
でないとビルドできない。
/* { /KC 0000 K } */
という謎のコメントは、EBCDICでパンチカードにしたときに(-:
になるパターン。
$ ./tmp < westley.c
...
_________________________________________________________________________________
/ /* { /KC 0000 K } */ |
| [ [ [ |
| [ [ [ [ [ [ |
| [ [ [ [[[[ [ [ |
| [ [ [ [ [ |
| [ [ [ [ |
| [ [ [ |
| [ [ [ [ |
| [ [ |
| [ [ |
| [ [ |
| [ [ [ [ |
| [ [ |
|________________________________________________________________________________|
...
賞名の位置独立コードは、各行をどこに置いても動くことを指しているが、本来はどのアドレスに配置されても動く機械語のことを言う。
実に神がかっている。これは、westley最後の作品(2020年現在)。次の作品がみたい。