最近のあなごる問題

Spiral Fixed

なかなか難しい問題だった。どうアプローチするのが最善なのかわからない。私は以下の方法で解いた。他の人の解は結局調べていない。

05 15 25 35 45 55
04 14 24 34 44 54
03 13 23 33 43 53
02 12 22 32 42 52
01 11 21 31 41 51
00 10 20 30 40 50

この 6 x 6 を Spiral に展開し、上位の桁、下位の桁を上下に並べ、適当なところで区切ると、

上位: 01234555555 432100000 1234444 32111 233 2
下位: 55555543210 000001234 4444321 11123 332 2

となり、わりときれいな対象的な構造が出てくる。徐々に振り幅が小さくなる減衰振動みないなイメージだ。これを C にすると、

x,l,i;main(n,y,u,j){
    scanf("%d",&n);
    for(y=u=n-1;n--;x=i++%2?++l:--u)
        for(j=n-~n;j--;i%2?x<=l?y+=y<u:x--:x>=u?y-=y>l:x++)
            printf("%d%d ",x,y);
}

139B 。upper bound と lower bound を徐々に縮めていく方法だが、変数が 7 つにもなる。最短な感じがしないな。
なお、この問題は途中で FIX が出て、解の出力量が大幅に増された。このため、Groovy の解は、タイムアウトするようになってしまい、幻の解答になってしまった。

Circle radius

この問題の解法は、ピタゴラスの定理を用いて、

a*a+(r-b)*(r-b)=r*r
r=(a*a/b+b)/2

となる。この部分が、整数に丸めると C / JavaScript ともに、

a*a/b-~b>>1

と書ける。もう少しわかりやすく書くと、

(a*a/b+b+1)/2       // ただし、除算は整数除算(切り捨て)

整数に丸めるという前提のもと、これって正しいのかなぁ?つまり、以下が常に成り立つのか?

[(a*a/b+b)/2+0.5] == [([a*a/b]+b+1)/2]
     / : 有理数除算
     []: 切り捨て整数化

左辺は有理数計算で最後に四捨五入。右辺は、整数計算。
左辺は、

[(a*a/b+b)/2+0.5]
      = [([a*a/b]+a*a%b/b+b)/2+0.5]
      = [([a*a/b]+b+1)/2+a*a%b/b/2]
                                                 0<=a*a%b<b なので、
                                                 0<=a*a%b/b/2<0.5
      = [([a*a/b]+b+1)/2+X]                      0<=X<0.5
      = [[([a*a/b]+b+1)/2]+([a*a/b]+b+1)%2/2+X]
                                                 ([a*a/b]+b+1)%2/2=0 or 0.5
      = [[([a*a/b]+b+1)/2]+Y]                    0<=Y<1
      = [[([a*a/b]+b+1)/2]]
      = [([a*a/b]+b+1)/2]

と変形でき右辺に一致した。正しいということだ。

camelCase

camelCase と toggleCASE の私の C の解:

main(p,c){read(0,&c,1)&&main(c^putchar(c^c/2&p&32)/2);} //camelCase
main(p,c){read(0,&c,1)&&main(putchar(c^c/2&p&32)^c/2);} //toggleCASE

この双対性が美しかったが、最短ではなかった。