5 Best Ways to Find All Prime Factors of a Given Number in Sorted Order in Python

Rate this post

πŸ’‘ Problem Formulation: The task is to find all the prime factors of a given positive integer and return them in ascending order. For example, given the input number 60, the desired output should be a list of its prime factors, [2, 2, 3, 5], sorted in non-decreasing order.

Method 1: Trial Division

This method involves dividing the given number by the smallest prime numbers, starting from 2, and continuing the division process with the quotient until it reaches 1. For each divisor found, it is added to the list of prime factors. The trial division is a straightforward and easy-to-understand approach.

Here’s an example:

def prime_factors_trial_division(n):
    factors = []
    divisor = 2
    while divisor * divisor  1:
        factors.append(n)
    return factors

print(prime_factors_trial_division(60))

Output: [2, 2, 3, 5]

This code snippet defines a function prime_factors_trial_division() that takes an integer n and returns its prime factors. It does so by iteratively dividing n by the smallest divisor until it becomes 1, storing each prime factor encountered. The function finally appends the remaining number if it is greater than 1, ensuring all prime factors are found.

Method 2: Sieve of Eratosthenes

The Sieve of Eratosthenes is an efficient way to find all prime numbers up to a given limit and can be modified to find the prime factors of a number. By first generating a list of prime numbers, we reduce the number of potential divisors when finding the prime factors of our target number.

Here’s an example:

def sieve_of_eratosthenes(n):
    sieve = [True] * (n+1)
    for i in range(2, int(n**0.5) + 1):
        if sieve[i]:
            for j in range(i*i, n+1, i):
                sieve[j] = False
    return [i for i in range(2, n+1) if sieve[i]]

def prime_factors_sieve(n, primes):
    factors = []
    for prime in primes:
        while n % prime == 0:
            factors.append(prime)
            n //= prime
    if n > 1: 
        factors.append(n)
    return factors

primes = sieve_of_eratosthenes(60)
print(prime_factors_sieve(60, primes))

Output: [2, 2, 3, 5]

The function sieve_of_eratosthenes() generates all prime numbers up to a given limit n. The function prime_factors_sieve() uses this list to find the prime factors of n, resembling trial division but with fewer iterations needed because it divides only by known primes.

Method 3: Optimized Trial Division with 6k +/- 1 Rule

The optimized trial division uses the mathematical fact that all primes are of the form 6k+/-1 (with obvious exceptions of 2 and 3). We can use this fact to avoid unnecessary divisions, significantly speeding up the trial division method for finding prime factors.

Here’s an example:

def prime_factors_optimized(n):
    factors = []
    while n % 2 == 0:
        factors.append(2)
        n //= 2
    while n % 3 == 0:
        factors.append(3)
        n //= 3

    i = 5
    while i * i  1:
        factors.append(n)
    return factors

print(prime_factors_optimized(60))

Output: [2, 2, 3, 5]

In this example, using prime_factors_optimized(), we first remove all factors of 2 and 3. Then, we iterate through potential prime factors following the 6k+/1 pattern to factorize the remaining n. When the square of the current divisor exceeds n, we can conclude that n is either 1 or a prime number and handle it accordingly.

Method 4: Using Factorization Wheels

Factorization wheels are a way to skip multiples of the first few primes when searching for prime factors. It combines the simplicity of the trial division with a pattern that avoids needless checks, resulting in a more efficient factorization process.

Here’s an example:

def prime_factors_wheel(n):
    factors = []
    increments = [4, 2, 4, 2, 4, 6, 2, 6]
    divisor = 2
    while n % divisor == 0:
        factors.append(divisor)
        n //= divisor
    divisor = 3
    while n % divisor == 0:
        factors.append(divisor)
        n //= divisor
    divisor = 5
    wheel_index = 0
    while divisor * divisor  1:
        factors.append(n)
    return factors

print(prime_factors_wheel(60))

Output: [2, 2, 3, 5]

In the prime_factors_wheel() function, the wheel (a list of increments) allows us to test for divisibility using increments that skip multiples of 2, 3, and 5. This reduces the number of required divisibility tests. After testing against lower primes, the wheel is used to increment the divisor for further tests.

Bonus One-Liner Method 5: List Comprehension with Trial Division

Python enables concise expression of algorithms with list comprehensions. The prime factors of a number can be computed using trial division within a list comprehension that elegantly combines generation and filtering of potential factors.

Here’s an example:

n = 60
prime_factors_oneliner = [p for p in range(2, n // 2 + 1) if n % p == 0 and all(p % d != 0 for d in range(2, int(p ** 0.5) + 1))]
print(prime_factors_oneliner)

Output: [2, 3, 5]

This one-liner works by iterating over all numbers from 2 to n//2 and checking if they are factors of n. Furthermore, it ensures that these factors are prime by verifying that no divisors exist that can divide them evenly (excluding one and the number itself).

Summary/Discussion

  • Method 1: Trial Division. Simple and intuitive. Inefficient for large numbers.
  • Method 2: Sieve of Eratosthenes. Efficient for a range of numbers but redundant for a single number calculation.
  • Method 3: Optimized Trial Division with 6k +/- 1 Rule. More efficient for larger numbers. Slightly more complex.
  • Method 4: Using Factorization Wheels. Avoids unnecessary checks. Can be complex to understand and implement.
  • Method 5: List Comprehension with Trial Division. Elegant and concise. May be less efficient and does not sort factors.