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