Reputation: 135
EDIT: Though I did say in the original post that I'd like to use list comprehension, I would gladly accept any solution. I simply assumed list comprehension would be the simplest way to do it.
I am working on a problem involving prime factorization, and have run into an issue regarding list comprehension.
I have a list of prime factors of a number, and of course the list could be any number of numbers. It could be [2,3,5] or just [2], or [2,3,11,17], etc.
What I would like to be able to do would be to find all products of powers of these numbers such that the product is less than or equal to 100,000. So for example if my prime factorization is [2,3,5], I would like to have all numbers of the form (2^a)(3^b)(5^c) for natural numbers a,b,c, satisfying (2^a)(3^b)(5^c) <= 100,000.
Is there a way to do this with list comprehension given that the number of prime factors is an arbitrary length?
Upvotes: 0
Views: 343
Reputation: 1047
Check this out.
import math
Nmax = 100
primeLst = [2, 3, 5]
result = []
enumMax = [int(math.floor(math.log(Nmax) / math.log(i))) for i in primeLst]
def prod(i, curRes):
if curRes > Nmax:
return
if i==len(primeLst):
result.append(curRes)
else:
for j in range(enumMax[i]+1):
prod(i+1, curRes * (primeLst[i]**j))
prod(0, 1)
# result: [1, 5, 25, 3, 15, 75, 9, 45, 27, 81, 2, 10, 50, 6, 30, 18, 90, 54, 4, 20, 100, 12, 60, 36, 8, 40, 24, 72, 16, 80, 48, 32, 96, 64]
Upvotes: 0
Reputation: 74655
This modification of @niemmi's answer uses heapq.merge
to merge each of the sequences from each of the recursive calls to produce the products in increasing order:
from heapq import merge
def prods(factors, limit, index = 0, total = 1):
# Base case, yield current number
if index >= len(factors):
yield total
return
iters = []
while total < limit:
iters.append(prods(factors, limit, index + 1, total))
total *= factors[index]
for res in merge(*iters):
yield res
print list(prods([2, 3, 5], 100))
There is the output:
>>> print list(prods([2, 3, 5], 100))
[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80, 81, 90, 96]
Upvotes: 0
Reputation: 17263
You could use recursive function that picks one of the factors and multiplies the current total until the total is above the limit. For each iteration you could then recursively call the same function while moving to next factor. Once you have exhausted all the factors just yield the current total:
def prods(factors, limit, index = 0, total = 1):
# Base case, yield current number
if index >= len(factors):
yield total
return
while total <= limit:
# Python 3 yield from could be used
for res in prods(factors, limit, index + 1, total):
yield res
total *= factors[index]
print list(prods([2, 3, 5], 100))
Output:
[1, 5, 25, 3, 15, 75, 9, 45, 27, 81, 2, 10, 50, 6, 30, 18, 90, 54, 4, 20, 100, 12, 60, 36, 8, 40, 24, 72, 16, 80, 48, 32, 96, 64]
Upvotes: 1