我有一个数字的主要因素的python列表。我(python)如何找到所有因素?

StackOverflow https://stackoverflow.com/questions/3643725

  •  30-09-2019
  •  | 
  •  

我正在处理一个项目Euler问题,该问题需要分解整数。我可以提出所有列表的列表,这些列表是给定数字的因素。算术的基本定理意味着我可以使用此列表来得出 每一个 数量的因素。

我目前的计划是在基本素数清单中获取每个数字,并提高其功率,直到它不再是为每个素数找到最大指数的整数因素为止。然后,我将乘以原始exponent对的所有可能组合。

因此,例如,180:

Given: prime factors of 180: [2, 3, 5]
Find maximum exponent of each  factor: 
    180 / 2^1 = 90
    180 / 2^2 = 45
    180 / 2^3 = 22.5 - not an integer, so 2 is the maximum exponent of 2.

    180 / 3^1 = 60
    180 / 3^2 = 20
    180 / 3^3 = 6.6 - not an integer, so 2 is the maximum exponent of 3.

    180 / 5^1 = 36
    180 / 5^2 = 7.2 - not an integer, so 1 is the maximum exponent of 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、30、36、45、60、90、180

这是我到目前为止的代码。两个问题:首先,我认为这根本不是很柔感。我想解决这个问题。第二,我 真的 没有Pythonic进行组合的第二步。出于耻辱,我让您摆脱了荒谬的循环。

n是我们要考虑的数字。 ListOllprimes是高达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)
有帮助吗?

解决方案

而不是指数列表,请简单地考虑 重复 每个素数的次数 一个因素。之后,处理结果 primefactors 列表 - 重复, itertools.combinations 做您需要的事情 - 您只需要长度2的组合 len(primefactors) - 1 包括项目(仅一个的组合是主要因素,所有这些因素将是原始数字 - 如果您也需要这些,只需使用 range(1, len(primefactors) + 1) 而不是 range(2, len(primefactors)) 我的主要建议将使用)。

结果中将有重复(例如, 6 将出现两次作为一个因素 12, ,因为后者的 primefactors 将会 [2, 2, 3])当然,它们当然可以以通常的方式除草(即 sorted(set(results)) 例如)。

计算 primefactors 给出 listOfAllPrimes, ,例如:

def getprimefactors(n):
    primefactors = []
    primeind = 0
    p = listOfAllPrimes[primeind]
    while p <= n:
        if n % p == 0:
            primefactors.append(p)
            n //= p
        else:
            primeind += 1
            p = listOfAllPrimes[primeind]
    return primefactors

其他提示

为什么您要从一组主要因素开始解决方案?当您分解一个数字时,您可以轻松地获得其所有主要因素(重复),并从中获得每个因素的指数。考虑到这一点,您可以写下:

import itertools
prime_factors = get_prime_factors(180) 
# 2, 2, 3, 3, 5 
factorization = [(f, len(list(fs))) for (f, fs) in itertools.groupby(prime_factors)]
# [(2, 2), (3, 2), (5, 1)]
values = [[(factor**e) for e in range(exp+1)] for (factor, exp) in factorization]
# [[1, 2, 4], [1, 3, 9], [1, 5]]
print sorted(product(xs) for xs in itertools.product(*values))
# [1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 18, 20, 30, 36, 45, 60, 90, 180]

get_prime_factorsproduct 在这里没有实现,但是您会得到这个想法(两者都很容易编写)

恕我直言,作为数学问题,可以使用功能而不是命令样式可以很好地解决欧拉问题(尽管我承认某些解决方案可能不会像所需的那样出现Pythonic)。

您可以使用 itertools.combinations() 一旦您获得了重复列表,例如 [2, 2, 3, 3, 5] 为了 180. 。然后,只需将组件乘以每种组合,就会为您带来一个因素。

具有一些凉爽的Python功能:

def factors( num ):
    for p in primes:
        if num==1: break # stop when num is 1
        while True: # these factors may be repeated 
            new, rest = divmod(num, p) # does div and mod at once
            if rest==0: # its divisible
                yield p # current prime is factor
                num = new # continue with the div'd number
            else:
                break # no factor so break from the while


print list(factors(2*2*3*3*5*7*11*11*13)) # [2, 2, 3, 3, 5, 7, 11, 11, 13] ofc

这是针对原始问题的简单有效的解决方案:

def getDivisors(n):
    divisors = []
    d = 1
    while d*d < n:
        if n % d == 0:
            divisors.append(d)
            divisors.append(n / d);
        d += 1
    if d*d == n:
        divisors.append(d)
    return divisors

输出列表未分类。如果需要,您可以使其更加“ Pythonic”。

全部解决方案;即不需要现有的主要因素列表。

#!/usr/bin/python3 -O

from primegen import erat3 as generate_primes # see Note[1]
import operator as op, functools as ft, itertools as it

def all_factors(number):
    prime_powers= []

    for prime in generate_primes(): # for prime in listOfAllPrimes
        if prime > number: break

        this_prime_powers= [1]
        new_number, modulo= divmod(number, prime)

        while not modulo:
            number= new_number
            this_prime_powers.append(this_prime_powers[-1] * prime)
            new_number, modulo= divmod(number, prime)

        if len(this_prime_powers) > 1:
            prime_powers.append(this_prime_powers)

    # at this point:
    # if number was 360, prime_powers is [[1, 2, 4, 8], [1, 3, 9], [1, 5]]
    # if number was 210, prime_powers is [[1, 2], [1, 3], [1, 5], [1, 7]]

    return sorted(
        ft.reduce(op.mul, combination, 1)
        for combination in it.product(*prime_powers))

if __name__ == "__main__":
    def num_result(number):
        return number, all_factors(number)
    print(num_result(360))
    print(num_result(210))
    print(num_result(7))

注意[1: :作为素数生成器,您可以从中选择一个 如何在Python中实施有效的无限发电机? 或使用自己的 listOfAllPrimes).

这会产生一个完整的因素列表,即 1number 论点本身。如果要省略这些,可以使用 all_factors(number)[1:-1].

$ allfactors.py 
(360, [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 18, 20, 24, 30, 36, 40, 45, 60, 72, 90, 120, 180, 360])
(210, [1, 2, 3, 5, 6, 7, 10, 14, 15, 21, 30, 35, 42, 70, 105, 210])
(7, [1, 7])
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top