メモ

yukicoderでゆるふわgolf

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