Various details
You initialise sum = 0
before the loop and then at the end of each iteration making it slightly harder to understand how it is being used and how one iteration affects another. It would be clearer (and shorter) to initialise it at the beginning of each iteration.
Also, sum
is a Python built-in: by defining a variable with the same name, you are somehow hiding the built-in which we may want to use later on. A more precise name such as div_sum
could be used.
You may want to divide your logic into smaller functions which are easier to maintain but also to document and to test. For instance:
def get_divisor_squared_sum(n):
div_sum = 0
for y in range(1, n+1):
if n % y == 0:
div_sum += y**2
return div_sum
assert get_divisor_squared_sum(1) == 1*1
assert get_divisor_squared_sum(2) == 1*1 + 2*2
assert get_divisor_squared_sum(6) == 1*1 + 2*2 + 3*3 + 6*6
assert get_divisor_squared_sum(9) == 1*1 + 3*3 + 9*9
def list_squared(m, n):
total=[]
for x in range(m, n+1):
div_sum = get_divisor_squared_sum(x)
if math.sqrt(div_sum).is_integer():
total.append([x, div_sum])
return total
Then, it gets easier to improve one function indedepently of how it is being used. For instance, we could improve get_divisor_squared_sum
in various ways.
First, we could use the sum
builtin.
def get_divisor_squared_sum(n):
return sum(d**2 for d in range(1, n+1) if n % d == 0)
Also, and probably more important, we could stop looking for divisors much earlier as mentionned in other answers (I will not repeat what has been said but this one of the best optimisations you could put in place).
I'm not sure about the exact expectations of the CodeWars challenge but I think the return type of your function could be slightly more Pythonic: instead of returning list of lists, I'd rather return a list of tuples. I highly recommend the excellent "Lists vs. Tuples" post from Ned Batchelder
's excellent blog to see the technical and cultural differences between the 2.
def list_squared(m, n):
total=[]
for x in range(m, n+1):
div_sum = get_divisor_squared_sum(x)
if math.sqrt(div_sum).is_integer():
total.append((x, div_sum))
return total