メモ

yukicoderでゆるふわgolf

yukicoder No.521 Cheeses and a Mousetrap(チーズとネズミ捕り)

問題はこち
No.521 Cheeses and a Mousetrap(チーズとネズミ捕り) - yukicoder

K=0及びK>Nのときは0。
そうでないとき、該当する箱はK番目かN+1-K番目。この2つが一致するとき危険は箱は1つで、一致しないとき2つ。

n,k;
main(){
	scanf("%d%d",&n,&k);
	if(k==0||k>n)printf("0");
	else if(k==n+1-k)printf("%d",n-1);
	else printf("%d",n-2);
}

ぎゅっとするだけ。条件分岐はどちらでも同じになった

main(n,k){scanf("%d%d",&n,&k);printf("%d",!k|k>n++?0:n-3+!(n-k-k));}
main(n,k){scanf("%d%d",&n,&k);printf("%d",k&&k<++n?n-3+!(n-k-k):0);}

68B

yukicoder No.514 宝探し3

問題はこち
No.514 宝探し3 - yukicoder

N=100000とおく
(0,0)及び(N,0)の2点からの距離が分かれば特定できる。
なぜなら、それぞれの点からの距離をd1,d2、宝の位置を(x,y)とすれば
x+y=d1
(N-x)+y=d2
となるので、この連立方程式を解く事により
x=(d1-d2+N)/2
y=(d1+d2-N)/2
が得られるからである。
これをそのまま実装する

x,y,d1,d2,N=100000;
main(){
	printf("0 0\n");
	scanf("%d",&d1);
	if(d1==0)return 0;
	printf("100000 0\n");
	scanf("%d",&d2);
	if(d1==2)return 0;
	printf("%d %d\n",(d1-d2+N)/2,(d1+d2-N)/2);
}

よく考えると、2回目に質問する座標は(d1,0)でもよいことがわかる(宝の位置が質問する点より左にありさえすれば、(N,0)と同じ式が得られるので)
このことに注意しつつ、あとでループの形にできるように、同じような形になるよう書き換えたのがこれ

a,b;
main(){
	fflush(!printf("%d %d\n",a-b/2,b/2));scanf("%d",&a);
	if(a)fflush(!printf("%d %d\n",a-b/2,b/2)),scanf("%d",&b);
	if(b)fflush(!printf("%d %d\n",a-b/2,b/2));
}

ループ変数iはmainの引数に入れたいので、1から始まることを考えると
(i,a,b)が(1,0,0),(2,非0,0),(3,非0,非0)の時だけscanfをし、(2,0,0),(3,非0,0)のときはscanfを実行しないように分岐したい。
これはぐっと睨むとi%2^!a^!bと書けることがわかるので次のように書ける

a,b;main(i){for(;i%2^!a^!b&&fflush(!printf("%d %d\n",a-b/2,b/2))+scanf("%d",i++%2?&a:&b););}

ここでa,bのアドレスを調べると、b,aの順に並んでいることがわかるので、scanfの引数の分岐をまとめることができる

a,b;main(i){for(;i%2^!a^!b&&fflush(!printf("%d %d\n",a-b/2,b/2))+scanf("%d",&b+i++%2););}

89B

yukicoder No.516 赤と青の風船

問題はこちら
No.516 赤と青の風船 - yukicoder

入力を読み込んで、それがBLUEかREDか判別する

char s[10];
b,r;
main(){
	for(int i=0;i<3;i++){
		scanf("%s",s);
		if(strcmp(s,"BLUE")==0)b++;
		else r++;
	}
	if(b<r)puts("RED");
	else puts("BLUE");
}

各文字列の長さが短いのでint型に読み込んでも大丈夫そう。
文字数が違うので、BLUEとREDをint型として見た時の値の大きさは大きく異なり、例えばこういうのが考えられる

s;
main(i){
	for(;gets(&i);s+=i>>30);
	puts(s>1?"BLUE":"RED");
}

ただ、もっとよく考えると、BLUEがINT_MAX/2より僅かに大きいことを利用して次のようにできる

s;
main(i){
	for(;gets(&i);s+=i);
	puts(s<0?"BLUE":"RED");
}

54B

yukicoder No.512 魔法少女の追いかけっこ

問題はこちら
No.512 魔法少女の追いかけっこ - yukicoder

追いかける側がA[i]地点にあるi番目の交差点にたどり着いた時、追いかけられる側はA[i]/X*Y地点にいる。これがA[i+1]より真に大きければ見失う。
除算をすると誤差で落とされるケースが多数あるらしいので、A[i]/X*Y≦A[i+1]をA[i]*Y≦A[i+1]*Xと変形して整数の範囲でやる

a[100],x,y,n;
main(){
	scanf("%d%d%d",&x,&y,&n);
	for(int i=0;i<n;i++)scanf("%d",a+i);
	for(int i=0;i<n-1;i++)if(a[i]*y>a[i+1]*x){
		puts("NO");
		return 0;
	}
	puts("YES");
}

前から順番に読み込めば配列はいらない

p,q,f;
main(a,b){
	for(scanf("%d%d%*d",&a,&b);~scanf("%d",&q);p=q)f|=a*q<b*p;
	puts(f?"NO":"YES");
}

94B

scanfを1つにするパターンも考えたが、Nの読み飛ばしが難しくて短くならなかった

p,q,f;main(a,b){for(scanf("%d%d%*d",&a,&b);~scanf("%d",&q);p=q)f|=a*q<b*p;puts(f?"NO":"YES");}
a,b,p,q,f;main(i){for(;~scanf("%d",&q);*(--i?~i?i+2?&p:&q:&b:&a)=q)f|=a*q<b*p;puts(f?"NO":"YES");}
a,b,p,q,f;main(i){for(;~scanf("%d",&q);~i--?i>-2?a=b,b=q:(p=q):0)f|=a*q<b*p;puts(f?"NO":"YES");}

2017/08/01追記
やっぱりscanfを1つにしたほうが短くなった

a,b,p,q,f;
main(i){
	for(;~scanf("%d",a?b?&q:&b:&a);--i+2?p=q:0)f|=a*q<b*p;
	puts(f?"NO":"YES");
}

92B