AOJでShortCoding
先日告知してたAOJのコードです。
0001
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/problem.jsp?vol=0&id=0001&tle=1&mle=32768&title=List%20of%20Top%203%20Hills&doc=4&lang=jp
このコードは一番目に上位3つのうちどれかの値が含んでたらだめなコード。でも通っちゃった☆
値を比較して変数に確保していく方法ではなく、qsortを利用しました。
qsortの比較関数はショートコーディング書籍で書かれてた手法です。先人達はすごいです。
// 124byte s[]; M(int*a){return*1[&a]-*a;} main(i){ for(;~scanf("%d",s+i++);qsort(s,i,4,M)); exit(!printf("%d\n%d\n%d\n",*s,s[1],s[2])); }
出力を一度にするのではなく、1回に分けてループさせたほうが短くなった。
// 122byte s[]; M(int*a){return*a-*1[&a];} main(i){ for(;~scanf("%d",s+i);i++); for(qsort(s,i,4,M);i-8;)printf("%d\n",s[--i]); exit(0); }
まだまだ短く書けるようですが…どうやって書くんだろう。
0002
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/problem.jsp?vol=0&id=0002&tle=1&mle=32768&title=Digit%20Number&doc=4&lang=jp
log10を使って桁数を求める。ぐーぐる先生で調べた結果がこれだよ!
// 69byte main(a,b){ for(;~scanf("%d%d",&a,&b);) printf("%d\n",a=log10(a+b)+1); }
出力する桁数の値が1桁だと決め付ける、文字変換後、putsを利用すればさらに短く書けます。
// 63byte main(a,b){ for(;~scanf("%d%d",&a,&b);puts(&a)) a=log10(a+b)+49; }
たぶんこれが最短コードでしょう。cheatでない限り…。
0005
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/problem.jsp?vol=0&id=0005&tle=1&mle=32768&title=GCD%20and%20LCM&doc=4&lang=jp
最初は再帰を利用したコードを書いたのですが、ループで求めたほうが短くなりました。
// 98byte main(x,y,z,v,w) { for(;~scanf("%d%d",&x,&y);printf("%d %d\n",v,x/v*y)) for(v=x,w=y;w;w=z)z=v%w,v=w; }
素直にgcdを求めるアルゴリズムを書いてますが、速度を犠牲にすればさらに短く出来るようです。
0006
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/problem.jsp?vol=0&id=0006&tle=1&mle=32768&title=Reverse%20Sequence&doc=4&lang=jp
main再帰を利用しました。この問題の入力は 文字列[EOF] ではなく、文字列[改行][EOF] という入力なので、
改行が入力されたときに再帰が終わる処理をしています。
ここで少し脱線、main関数について。
main関数の第一引数にはコマンドオプションの個数(コマンド自体も含む)、
第二引数には各々へのポインタが格納されますが、オプションを何も指定しない場合は
第一引数には1、第二引数はゴミが格納されます。
main再帰ではこれらの初期値を条件分岐として利用出来ます。
// 71byte main(i,s){ i=getchar();return i-10&&main(i,0)+putchar(i)*s&&!puts(""); }
このコードを眺めていて、まだまだ短く出来るなぁ(無駄大杉)という感覚があったのですが
その感覚は当たっていたようで、さらに短くなりました。
// 57byte main(i){ return i-10&&main(getchar())&putchar(i-1?i:10); }
ショートコーディングは楽しいけど、AOJでは控えようと思います。
今度はProjectEulerかなぁ。