a[900]; b;c;d=1 ;e=1;f; g;h;O; main(k,
l)char* *l;{g= atoi(* ++l); for(k=
0;k*k< g;b=k ++>>1) ;for(h= 0;h*h<=
g;++h); --h;c=( (h+=g>h *(h+1)) -1)>>1;
while(d <=g){ ++O;for (f=0;f< O&&d<=g
;++f)a[ b<<5|c] =d++,b+= e;for( f=0;f<O
&&d<=g; ++f)a[b <<5|c]= d++,c+= e;e= -e
;}for(c =0;c<h; ++c){ for(b=0 ;b<k;++
b){if(b <k/2)a[ b<<5|c] ^=a[(k -(b+1))
<<5|c]^= a[b<<5 |c]^=a[ (k-(b+1 ))<<5|c]
;printf( a[b<<5|c ]?"%-4d" :" " ,a[b<<5
|c]);} putchar( '\n');}} /*Mike Laman*/
↑のコードは、1984年(第一回)IOCCCの登場作品です。
このコードをコンパイルして実行すると、数字の渦巻きが表示されます。( ^ω^)オモスレー
数字の渦巻きって何ぞや??と思われた方、↓の画像をご覧下さい。
中央に1があり、そこから反時計回りに任意の数まで、数字が順に並んで表示されます。
C言語の標準出力は、
左 → 右
そして、
上
↓
下
へと表示されるため、最終的に渦巻き状に数字を配置するには、出力の都度、計算が必要になります。
ちょっと面白いです^^;)
VC++2005での実行方法:
特にコードを修正する必要もなく、そのままコンパイル、実行できます。
ただし、以下の様な警告が表示されるため、
----------------------------------------------------------------
warning C4013: 関数 'atoi' は定義されていません。int 型の値を返す外部関数と見なします。
warning C4013: 関数 'printf' は定義されていません。int 型の値を返す外部関数と見なします。
warning C4013: 関数 'putchar' は定義されていません。int 型の値を返す外部関数と見なします。
----------------------------------------------------------------
これが気になる方は、コードの先頭に以下2行を記述して下さい。
#include <stdio.h>
#include <stdlib.h>
出来上がった実行ファイルに、パラメータ(幾つの数までの渦巻きを表示するか)を渡せば、
数字の渦巻きが表示されます。
それではいよいよ、お待ちかね、アルゴリズムの解説を行います。キタ━(゚∀゚)━!!!!!
冒頭のコードですが、そのままだと非常に見辛い!!
・・・というわけで、まず改行 及び インデントを入れます。
そして、変数O(オー)が、0(ゼロ)と紛らわしい為「r」に置換します。
変数l(エル)が、1(イチ)や|(or演算子)と紛らわしい為、「s」に置換します。
ついでに、お行儀良く#include <stdio.h>と、#include <stdlib.h>も付け足します。
という訳で、冒頭のコードを多少読みやすく(?)修正したコードがコチラ↓↓
#include <stdio.h>
#include <stdlib.h>
a[900];
b;
c;
d=1;
e=1;
f;
g;
h;
r;
main(k,s)char**s;
{
g = atoi(*++s);
for(k=0; k*k < g; b=k++>>1);
for(h=0; h*h<=g; ++h);
--h;
c = ( (h += g>h*(h+1)) -1 ) >> 1;
while(d <=g){
++r;
for(f=0; f< r && d<=g; ++f)
a[b<<5|c] =d++, b+=e;
for(f=0; f<r && d<=g; ++f)
a[b<<5|c]=d++, c+=e;
e= -e;
}
for(c=0; c<h; ++c){
for(b=0; b<k; ++b) {
if(b <k/2)
a[b<<5|c] ^=a[(k-(b+1)) << 5|c] ^= a[b<<5|c] ^= a[(k-(b+1))<<5|c];
printf(a[b<<5|c] ? "%-4d" : " ",a[b<<5|c]);
}
putchar('\n');
}
}
/* Mike Laman */
このコードの先頭から読み解いていきます。
C言語では、変数の型が宣言されない場合、int型変数とみなします。
その為、グローバル変数のa,b,c,d,e,f,g,h,rは int型の変数です。
main関数のパラメータkも、int型の変数です。
また、main(k,s)char**s;{} は古いコードの書き方ですが、現在でいう main(k, char ** s){} に相当します。
(つまり、main(k,s)char**s;{} の部分は、変数名の違いこそあれ、良く目にする main(int argc, char ** argv){} と同じ物だという事です^^;)
その下の g = atoi(*++s) ですが、
プログラム実行直後、
*sには第1パラメータ(通常はプログラムのパス)文字列へのポインタ、
*(s+1)には第2パラメータ(ここでは、ユーザが入力した任意の数)文字列へのポインタ が格納されています。
つまり、g = atoi(*++s)は、g = atoi( *(s+1) )と直す事ができ、変数gにユーザが入力した値を代入しているだけです。