Все в одном решении;т.е. нет необходимости в существующем списке простых факторов.
#!/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
).
Это создает полный список факторов, т.е. включает 1
и сам аргумент number
.Если вы хотите опустить их, вы можете использовать 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])