在一个项目欧拉问题中,需要对一个数字进行因式分解。我们已经有了这个数字的所有质因数。根据算术基本定理,我们可以用这个列表推导出这个数字的所有因子。
我们目前的计划是取基本质因数列表中的每个数字,并将其幂提高直到它不再是整数因子,以找到每个质因数的最大指数。然后,我们将各个质数指数对的所有可能组合相乘。例如,对于180:
给定:180的质因数:[2, 3, 5]
找到每个因子的最大指数:
180 / 2^1 = 90
180 / 2^2 = 45
180 / 2^3 = 22.5 - 不是整数,所以2是2的最大指数。
180 / 3^1 = 60
180 / 3^2 = 20
180 / 3^3 = 6.6 - 不是整数,所以2是3的最大指数。
180 / 5^1 = 36
180 / 5^2 = 7.2 - 不是整数,所以1是5的最大指数。
然后,我们对这些指数组合进行各种组合,直到最大指数,以获得因子:
2^0 * 3^0 * 5^0 = 1
2^1 * 3^0 * 5^0 = 2
2^2 * 3^0 * 5^0 = 4
2^0 * 3^1 * 5^0 = 3
2^1 * 3^1 * 5^0 = 6
2^2 * 3^1 * 5^0 = 12
2^0 * 3^2 * 5^0 = 9
2^1 * 3^2 * 5^0 = 18
2^2 * 3^2 * 5^0 = 36
2^0 * 3^0 * 5^1 = 5
2^1 * 3^0 * 5^1 = 10
2^2 * 3^0 * 5^1 = 20
2^0 * 3^1 * 5^1 = 15
2^1 * 3^1 * 5^1 = 30
2^2 * 3^1 * 5^1 = 60
2^0 * 3^2 * 5^1 = 45
2^1 * 3^2 * 5^1 = 90
2^2 * 3^2 * 5^1 = 180
因此,因子的列表 = [1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 18, 20, 30, 36, 45, 60, 90, 180]
这是我们目前为止的代码。有两个问题:第一,我们认为它一点也不Pythonic。我们想修复它。第二,我们真的没有Pythonic的方法来做组合的第二步。为了避免尴尬,我们没有给你展示那套可笑的循环。
n 是我们要分解的数字。listOfAllPrimes是预先计算的列表,其中包含多达 1000 万的质数。
def getListOfFactors(n, listOfAllPrimes):
maxFactor = int(math.sqrt(n)) + 1
eligiblePrimes = filter(lambda x: x <= maxFactor, listOfAllPrimes)
listOfBasePrimes = filter(lambda x: n % x ==0, eligiblePrimes)
listOfExponents = [] #(do I have to do this?)
for x in listOfBasePrimes:
y = 1
while (x**(y+1)) % n == 0:
y += 1
listOfExponents.append(y)
2、解决方案
方案一
建议使用 itertools.combinations 来获取所有可能的因子组合。之后,只需将每个组合中的项相乘即可得到因子。
import itertools
def get_factors(n):
prime_factors = get_prime_factors(n) # get the prime factors of n
factor_combinations = itertools.product(*prime_factors) # get all possible combinations of factors
factors = [reduce(lambda x, y: x * y, combination) for combination in factor_combinations] # multiply the factors in each combination
return factors
def get_prime_factors(n):
prime_factors = []
divisor = 2
while n > 1:
if n % divisor == 0:
prime_factors.append(divisor)
n //= divisor
else:
divisor += 1
return prime_factors
方案二
建议使用filter()和map()函数来生成质因数列表,然后使用product()函数来生成所有可能的因子组合。
from itertools import product
def get_factors(n):
prime_factors = list(filter(lambda x: n % x == 0, range(2, int(n**0.5) + 1)))
if prime_factors[-1]**2 == n:
prime_factors.pop()
factors = [reduce(lambda x, y: x * y, combination) for combination in product(prime_factors, repeat=2)]
return set(factors) # remove duplicates