codeiq 「カット・アンド・スクエア問題」

問題はこちら
http://riverplus.net/codeiq/CutAndSquare.pdf

かいつまんで言うと、
[偶数 n に対して、先頭にゼロを持たない n 桁の整数で上 n/2 桁と下 n/2 桁とに分け、それぞれを 2 乗して和をとると、元の数に戻るような数で、n=6, n=10の場合を求めよ。]という感じ。
色々と回答があるようで、参考になったな~。

で、Rubyで書いた提出コードが下記。
sqrtの結果を整数に丸めるあたりが怪しい気がするが、まぁ、当たりでないときは外れるはずだからOKのはず。

ideone.comにも置きました。便利だね。
http://ideone.com/eMPnrv

【方針】
求めるN桁の数をnとし、 n = a * 10**(N/2) + b とする。
n = a**2 + b**2 (b>0, a>10**(N/2 – 1)) の条件を満たす整数a,bを見つける方針でとく。
1. n = a**2 + b**2 の1桁目に注目すると、aの1桁目の数字は0,2,8のみとなる。
   (Excelで100通りをすべてチェックしましたが、a,bの下1桁の値の組み合わせは8通りしかありません。)
2. 条件の式からbについて解くことができるので、各aについて、bが条件を満たす整数かどうかをチェックする。
   (bについてはループしなくて済む。)

N=10
Base2=10**(N/2)

result = []
((Base2/10)...Base2).select{|a| # aの下1桁を0, 2, 8に絞る。
  tmp = a%10
  tmp == 0 or tmp == 2 or tmp ==8
}.each{|a| # aについてのループ。
  # bは、aについて解いておく。(b>0なので、一意にさだまる。)
  b=(1 + Math.sqrt(1+4*Base2*a -4*a*a)).round/2
  n = a*Base2 + b
  result << n if a*a + b*b == n # 条件を満たすかどうかをチェック。
}
p result
p result.reduce(&:+)

コメントを残す