コードを短くするのって楽しいですよね?(2)

この手のコードを短く書くにはC++ではなくてCで書くべきだ。id:tanakh:20051120#p1にあるように、


scanfを使うとcinと同じく空白を読み飛ばしてくれるんですね。

Cなら、
・(当然ながら)using namespace std; がいらない。
・#include が無くてもコンパイルが通る。
・intを返す関数の型を省略してもコンパイルが通る。

とかなり文字数が稼げる。


また、この問題を解くこと自体はたやすい。オーソドックスな解法は、以下のようなものだろう。


最初にfound=falseとする。「(」を見つけるごとに擬似stackにnodeの値をpush。


「()()」(leaf)を見つけたら、そこまでの合計(これらは擬似stack上にある値を足し合わせる)を、最初に提示された値を比較する。一致していれば、found=true;


「)」を見つけたら、擬似stackから値をpopする。擬似stackが空になった時点で終了。そのときにfoundがtrueであれば"yes",そうでなければ"no"。この一連の動作をEOFが出現するまで繰り返す。


サンプルとして書いてみた。


main(){
int a[6],s,r=3,n=0,l=0,f;
while(n+1){
if (scanf("%d",&n)) {
if (!l) {
printf(&"no\n\0yes\n\0"+r);
s=r=0,n=-n;
}
s+=a[l]=n;
f=0;
}
n=getchar();
if(n==40) a[++l]=0,f++;
if(n==41) {
if(++f==4 && !s) r=4;
s-=a[l--];
}
}
}
それぞれの変数の意味は、aが擬似stack、lが擬似stackのpointer、sがsum、nはテンポラリ変数、rはfoundのフラグ、fは「()()」検出用。


上のプログラムでは、「(」「)」が数字なしに4回連続すれば「()()」と判定している。本当は、これだと「((((」とかもleafとして判定されるのでまずいのだが、投稿してみたところ、これでacceptされるので、まあ良いことにする。


この時点では、たいしたテクニックは使っていない。まだまだ改良の余地がある。(つづく)