メモ

yukicoderでゆるふわgolf

yukicoder No.668 6.0*10^23

問題はこちら
No.668 6.0*10^23 - yukicoder

桁上りなどに気をつけて、3桁目を四捨五入するコードを書く

char s[1000010];
int main(){
	gets(s);
	int s0=s[0]-48;
	int s1=s[1]-48;
	int s2=s[2]-48;
	int n=strlen(s)-1;
	
	if(s2>=5)s1++;
	if(s1>9){
		s1=0;
		s0++;
	}
	
	if(s0>9)printf("1.0*10^%d",n+1);
	else printf("%d.%d*10^%d",s0,s1,n);
}

これを素直に縮めるとこう

char s[1<<17];
main(f){
	gets(s);
	s[2]>52?++s[1]>57?s[1]=48,++*s>57?*s=49,f=0:0:0:0;
	printf("%c.%c*10^%d",*s,s[1],strlen(s)-f);
}

123B
配列をとらずに入力を1Bずつ読むとむしろ長くなる

a,b,c,t;
main(f){
	for(;read(0,&t,1);)++c<3?a=b,b=t:c<4?t>52?++b>57?b=48,++a>57?a=49,f=0:0:0:0:0;
	printf("%c.%c*10^%d",a,b,c+~f);
}

125B

よく考えると、出力すべき「a.b*10^c」の「a.b」のところは%.1fでいけそうじゃない?

c;
float s,z=1;
main(t){
	for(;read(0,&t,1);z*=.1)c++<3?s+=(t-48)*z:0;
	printf("%.1f*10^%d",s,s>9.95?s/=10,c-1:c-2);
}

しかしこれは「3350」などで丸めに失敗し「3.3*10^3」と出力されてしまう。
じゃあ4桁読めばいいじゃん、とc++<3をc++<4に変えると、今度は「335」などで改行を読み込んでしまい困る。
「4桁目以降は全て1」と思うことにしてc++<3?s+=(t-48)*z:0;の最後の0をs+=c++<3?(t-48)*z:z;とzに取り替えるとうまくいく。

c;
float s,z=1;
main(t){
	for(;read(0,&t,1);z*=.1)s+=c++<3?(t-48)*z:z;
	printf("%.1f*10^%d",s,s>9.95?s/=10,c-1:c-2);
}

111B

2019/03/16追記
c-1,c-2なんて、いかにも「cをmainの引数にしてください」という感じがする

t;
float s,z=1;
main(c){
	for(;read(0,&t,1);z*=.1)s+=c-->-2?(t-48)*z:z;
	printf("%.1f*10^%d",s,s>9.95?s/=10,-c:~c);
}

yukicoder No.677 10^Nの約数

問題はこちら
No.677 10^Nの約数 - yukicoder

約数は2^i*5^jの形をしている。全て求めてソートすればよい。
ここでは約数を保存せず、毎回「今まで出力したものより大きい最小のもの」を探すようにしている。O(N^4)

main(){
	int n;
	scanf("%d",&n);
	long M=0;//直前に出力したもの
	for(int cnt=0;cnt<(n+1)*(n+1);cnt++){
		//約数は全部で(n+1)*(n+1)個
		long m=2e18;//Mより大きな最小の約数(=次に出力するもの)
		for(int i=0;i<=n;i++)for(int j=0;j<=n;j++){
			long t=pow(2,i)*pow(5,j);
			if(t>M&&t<m)m=t;
		}
		printf("%ld\n",m);
		M=m;
	}
}

まずざっと縮める

long M,m,t;i,j,x;
main(n){
	for(scanf("%d",&n);x++<~n*~n;printf("%ld\n",M=m))
		for(m=2e18,i=0;i<=n;i++)for(j=0;j<=n;j++)(t=(t=pow(5,j))<<i)>M&t<m?m=t:0;
}

for文をまとめる

for(m=2e18,i=0;i<=n;i++)for(j=0;j<=n;j++)(t=(t=pow(5,j))<<i)>M&t<m?m=t:0;
for(m=2e18,i=0;j<=n?(t=(t=pow(5,j++))<<i)>M&t<m?m=t:1:(j=0,i++<n););
for(m=2e18,i=0;j>n?j=0,i++<n:(t=(t=pow(5,j++))<<i)>M&t<m?m=t:1;);

もう1つのfor文をまとめても短くならなかった

long M,m,t;i,j,x;main(n){for(scanf("%d",&n);x++<~n*~n;printf("%ld\n",M=m))for(m=2e18,i=0;j>n?j=0,i++<n:(t=(t=pow(5,j++))<<i)>M&&t<m?m=t:1;);}
long M,m=1,t;i,j,x;main(n){for(scanf("%d",&n);j>n?j=0,i++>=n?i=!printf("%ld\n",M=m),m=2e18,++x<~n*~n:1:(t=(t=pow(5,j++))<<i)>M&&t<m?m=t:1;);}

何れにせよ140B

yukicoder No.661 ハローキティはりんご3個分

問題はこちら
No.661 ハローキティはりんご3個分 - yukicoder

要するにFizzBuzz

main(){
	int n;
	scanf("%d",&n);
	while(n--){
		int t;
		scanf("%d",&t);
		if(t%40==0)puts("ikisugi");
		else if(t%8==0)puts("iki");
		else if(t%10==0)puts("sugi");
		else printf("%d\n",t/3);
	}
}

No.9002 FizzBuzz(テスト用) - yukicoderへの提出をリライトしただけ

x;main(i){for(;~scanf("%d",&x);)--i&&printf(x%8?x%10?"%d":0:"iki",x/3)+puts(x%10?"":"sugi");}

93B

yukicoder No.667 Mice's Luck(ネズミ達の運)

問題はこちら
No.667 Mice's Luck(ネズミ達の運) - yukicoder

本質的には累積和の概念だと思うので★1.5よりは高級だと思うんですがどうなんでしょ

「セーフな箱があといくつ残っているか」を覚えておけば良い

main(){
	char s[1<<17];
	int n,o;
	n=strlen(gets(s));
	for(i=0;i<n;i++)if(s[i]=='o')o++;
	for(i=0;i<n;i++){
		printf("%f\n",o*100.0/(n-i));
		if(s[i]=='o')o--;
	}
}

s[i]%5で、oのとき1,xのとき0になることを使って縮める。
また、ループの終了条件をs[i]にすれば後半のループでnを破壊しても大丈夫
ループをまとめるのはうまくできなかった

n,o,i;
char s[1<<17];
main(){
	for(gets(s);s[n];o+=s[n++]%5);
	for(;s[i];o-=s[i++]%5)printf("%f\n",o*1e2/n--);
}

105B

yukicoder No.676 C0nvertPr0b1em

問題はこちら
No.676 C0nvertPr0b1em - yukicoder

指示通り実装するだけ

char s[1010];
main(){
	scanf("%s",s);
	for(int i=0;s[i];i++){
		if(s[i]=='l'||s[i]=='I')putchar('1');
		else if(s[i]=='o'||s[i]=='O')putchar('0');
		else putchar(s[i]);
	}
}

readとgetcharのどちらを使うか問題だが、今回は~getchar()の方が扱いやすい値になった。
'I'と'l'は73と108なので反転すると-74と-109。c%35+4で判別できる
'o'と'O'は79と111なので反転すると-80と-112。C%16で判別できる

main(c){for(;c=~getchar();)putchar(c%35+4?c%16?~c:48:49);}

58B