Skip to main content
2 of 2
added 817 characters in body

My suggestion:

def list_squared(m, n)
   (m..n).each_with_object([]) do |to_check, result|
     to_check_sqrt = Math.sqrt(to_check).to_i

     area = (2..to_check_sqrt).inject(1 + to_check ** 2) do |sum, divisor|
       if to_check % divisor == 0
         sum += divisor ** 2
         sum += (to_check / divisor) ** 2 if divisor != (to_check / divisor)
       end

       sum
     end

     result << [to_check, area] if Math.sqrt(area) == Math.sqrt(area).to_i
   end
end

Edit:

Or this way seems to work too and a little bit faster:

def list_squared2(m, n)
  divisors = {}

  # build a divisor lookup table
  (1..Math.sqrt(n).to_i).each do |divisor|
    (((m / divisor).to_i * divisor)..n).step(divisor) do |divisor_of|
       divisors[divisor_of] ||= []
       divisors[divisor_of] << divisor
       divisors[divisor_of] << divisor_of / divisor if divisor != (divisor_of / divisor)
     end
  end

  # lookup needed values
  (m..n).each_with_object([]) do |to_check, result|
    divisors[to_check] += [to_check]
    area = divisors[to_check].uniq.inject(0) { |sum, divisor| sum + divisor ** 2 }

    result << [to_check, area] if Math.sqrt(area) == Math.sqrt(area).to_i
  end
end