背景
高校までは数学が一番得意で、大好きでした。
なのに文系の大学に入った私は数学とは縁遠い生活を送り
そして社会人になり早十年…
微積分も三角関数も忘れてしまった左脳だけ発達してる系エンジニアですが、
最近はYouTubeのおかげで数学に触れる機会が少しずつ増えました。
入試問題を解いたり、知られざる大学数学の世界を気軽に触れられるいい時代です。
本日は以下の動画で紹介されていた面白い性質を持った整数「カプレカ数」について
Rubyを使って検証していきます。
※元ネタ
予備校のノリで学ぶ「大学の数学・物理」
最大から最小を引いて元通り!【カプレカ数】
カプレカ数とは
カプレカ数(カプレカすう、Kaprekar Number)とは、次のいずれかで定義される整数である。
1. 2乗して前の部分と後ろの部分に分けて和を取ったとき、元の値に等しくなるもの。
2. 桁を並べ替えて最大にしたものから最小にしたものの差を取ったとき、元の値に等しくなるもの。引用元:Wikipedia
今回調べるのは定義2の方です。
例えば495を例に考えてみます。
495を並べ替えて作れる最大の数は954、最小の数は459です。
954 - 459 = 495ですから、元の数字495と等しくなりました!
面白いですね!
このような数字をカプレカ数といい、
我々が普段目にする桁数の数字では数えられるほどしかありません。
では本題のRubyプログラムに入っていきましょう。
任意の整数がカプレカ数かどうかを判定する
num = 627
# 配列に格納
arr = num.to_s.split('').map!(&:to_i)
p arr # => [6, 2, 7]
# 並べ替えて最大と最小を作る
max = arr.sort{ |a, b| a <=> b }.join('').to_i
min = arr.sort{ |a, b| b <=> a }.join('').to_i
p max # => 762
p min # => 267
# 最大 - 最小が元の数字と同じかどうかの判定
diff = max - min
p diff == num # => false
これでnum
を書き換えることで任意の整数1つのみの判定を行えるようになりました。
特定の範囲の中にカプレカ数かどうかを判定する
ここから繰り返し処理を用いて特定の範囲の中にカプレカ数があるかどうかを探してみましょう。
result = []
num = 1
final = 1_000_000
while num < final do
arr = num.to_s.split('').map!(&:to_i)
min = arr.sort{ |a, b| a <=> b }.join('').to_i
max = arr.sort{ |a, b| b <=> a }.join('').to_i
diff = max - min
if diff == num
result.push("【#{num}】 #{max} - #{min} = #{diff}")
end
num += 1
end
if result.empty?
result.push("該当なし")
end
puts result
(可読性重視で敢えて三項演算子は使っていません)
【495】 954 - 459 = 495
【6174】 7641 - 1467 = 6174
【549945】 995544 - 445599 = 549945
【631764】 766431 - 134667 = 631764
上記例では6桁の整数までで試したところ、4つのカプレカ数が見つかりました。
5桁には存在しないというのもまた不思議!
余談
PCのスペックにもよりますが、100万回も繰り返し処理したら結構時間かかります。
冒頭で紹介した495という数字を見て
495 = 99 × 5がすぐに思いついたあなたは数学的センスをお持ちですね。
そう、カプレカ数はどれも9の倍数です。
なので100万回やらなくても、9の倍数のみ検証すればもっと処理は軽減できます。
もっといい書き方がありましたらコメントで教えてください!
(2020/06/29 追記)
早速コメントをいただき改良版をコメント欄に投稿しました!