I was participating in a python challenge in codewars website. I encountered the following 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.
The output should be:
list_squared(1, 250) --> [[1, 1], [42, 2500], [246, 84100]]
list_squared(42, 250) --> [[42, 2500], [246, 84100]]
list_squared(250, 500) --> [[287, 84100]]
I have written following code with two additional functions: one corresponding to determine all factors of a number and other checking if a number is perfect square or not.
Function to determine all factors:
def fact(m):
return [i for i in range(1,m+1) if m%i == 0]
Function to check if a number is perfect square and return 0 if it is not otherwise return square root
def square_root(x):
ans = 0
while ans < x // 2 + 1:
ans = ans + 1
if ans*ans == x:
return ans
break;
return 0
Function where the desired result is calculated
def list_squared(m, n):
# your code
fac=[]
for i in range(m,n+1):
sq_sum = sum(list(map(lambda x: x**2,fact(i))))
if square_root(sq_sum) != 0:
fac.append([i,sq_sum])
return fac
This code gives me the correct result, however it is too long. I was able to pass all the test results but it took me around 6000 ms. When I attempted to submit the code, the web submission returns that the algorithm is inefficient and it took more than 1200 ms which is the maximum.
I would highly appreciate if anyone can point to a better algorithm for this.