From 77c4799317bb806d919f147b05e11f68e8c7d9aa Mon Sep 17 00:00:00 2001 From: Mattrixwv Date: Thu, 29 Oct 2020 10:36:05 -0400 Subject: [PATCH] Added prime number generator --- Algorithms.py | 111 +++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 65 deletions(-) diff --git a/Algorithms.py b/Algorithms.py index 0d0bf19..9cdaf67 100644 --- a/Algorithms.py +++ b/Algorithms.py @@ -20,8 +20,38 @@ Copyright (C) 2019 Matthew Ellison along with this program. If not, see . """ + import math + +#Generate an infinite sequence of prime numbers using the Sieve of Eratosthenes +#Based on code by David Eppstein found at https://code.activestate.com/recipes/117119/ +def primeGenerator(): + #Return 2 the first time, this lets us skip all even numbers later + yield 2 + + #Map composite integers to primes witnessing their compositeness + dict = {} + + #Start checking for primes with the number 3 + possiblePrime = 3 + while True: + #If q is not in the dictionary it is a new prime number + #Return it and mark it's next multiple + if possiblePrime not in dict: + yield possiblePrime + dict[possiblePrime * possiblePrime] = [possiblePrime] + #If q is in the dictionary it is a composite number + else: + #Move each witness to it's next multiple + for num in dict[possiblePrime]: + dict.setdefault(num + possiblePrime, []).append(num) + #We no longer need this, free the memory + del dict[possiblePrime] + + #Skip all multiples of 2 + possiblePrime += 2 + #This function returns a list with all the prime numbers <= goalNumber def getPrimes(goalNumber: int) -> list: primes = [] @@ -61,78 +91,29 @@ def getPrimes(goalNumber: int) -> list: #This function gets a certain number of primes def getNumPrimes(numberOfPrimes: int) -> list: + gen = primeGenerator() + #gen = postponed_sieve() primes = [] - foundFactor = False - - #If the number is 0 or negative return an empty list - if(numberOfPrimes < 1): - return primes - #Otherwise there is at lease 1, meaning 2 will be the first entry - else: - primes.append(2) - - #Loop through every odd number starting at 3 until you reach the correct number of entries looking for a prime number - possiblePrime = 3 #Holds the next possible prime number - while((len(primes) < numberOfPrimes) and (possiblePrime > 0)): - #Loop through all primes we have already found, up to sqrt(possiblePrime), checking for a factor - primesCnt = 0 - #We can safely assume that there will at lease be 1 element in the primes list because of 2 being added before the loop - topPossibleFactor = math.ceil(math.sqrt(possiblePrime)) - while(primes[primesCnt] <= topPossibleFactor): - #If you find a factor the number is not a prime so raise the flag and break the loop - if((possiblePrime % primes[primesCnt]) == 0): - foundFactor = True - break - else: - primesCnt += 1 - #Check if the index has gone out of bounds and break the loop if it has - if(primesCnt >= len(primes)): - break - - #If you don't find a factor then this number is prime so add it to the list - if(not foundFactor): - primes.append(possiblePrime) - #If it wasn't prime simply reset the flag - else: - foundFactor = False - #Increment to the next possible prime number - possiblePrime += 2 - - #Everything should already be in order, but sort it just in case - primes.sort() + for _ in range(1, numberOfPrimes + 1): + primes.append(next(gen)) #Return the list with all the prime numbers return primes #This is a function that returns all the factors of goalNumber def getFactors(goalNumber: int) -> list: - #You need to get all the primes up to this number - primes = getPrimes(math.ceil(math.sqrt(goalNumber))) #If there is a prime it must be <= sqrt(num) - factors = [] - - #You need to step through each prime and see if it is a factor in the number - cnt = 0 - while((cnt < len(primes)) and (goalNumber > 1)): - #If the prime is a factor you need to add it to the factor list - if((goalNumber % primes[cnt]) == 0): - factors.append(primes[cnt]) - goalNumber /= primes[cnt] - #Otherwise advance the location in primes you are looking at - #By not advancing if the prime is a factor you allow for multiple of the same prime number as a factor - else: - cnt += 1 - - #If you didn't get any factors the number itself must be a prime - if(len(factors) == 0): - factors.append(goalNumber) - goalNumber /= goalNumber - - #If for some reason the goalNumber is not 0 print an error message - if(goalNumber > 1): - print("There was an error in getFactors(). A leftover of " + str(goalNumber)) - - #Return the list of factors - return factors + prime_factors_list = [] + while goalNumber % 2 == 0: + prime_factors_list.append(2) + goalNumber /= 2 + for i in range(3, int(math.sqrt(goalNumber))+1, 2): + if goalNumber % i == 0: + prime_factors_list.append(i) + goalNumber /= i + if goalNumber > 2: + prime_factors_list.append(int(goalNumber)) + prime_factors_list.sort() + return prime_factors_list #This function returns all the divisors of goalNumber def getDivisors(goalNumber: int) -> list: