メモ

yukicoderでゆるふわgolf

yukicoder No.24 数当てゲーム

問題はこちら
No.24 数当てゲーム - yukicoder

答えの可能性が残っているかどうかをbitで保存しておく
質問した4数もbitで保存して、YESならbitand、NOならbitnotしてからbitand
最終的にはbitが残っているのは1箇所だけになるのでそこを出力

int main(){
	int n=1023,t,i,x,y;
	//nに情報を保存。初期値として0~9までbitを立てておく
	char s[4];
	scanf("%d",&t);
	while(t--){
		x=0;i=4;
		while(i--){
			scanf("%d",&y);
			x|=1<<y;
			//読み込んだ数をbitで保存
		}
		scanf("%s",s);
		n&=*s=='N'?~x:x;
		//読み込んだ文字列はstrcmpしなくても1文字目だけ見れば判別可能
	}
	i=0;
	while(n/=2)i++;
	printf("%d\n",i);
	return 0;
}

nの初期化がいやだからbitの保存を逆にする。つまり、答えではないことが確定したところにbitがたつ
あとは1つ目の数を読み飛ばしたりいつもどおり短縮

char s[4];
n,x;
main(y){
	for(;gets(s);)for(n|=*s>78?~x:x,x=0;scanf("%d",&y)>0;x|=1<<y);
	//文字列がきたせいでscanfできなくなった時は-1ではなく0が返ってくる
	//ループを抜けたときxは0
	for(;n&1<<x;x++);
	x=!printf("%d",x);
}

scanfの読み込み失敗によってYES,NOの前の空白が読み飛ばされるのでgetsで読めるようになっている

charと書くのはまどろっこしい
ところでCではリトルエンディアンで値が保存されているので

int s;
gets(&s);

を実行すると、NOだった時には'N'+('O'<<8)=20302が、YESだと5457241が返ってくる。
(実際には後ろの方に前のデータが残ることがあることに注意)
これを利用して次のように短縮できる

s,n,x;
main(y){
	for(;gets(&s);)for(n|=s>3e4?~x:x,x=0;scanf("%d",&y)>0;x|=1<<y);
	for(;n&1<<x;x++);
	x=!printf("%d",x);
}

114B


2017/07/30追記
Aの最下位bitはA&-Aで得られたので、次のように短縮できる

s,n,x;
main(y){
	for(;gets(&s);)for(n|=s>3e4?~x:x,x=0;scanf("%d",&y)>0;x|=1<<y);
	printf("%.f",log2(~n&-~n));
}

入力に1つでもYESがあれば~nは1<< ansに一致するが、すべてNOだったときはその-1倍になるので、&以下が必要
この手間を嫌ってnに保存するbitを反転させても同じ長さになった

s,n,x;main(y){for(;gets(&s);)for(n|=s>3e4?~x:x,x=0;scanf("%d",&y)>0;x|=1<<y);printf("%d",log2(~n&-~n));}
s,n=1023,x;main(y){for(;gets(&s);)for(n&=s>3e4?x:~x,x=0;scanf("%d",&y)>0;x|=1<<y);printf("%d",log2(n));}

105B