I am doing a problem my buddy gave to me and I have my solution which works but needs to be optimised. I have tried to optimise it as much as I can with my knowledge but it seems there is still room for improvement. I am trying to improve my ruby. Here is the challenge:
Divisors of 42 are : 1, 2, 3, 6, 7, 14, 21, 42. These divisors squared are: 1, 4, 9, 36, 49, 196, 441, 1764. The sum of the squared divisors is 2500 which is 50 * 50, a square!
Given two integers m, n (1 <= m <= n) we want to find all integers between m and n whose sum of squared divisors is itself a square. 42 is such a number.
The result will be an array of arrays, each subarray having two elements, first the number whose squared divisors is a square and then the sum of the squared divisors.
def list_squared(m, n)
array = []
(m..n).to_a.each do |i|
q = (1..i/2).to_a.push(i).map {|x| x**2 if i % x == 0 }.compact.reduce(:+)
array << [i, q] if Math.sqrt(q) % 1 == 0
end
array
end
This works but apparently is inefficient. Could someone point me in the right direction. I am assuming its the "map" but I initially had:
def list_squared(m, n)
array = []
(m..n).to_a.each do |i|
q = (1..i/2).to_a.select {|x| i % x == 0 }.push(i).map { |x| x**2 }.reduce(:+)
array << [i, q] if Math.sqrt(q) % 1 == 0
end
array
end
(m..n).to_a.each
. What happens if it evaluates to(0..1_000_000_000).to_a...
? You've unnecessarily used a huge amount of memory where you could have iterated directly usingeach
. \$\endgroup\$