Reputation: 2921
I'm trying to memoize divisor sums of numbers.
divisorSums = {}
def sumDivisors(num):
global divisorSums
total = 0
if num == 1:
return 0
for i in xrange(num/2, 0, -1):
if i in divisorSums:
return divisorSums[i]
else:
if not num % i:
total += i
divisorSums[num] = total
return total
However, this returns 1 for all numbers, when I loop through the numbers. It is correct when it used singularly, so the problem is my lookup system. I'm pretty sure I don't understand how to look for a value in a dictionary. Can someone help me out?
Upvotes: 1
Views: 88
Reputation: 98078
Here:
if i in divisorSums:
return divisorSums[i]
returning divisorSums[i] is not the right thing to do as there may be some prime factors less than i
. Here is one way using a helper function to remember/calculate factors of numbers:
from itertools import groupby
divisorC={}
def divisors(num):
if num in divisorC:
return divisorC[num]
l = {1:1}
for i in xrange(num/2, 1, -1):
if num % i == 0:
l[i] = 1
l.update(divisors(i))
l.update(divisors(num/i))
break
divisorC[num] = l
return divisorC[num]
def sumDivisors(num):
if num == 1: return 0
l = {}
for i in xrange(num/2, 0, -1):
if num % i == 0:
l.update(divisors(i))
l.update(divisors(num/i))
l[i] = 1
l[num/i] = 1
break
return sum(v for v in l)
Upvotes: 2
Reputation: 304355
The usual shortcut trick for memoize is to use a mutuable default argument
def sumDivisors(num, divisorSums={}):
if num in divisorSums: # Check if you have
return divisorSums[num] # memoized the answer here
total = 0
if num == 1:
return 0
for i in xrange(num/2, 0, -1):
if not num % i:
total += i
divisorSums[num] = total
return total
Other than that your code seems to work ok. How were you runnning it to get just 1
?
Upvotes: 3