Alex Rivera | Logout

Efficiently generate all composite numbers less than N (with their factorizations)

Asked 2012-04-11T15:52:57.020
14

I'd like to build an efficient Python iterator/generator that yields:

  • All composite numbers less than N
  • Along with their prime factorization

I'll call it "composites_with_factors()"

Assume we already have a list of primes less than N, or a primes generator that can do the same.

Note that I:

  • DO NOT need the numbers to be yielded in numerical order
  • DO NOT care if 1 is yielded at the beginning or not
  • DO NOT care if primes are yielded, too

I figure this can be done with a clever recursive generator...

So, for example, a call to composites_with_factors(16) may yield:

# yields values in form of "composite_value, (factor_tuple)"
2, (2)
4, (2, 2)
8, (2, 2, 2)
6, (2, 3)
12, (2, 2, 3)
10, (2, 5)
14, (2, 7)
3, (3)
9, (3, 3)
15, (3, 5)
5, (5)
7, (7)
11, (11)
13, (13)

As you can see from the order of my output, I conceive of this working by starting with the smallest prime on the available primes generator, and outputting all powers of that prime less than N, then try again through the powers of that prime but at each stage seeing if I can apply powers of additional primes (and still be less than N). When all combinations with THAT prime are done, drop it, and repeat with the next lowest prime number available on the primes generator.

My attempts to do this with "recursive generators" have gotten me very confused on when to pop out of the recursion with "yield ", or "raise StopIteration", or "return", or simply fall out of the recursed function.

Thanks for your wisdom!

ADDITIONAL NOTE:

I do have one way to do this now: I have written a function to factor numbers, so I can factor them down to primes, and yield the results. No problem. I keep this blazingly fast by relying on a cache of "what is the lowest prime factor of number N"... for N up to 10 million.

However, once I'm

Edit
Report

1 Answer

0

Recursively (pseudo-code):

def get_factorizations_of_all_numbers( start = starting_point
                                     , end = end_point
                                     , minp = mimimum_prime
                                     ):
    if start > end:
        return Empty_List
    if minp ^ 2 > end:
        return list_of_all_primes( start, end )
    else
        a = minp * get_factorizations_of_all_numbers( rounddown(start/minp)
                                                    , roundup(end/minp)
                                                    )
        b = get_factorizations_of_all_numbers( start
                                             , end
                                             , next_prime( minp )
                                             )
        return append( a , b )

get_factorizations_of_all_numbers( 1, n, 2 )
answered 2012-04-11T16:42:00.253

Your Answer