def getPartitionNumber( n ): if real_int( n ) < 0: raise ValueError( 'non-negative argument expected' ) elif n in ( 0, 1 ): return 1 total = 0 sign = 1 i = 1 k = getNthGeneralizedPolygonalNumber( i, 5 ) while n - k >= 0: total += sign * getPartitionNumber( fsub( n, k ) ) i += 1 if i % 2: sign *= -1 k = getNthGeneralizedPolygonalNumber( i, 5 ) return total
def getPartitionNumber( n ): ''' This version is, um, less recursive than the original, which I've kept. The strategy is to create a list of the smaller partition numbers we need to calculate and then start calling them recursively, starting with the smallest. This will minimize the number of recursions necessary, and in combination with caching values, will calculate practically any integer partition without the risk of a stack overflow. I can't help but think this is still grossly inefficient compared to what's possible. It seems that using this algorithm, calculating any integer partition ends up necessitating calculating the integer partitions of every integer smaller than the original argument. ''' debugPrint( 'partition', int( n ) ) if real_int( n ) < 0: raise ValueError( 'non-negative argument expected' ) elif n in ( 0, 1 ): return 1 sign = 1 i = 1 k = 1 estimate = log10( fdiv( power( e, fmul( pi, sqrt( fdiv( fmul( 2, n ), 3 ) ) ) ), fprod( [ 4, n, sqrt( 3 ) ] ) ) ) if mp.dps < estimate + 5: mp.dps = estimate + 5 partitionList = [ ] signList = [ ] while n - k >= 0: partitionList.append( ( fsub( n, k ), sign ) ) i += 1 if i % 2: sign *= -1 k = getNthGeneralizedPolygonalNumber( i, 5 ) partitionList = partitionList[ : : -1 ] total = 0 for partition, sign in partitionList: total = fadd( total, fmul( sign, getPartitionNumber( partition ) ) ) return total