年子平方数の最初の21個を列挙する

2004年8月号 Cマガ電脳クラブ 第161回 年子平方数
┌─────────────────────────────┐
│ 偶数桁の平方数(ある数を2乗してできる数)で、それぞれ同じ│
│桁数になるように左右半分に割ったとき、その2つの数が連続し│
│た2数になっているものを、「年子(としご)平方数」と呼ぶこと│
│にする。たとえば、                    │
│ 8281(=91^2)                      │
│では81と82が連続した2数となっている。ただし、右半分と│
│左半分、どちらが大きくてもかまわない。ここでは正の整数のみ│
│を扱い、すなおに10進法で考える。            │
│ この「年子平方数」をほかにも見つけてほしいのだが、たくさ│
│んあるので、小さいほうから順に(上記の例を含めて)21番目ま│
│でをお答えいただきたい。                 │
└─────────────────────────────┘
ライブドアブログ(livedoor Blog)| 読みたいブログが見つかる

ujihisa が Haskell で実装したようなので、僕は釣られて Ruby で実装しました (リンク先ネタバレ注意)。

まずは実行結果。たまたま手元にあった Ruby 1.9 の r20750 を使いました。

$ time ~/ruby-r20750/bin/ruby toshigo.rb
1: 8281
2: 183184
3: 328329
4: 528529
5: 715716
6: 60996100
7: 82428241
8: 98029801
9: 1322413225
10: 4049540496
11: 106755106756
12: 453288453289
13: 538277538276
14: 998002998001
15: 20661152066116
16: 29752082975209
17: 2214532822145329
18: 2802768328027684
19: 7783702677837025
20: 9998000299980001
21: 110213248110213249
110213250

real	7m28.407s
user	6m26.524s
sys	0m3.877s

以下コード。

class Integer
  def square?
    r = Math.sqrt(self)
    i = r.to_i
    return self == i*i && r == i
  end
end

m = 0
n = 2
b = 10
inc = b + 1
x = n*b + n - 1
y = (n - 1)*b + n
until m == 21
  if x.square?
    m += 1
    puts "#{m}: #{x}"
  end

  if y.square?
    m += 1
    puts "#{m}: #{y}"
  end

  n += 1
  if n == b
    b *= 10
    inc = b + 1
    x = n*b + n - 1
    y = (n - 1)*b + n
  else
    x += inc
    y += inc
  end
end
p n