【Ruby】特定の条件下で約数の和を算出する方法と導くまでの手順

　ある整数の約数の総和を算出するプログラムを作ってみました。また特定の条件下での約数の和も出せるようにします。例えば12600の約数の中から5000以下の約数の和も出すというようなことです。

　結果的に以下のようなコードで解決しました。

```ruby
def divisor(num, range)
  divisible = []
  divisible_range = []
  count = 1
  while count <= num
    divisible_or = num % count
    if divisible_or == 0
      divisible << count
      if count <= range
        divisible_range << count
      end
    end
    count += 1
  end
  puts "約数の総和は#{divisible.sum}です"
  puts "#{range}以下の約数の和は#{divisible_range.sum}です"
end

puts "約数の総和を出したい整数を入力してください"
num = gets.to_i
puts "和を出したい約数の範囲を指定してください"
range = gets.to_i
divisor(num, range)
```
　実行結果はこのようになります。

```erb
約数の総和を出したい整数を入力してください
12600
和を出したい約数の範囲を指定してください
5000
約数の総和は48360です
5000以下の約数の和は29460です
```

　またその後下記の記事を参考にさせていただき、以下のようにコードを修正いたしました。
[【Ruby】ある整数の約数（要素の数、和）を求める](https://qiita.com/hirakei1203/items/def4242d18862f776efc)

```ruby
def divisor(num,range)
  num_div = (1..num).select{ |count| num % count == 0 }
  range_div = (1..range).select{ |count| num % count == 0 }
  puts "約数の数は#{num_div.length}です"
  puts "約数の総和は#{num_div.sum}です"
  puts "#{range}以下の約数の和は#{range_div.sum}です"
end


puts "約数の総和を出したい整数を入力してください"
num = gets.to_i
puts "和を出したい約数の範囲を指定してください"
range = gets.to_i
divisor(num,range)
```

　もっと効率的な修正の仕方もあるかと思いますので、ご意見いただけたらありがたいです。また、これから同じプログラミング初心者でも分かるような手順で、答えを導くまでのプロセスを説明したいと思います。

1. とりあえず45の約数を出してみる
1. 変数を使って約数を出力させる
2. 約数の合計を出す
3. 1000以下の約数の和を出してみる
4. 和を出したい約数の範囲を指定できるようにする
4. 可読性をもう少し上げる

##1. とりあえず45の約数を出してみる
　まずは分かりやすく具体的な数字で約数を出力させてみます。45の約数を出したい場合は、1から45まで、割り切れる値かどうかを検証し、割り切れた値だけ出力すれば良さそうです。ということで「%」と繰り返し処理を使って約数を出力させてみました。

```ruby
45.times do |count|
  count += 1
  if 45 % count == 0
    puts count
  end
end
```
　このコードの実行結果はこうなります。

```erb
1
3
5
9
15
45
```

##2. 変数を使って約数を出力させる
　では今度は45に該当する値を変数にしてコードを書き換えました。これで入力した値の約数が出力されるようになります。

```ruby
def divisor(num)
  count = 1
  while count <= num
    divisible = num % count == 0
    if divisible
      puts count
    end
    count += 1
  end
end

puts "整数を入力してください"
num = gets.to_i
divisor(num)
```

##3. 約数の合計を出す
　求めたい値は約数の和であるため、まずは全ての約数の総和を出せるようにしてみました。割り切れた時だけ配列に値を格納していき、sumを使って配列の合計を出すやり方です。

```ruby
def divisor(num)
  divisible = []
  count = 1
  while count <= num
    divisible_or = num % count
    if divisible_or == 0
       divisible << count
    end
    count += 1
  end
  puts divisible.sum
end

puts "整数を入力してください"
num = gets.to_i
divisor(num)
```
　これで「45」を入力した場合、「78」という約数の総和が出力されます。

##4. 1000以下の約数の和を出せるようにする
　全ての約数の総和とは別に特定の条件下での約数の和も出したかったため、とりあえず1000以下の約数の和を出してみることにしました。配列とif文を追加しただけです。

```ruby
def divisor(num)
  divisible = []
  divisible_1000 = []
  count = 1
  while count <= num
    divisible_or = num % count
    if divisible_or == 0
       divisible << count
       if count <= 1000
        divisible_1000 << count
       end
    end
    count += 1
  end
  puts divisible.sum
  puts divisible_1000.sum
end

puts "整数を入力してください"
num = gets.to_i
divisor(num)
```
　これで「12600」を入力した場合、「48360」という約数の総和と「10405」という1000以下の約数の和も出せるようになりました。

##5. 和を出したい約数の範囲を指定できるようにする
　あとは1000の部分を変数にして最初に紹介したコードが完成しました。

```ruby
def divisor(num, range)
  divisible = []
  divisible_range = []
  count = 1
  while count <= num
    divisible_or = num % count
    if divisible_or == 0
      divisible << count
      if count <= range
        divisible_range << count
      end
    end
    count += 1
  end
  puts "約数の総和は#{divisible.sum}です"
  puts "#{range}以下の約数の和は#{divisible_range.sum}です"
end

puts "約数の総和を出したい整数を入力してください"
num = gets.to_i
puts "和を出したい約数の範囲を指定してください"
range = gets.to_i
divisor(num, range)
```

##6. 可読性をもう少し上げる
　ただあまりにもごちゃごちゃしているため、初めに紹介した下記の記事を参照したところ、以下のようにコードを書き換えることができました。
[【Ruby】ある整数の約数（要素の数、和）を求める](https://qiita.com/hirakei1203/items/def4242d18862f776efc)
　また記事に落とし込むにあたって、もともと自分が解いたやり方もこちらの記事のコードに寄せています。

```ruby
def divisor(num,range)
  num_div = (1..num).select{ |count| num % count == 0 }
  range_div = (1..range).select{ |count| num % count == 0 }
  puts "約数の数は#{num_div.length}です"
  puts "約数の総和は#{num_div.sum}です"
  puts "#{range}以下の約数の和は#{range_div.sum}です"
end


puts "約数の総和を出したい整数を入力してください"
num = gets.to_i
puts "和を出したい約数の範囲を指定してください"
range = gets.to_i
divisor(num,range)
```

　まだまだ勉強不足ですので、コメントお願いいたします。