あるプログラミングテスト問題に出会い、とても参考になったので、その学びを納めておきたいと思います。自身の回答に関しては、繰り返し処理が2重で存在するなど、まだまだ稚拙な回答ですが、この問題自体はとても参考になりました。
問題
Xを2 以上の整数とし、X の約数のうち X 自身を除いたものの和を Y とします。
このとき
- X = Y となるような X を完全数
- |X-Y| = 1 となるような X をほぼ完全数 (|X-Y| は X-Y の絶対値を意味する)
と言うことにする。
たとえば、X = 28 のとき
28 の約数は 1, 2, 4, 7, 14, 28 なので、Y = 1+2+4+7+14 = 28 となります。
従って、28 は完全数です。
また、X = 16 のとき
Y = 1+2+4+8 = 15 となるので、|16 - 15| = 1
従って、16 はほぼ完全数です。
入力された整数が完全数かほぼ完全数かそのいずれでもないかを判定するプログラムを作成する
入力される値
入力は以下のフォーマットで与えらる
Q
X_1
.
.
X_Q1
1行目のQには、判定したい整数の個数
続く Q 行には整数 X_1, ..., X_Q が入力されます。
期待する出力
各 X_i に対して
- X_i が完全数であれば "完全数"
- X_i がほぼ完全数であれば "ほぼ完全数"
- どちらでもなければ "どちらでもない"と 1 行に出力してください。
条件
すべてのテストケースで以下の条件を満たします。
- 1 ≦ Q ≦ 50
- 2 ≦ X_i ≦ 1000 (i=1, 2, ..., Q)
自分の回答
input_lines = readlines.map(&:to_i)
count = input_lines[0]
given_numbers = input_lines[1..count]
given_numbers.each do |num|
divide_numbers = [*1..num-1] # 解説1
sum = 0
divide_numbers.each do |divide|
sum += divide if num % divide == 0
end
if sum == num
puts "完全数"
elsif (sum - num).abs == 1 # 解説2
puts "ほぼ完全数"
else
puts "どちらでもない"
end
end
入力される数字の例
3
4
28
777
出力される例
ほぼ完全数
完全数
どちらでもない
解説
ちっぽけな解説ですが、一応載せておきます。
解説1 divide_numbers = [*1..num-1]
これは数学の話ではありますが、この問題は約数が重要です。また今回はその中でも、その数字自体は約数に含めてはいけないので、上記の構文で、1から始まり自分の一つ下の数字までの配列が格納されます。この配列は、今回の条件で約数になりうる数字の配列です。
# 28の場合
[1, 2, 3, 4, 5, 6, .. , 26, 27]
解説2 (sum - num).abs == 1
abs
はrubyで絶対値を出力するメソッドです。
(-5).abs = 5
(5).abs = 5
解説は以上です。
余談
余談ですが、この問題を見て小川洋子さんの「博士の愛した数式」を思い出しました。
記憶が短時間しか続かない数学者の博士と主人公である家政婦のやりとりを基本とした人間ドラマです。
その中で、博士が主人公とコミュニーションを取る上で、「友愛数」という数学の面白さを基に家政婦とコミュニケーションを取るシーンがありました。博士らしい他者との距離の取り方で、とても印象的でした。
この完全数の考え方は「友愛数」の考え方に似ています。なので思い出しました。コーディングテストの練習中に、博士の愛した数式を思い出して、少し悲しくなる、という謎現象でした。
最後までお読み頂きありがとうございました!(笑