Using python. The 'print' step in my prime factorizer works, but it never returns 1, and the list isn't generated either. Where is my program getting stuck?
from math import ceil, floor, sqrt
primeList = []
primeFactorList = []
def primeList(x):
primeList = [2]
for n in range(2,x):
for p in primeList:
if n%p == 0:
break
elif p == primeList[-1]:
primeList.append(n)
return(primeList)
# Generates list of prime numbers less than x
def primeFactorizer(x):
primeFactorList = []
while x != 1:
for p in primeList(x):
if x%p == 0:
primeFactorList.append(p)
x = x/p
print(x)
break
return(primeFactorList)
# Generates list of (possibly duplicate) prime factors of x
print(primeFactorizer(36))
primeListreturns primes up to but less than x.
If x in primeFactorizer is a prime number, x%p is never true inside the for-loop, therefore x never changes.
Forget about the primes and test every number for factorization:
def factorize(number):
factors = []
for factor in range(2, number + 1):
while number % factor == 0:
factors.append(factor)
number //= factor
print(number)
if number == 1:
break
return factors
print(factorize(36))
Related
I am trying to find all the prime numbers greater than 2 and less than 501. Please refer to my code given below:
num = 501
x = int(input('Enter a number greater than 1: '))
if x > 1:
for i in range(2, num):
if x % i == 0:
result = False
else:
result = True
if result == True:
print('Prime number.')
else:
print('Not a prime number.')
else:
print('Not a prime number.')
I tried to run the code for two numbers being 19 and 99. When I put a "break statement" after the code given below, I get the result of "99: not a prime number" but "19, being a prime is printed as not prime" and vice versa.
if x % i == 0:
result = False
break
Please correct the above code to print the correct output.
Instead of using trial division, it is much faster to use the Sieve of Eratosthenes, invented by a Greek mathematician over two thousand years ago:
def primes(n): # sieve of eratosthenes
i, p, ps, m = 0, 3, [2], n // 2
sieve = [True] * m
while p <= n:
if sieve[i]:
ps.append(p)
for j in range((p*p-3)/2, m, p):
sieve[j] = False
i, p = i+1, p+2
return ps
This function returns a list of primes less than n, sieving only on odd numbers and handling 2 separately. If you prefer to generate the primes rather than returning a list, use this:
def primegen(start=0): # stackoverflow.com/a/20660551
if start <= 2: yield 2 # prime (!) the pump
if start <= 3: yield 3 # prime (!) the pump
ps = primegen() # sieving primes
p = next(ps) and next(ps) # first sieving prime
q = p * p; D = {} # initialization
def add(m, s): # insert multiple/stride
while m in D: m += s # find unused multiple
D[m] = s # save multiple/stride
while q <= start: # initialize multiples
x = (start // p) * p # first multiple of p
if x < start: x += p # must be >= start
if x % 2 == 0: x += p # ... and must be odd
add(x, p+p) # insert in sieve
p = next(ps) # next sieving prime
q = p * p # ... and its square
c = max(start-2, 3) # first prime candidate
if c % 2 == 0: c += 1 # candidate must be odd
while True: # infinite list
c += 2 # next odd candidate
if c in D: # c is composite
s = D.pop(c) # fetch stride
add(c+s, s) # add next multiple
elif c < q: yield c # c is prime; yield it
else: # (c == q) # add p to sieve
add(c+p+p, p+p) # insert in sieve
p = next(ps) # next sieving prime
q = p * p # ... and its square
There is much more about primes at my blog.
If I'm not mistaken this will always return false for all numbers below 501 since when any inputed number will be divisible by itself.
You should also check if x != i.
This will work :
import math # This will import math module
def isprime(x):
if x > 1:
result = True
for i in range(2, int(math.sqrt(x))+1 ):
if ( x % i == 0):
result = False
break
if ( result == True):
print("Prime Number ")
else:
print("Not a Prime Number")
And do function call like:
isprime(19)
Please correct the above code to print the correct output.
I believe the following is both a simplified and corrected version of your code:
number = int(input('Enter a number greater than 1: '))
if number > 1:
for divisor in range(2, int(number ** 0.5) + 1):
if number % divisor == 0:
print('Not a prime number.')
break
else: # no break
print('Prime number.')
else:
print('Not a prime number.')
This code works but is not optimal. One simple optimization would be to handle 2/even as a special case and only divide by odd numbers starting at 3. A significant optimization would be to switch to a sieve approach as #user448810 suggests.
The code you provided only tests one number per user input. If you want to convert it to a loop that tests a range of numbers, say all numbers greater than 2 but less than 501, then we can do:
for number in range(3, 501):
if number > 1:
for divisor in range(2, int(number ** 0.5) + 1):
if number % divisor == 0:
print(number, 'is not a prime number.')
break
else: # no break
print(number, 'is a prime number.')
else:
print(number, 'is not a prime number.')
Can somebody solve this problem on Python ?
A positive integer m can be partitioned as primes if it can be written as p + q where p > 0, q > 0 and both p and q are prime numbers.
Write a Python function that takes an integer m as input and returns True if m can be partitioned as primes and False otherwise.
Tried this, but does not work for all testcases, for example it should return True for 3432, it returns False.
def partition(num):
primelist=[]
for i in range(2,num + 1):
for p in range(2,i):
if (i % p) == 0:
break
else:
primelist.append(i)
for x in primelist:
y= num-x
for z in range(2,y):
if y%z == 0:
return False
return True
The error lies in the second for loop. You are looping through possible primes x, and wish to then check that y = num - x is also prime.
The error in your logic is that in the second for loop, if the first element in the loop y = num - x is not prime, it will return False, without checking any of the other possible values.
You could correct this by moving the return False statement out one loop, but since you have already generated a list of primes less than num, primelist (and since y = num - x, (if prime y exists) it will be in this list), you can just check for membership of the list:
for x in primelist:
y= num-x
# Note: num = x + y, thus need only check y prime
if y in primelist:
return True
# If no such y is prime, not possible
else:
return False
Note: I would advise making the logic of your script more modular, separating out the prime list generator into its own function:
def partition(num):
"""
Return True if there exist primes x,y such that num = x + y.
Else return False.
"""
primelist = primes(num)
for x in primelist:
y= num-x
# Note: num = x + y, thus need only check y prime
if y in primelist:
return True
# If no such y is prime, not possible
else:
return False
def primes(num):
"""Return list of all primes less than num."""
primelist=[]
for i in range(2,num + 1):
for p in range(2,i):
if (i % p) == 0:
break
else:
primelist.append(i)
return primelist
final solution i got:
def primepartition(m):
primelist=[]
if m<0:
return False
else:
for i in range(2,m + 1):
for p in range(2,i):
if (i % p) == 0:
break
else:
primelist.append(i)
for x in primelist:
y= m-x
if y in primelist:
return True
return False
The given below code can hopefully give you the correct output.
def factors(n):
factorslist = []
for i in range(1, n+1, 1):
if n % i == 0:
factorslist.append(i)
return(factorslist)
def prime(n):
if factors(n) == [1, n] and n > 1:
return(True)
def primelist(n):
primenolist = []
for i in range(1, n+1, 1):
if prime(i) == True:
primenolist.append(i)
return(primenolist)
def primepartition(m):
if m > 0:
primenolist = primelist(m)
checklist = []
for p in primenolist:
q = m - p
if q in primenolist and p > 0 and q > 0:
checklist.append((p,q))
if len(checklist) > 0:
return(True)
else:
return(False)
else:
return(False)
Another approach,
Initially, we store all prime elements upto m and check for pair of primes whose sum equal to m
def primepartition(a):
l=[2]#since 'a' should be >=2 for below loops, we took here 2(1st prime).
for i in range(2,a):
flag=0
for j in range(2,i):
if i%j==0:
flag=0
break
else:
flag=1
if flag==1:
l.append(i)
for i in l:
for j in l:
if i+j==a:
return True
return False
n=int(input("Enter any number: "))
list=[]
for num in range(0,n + 1):
if num > 1:
for i in range(2,num):
if (num % i) == 0:
break
else:
list.append(num)
if (n<= 1):
print("False")
#print("It is not positive ")
else:
for i in list:
y = num -i
if (y in list):
print("True")
#print(y,"+",i,"=",n)
#print(i,"+",y,"=",n)
#print("The number can be expressed as the sum of two prime numbers.")
break
else:
print("False")
#print("The number can not be expressed as the sum of two prime numbers.")
Slight Variation of your code:
def primepartition0(m):
primelist=[]
if m<0:
return False
else:
for i in range(2,m + 1):
for p in range(2,i):
if (i % p) == 0:
break
else:
primelist.append(i)
for x in primelist:
for y in primelist:
if x != y and x+y == m:
return True
return False
An alternate approach that attemps to reduce the amount of code necessary:
def primepartition(m):
if m > 3:
for number in range(m // 2, m - 1):
difference = m - number
for psuedoprime in range(2, int(number ** 0.5) + 1):
if number % psuedoprime == 0 or difference > psuedoprime and difference % psuedoprime == 0:
break
else: # no break
return number, difference # as good a non-False result as any other...
return False
def factors(n):
factlist = []
for i in range(1,n+1):
# Since factors of 2 cannot be primes, we ignore them.
if n%i==0 and i%2!=0:
factlist.append(i)
return factlist
def isprime(n):
return(factors(n)==[1,n])
def preimesupto(n):
primelist = []
if n>=2:
primelist.append(2)
for i in range(n):
if isprime(i):
primelist.append(i)
return primelist
def primepartition(n):
if n<0:
return False
primelist = preimesupto(n)
for i in primelist:
j = n-i
if j in primelist:
return True
else:
return False
If you're not required to produce the actual primes but only test if there exists a pair of primes p and q such that p+q == N, you could make this very simple based on the Goldbach conjecture. All even numbers can be expressed as the sum of two primes. So return True if the number is even and check if N-2 is prime for odd numbers (because 2 is the only even prime and that's the only prime that will produce another odd number when starting from an odd number). This will boil down to a single prime test of N-2 only for odd numbers.
def primePart(N):
return N%2==0 or all((N-2)%p for p in range(3,int(N**0.5)+1,2))
primePart(3432) # True
primePart(37+2) # True
primePart(13+41) # True
primePart(123) # False
If you want to actually find a pair of primes that add up to N, you can generate primes up to N and return the first prime >= N/2 where N - prime is one of the primes already found:
def findPQ(N):
if not primePart(N): return
if N%2: return 2,N-2
isPrime = [0]+[1]*N
for p in range(3,N,2):
if not isPrime[p]: continue
if 2*p>=N and isPrime[N-p]: return p,N-p
isPrime[p*p::p] = [0]*len(isPrime[p*p::p])
output:
findPQ(3432) # (1723, 1709)
findPQ(12345678) # (6172879, 6172799)
To go beyond 10^9 you will need a more memory efficient algorithm than the sieve of Eratosthenes that is just as fast. This can be achieved with a dictionary of multiples of primes to skip:
def findPQ(N):
if not primePart(N): return
if N%2: return 2,N-2
skip,primes = {},{2}
for p in range(3,N,2):
if p in skip:
prime = skip.pop(p)
mult = p + 2*prime
while mult in skip: mult += 2*prime
if mult <= N: skip[mult] = prime
else:
if 2*p>=N and N-p in primes: return p,N-p
if p*p<=N: skip[p*p]=p
if 2*p<=N: primes.add(p)
output (takes a while but doesn't bust memory space):
findPQ(1234567890) # (617283983, 617283907)
def checkprime(number):
fact=1
for r in range(2,number):
if number%r==0:
fact=fact+1
return(fact<2)
def primepartition(m):
for i in range(2,m):
flag=0
if checkprime(i) and checkprime(m-i)==True:
flag=1
break
return(flag==1)
def matched(s):
list_of_string=list(s)
for y in range(len(list_of_string)):
if list_of_string[y]=='(':
for z in range(y,len(list_of_string)):
if list_of_string[z]==')':
list_of_string[y]='#'
list_of_string[z]='#'
break
return('('not in list_of_string and ')'not in list_of_string)
def rotatelist(l,k):
if k>len(l):
k=int(k%len(l))
return(l[k:]+l[0:k])
SPOILER ALERT! THIS MAY INFLUENCE YOUR ANSWER TO PROJECT EULER #3
I managed to get a working piece of code but it takes forever to compute the solution because of the large number I am analyzing.
I guess brute force is not the right way...
Any help in making this code more efficient?
# What is the largest prime factor of the number 600851475143
# Set variables
number = 600851475143
primeList = []
primeFactorList = []
# Make list of prime numbers < 'number'
for x in range(2, number+1):
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
primeList.append(x)
# Iterate over primeList to check for prime factors of 'number'
for i in primeList:
if number % i == 0:
primeFactorList.append(i)
# Print largest prime factor of 'number'
print(max(primeFactorList))
I'll first just address some basic problems in the particular algorithm you attempted:
You don't need to pre-generate the primes. Generate them on the fly as you need them - and you'll also see that you were generating way more primes than you need (you only need to try the primes up to sqrt(600851475143))
# What is the largest prime factor of the number 600851475143
# Set variables
number = 600851475143
primeList = []
primeFactorList = []
def primeList():
# Make list of prime numbers < 'number'
for x in range(2, number+1):
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
yield x
# Iterate over primeList to check for prime factors of 'number'
for i in primeList():
if i > number**0.5:
break
if number % i == 0:
primeFactorList.append(i)
# Print largest prime factor of 'number'
print(max(primeFactorList))
By using a generator (see the yield?) PrimeList() could even just return prime numbers forever by changing it to:
def primeList():
x = 2
while True:
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
yield x
x += 1
Although I can't help but optimize it slightly to skip over even numbers greater than 2:
def primeList():
yield 2
x = 3
while True:
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
yield x
x += 2
If you abandon your initial idea of enumerating the primes and trying them one at a time against number, there is an alternative: Instead deal directly with number and factor it out -- i.e., doing what botengboteng suggests and breaking down the number directly.
This will be much faster because we're now checking far fewer numbers:
number = 600851475143
def factors(num):
factors = []
if num % 2 == 0:
factors.append(2)
while num % 2 == 0:
num = num // 2
for f in range(3, int(num**0.5)+1, 2):
if num % f == 0:
factors.append(f)
while num % f == 0:
num = num // f
# Don't keep going if we're dividing by potential factors
# bigger than what is left.
if f > num:
break
if num > 1:
factors.append(num)
return factors
# grab last factor for maximum.
print(factors(number)[-1])
You can use user defined function such as
def isprime(n):
if n < 2:
return False
for i in range(2,(n**0.5)+1):
if n % i == 0:
return False
return True
it will return boolean values. You can use this function for verifying prime factors.
OR
you can continuously divide the number by 2 first
n = 600851475143
while n % 2 == 0:
print(2),
n = n / 2
n has to be odd now skip 2 in for loop, then print every divisor
for i in range(3,n**0.5+1,2):
while n % i== 0:
print(i)
n = n / i
at this point, n will be equal to 1 UNLESS n is a prime. So
if n > 1:
print(n)
to print itself as the prime factor.
Have fun exploring
First calculate the sqrt of your number as you've done.
number = 600851475143
number_sqrt = (number**0.5)+1
Then in your outermost loop only search for the prime numbers with a value less than the sqrt root of your number. You will not need any prime number greater than that. (You can infer any greater based on your list).
for x in range(2, number_sqrt+1):
To infer the greatest factor just divide your number by the items in the factor list including any combinations between them and determine if the resultant is or is not a prime.
No need to recalculate your list of prime numbers. But do define a function for determining if a number is prime or not.
I hope I was clear. Good Luck. Very interesting question.
I made this code, everything is explained if you have questions feel free to comment it
def max_prime_divisor_of(n):
for p in range(2, n+1)[::-1]: #We try to find the max prime who divides it, so start descending
if n%p is not 0: #If it doesn't divide it does not matter if its prime, so skip it
continue
for i in range(3, int(p**0.5)+1, 2): #Iterate over odd numbers
if p%i is 0:
break #If is not prime, skip it
if p%2 is 0: #If its multiple of 2, skip it
break
else: #If it didn't break it, is prime and divide our number, we got it
return p #return it
continue #If it broke, means is not prime, instead is just a non-prime divisor, skip it
If you don't know: What it does in range(2, n+1)[::-1] is the same as reversed(range(2, n+1)) so it means that instead of starting with 2, it starts with n because we are searching the max prime. (Basically it reverses the list to start that way)
Edit 1: This code runs faster the more divisor it has, otherwise is incredibly slow, for general purposes use the code above
def max_prime_divisor_of(n): #Decompose by its divisor
while True:
try:
n = next(n//p for p in range(2, n) if n%p is 0) #Decompose with the first divisor that we find and repeat
except StopIteration: #If the number doesn't have a divisor different from itself and 1, means its prime
return n
If you don't know: What it does in next(n//p for p in range(2, n) if n%p is 0) is that gets the first number who is divisor of n
I have an assignment where I need to find if a number is a perfect cube without using ** or pow() function in python
EDIT: Reworked for cubes.
What you can do is use the mathematical approach you'd most likely use the prime numbers and splitting in prime factors. This is what I implemented too.
First function will dynamically build up a list of primes using Aristoteles
primes_list = [2]
def add_primes():
""" Function to expand the primes if we run out of them Aristoteles
"""
length = primes_list[primes_list.__len__()-1]
new_length = length*2
for i in range(length, new_length):
is_prime = True
for prime in primes_list:
if is_prime and i%prime == 0:
is_prime = False
if is_prime:
primes_list.append(i)
Second just like in math I split up the number into it's prime factors
def split_in_primes(number, found_primes=None):
""" Function to split the number in primes
"""
if found_primes is None:
found_primes = []
one_found = False
for prime in primes_list:
if number % prime == 0:
number /= prime
found_primes.append(prime)
one_found = True
if number > 1 and one_found:
split_in_primes(number, found_primes)
elif not one_found and number > 1:
add_primes()
split_in_primes(number, found_primes)
return found_primes
As last I check if the prime factors come in multitudes of 3, so being a perfect cube:
def is_perfect_cube(number):
""" Check if the number is a perfect cube
"""
found_primes = split_in_primes(number)
counts = []
for prime in primes_list:
counts.append(found_primes.count(prime))
is_cube = True
for count in counts:
if count%3 != 0:
is_cube = False
return is_cube
for i in range(0, 50):
print(str(i) + " is perfect cube? " + str(is_perfect_cube(i)))
ALTERNATIVE AND BETTER!! As pointed out in one of the comments this will be a lot more efficient if you re;ove split_in_primes and change iscube to:
def is_cube(number, start_index = 0):
""" Function to split the number in primes
"""
if number == 0:
return False
for prime in primes_list[start_index:]:
start_index += 1
count = 0
while number % prime == 0:
count += 1
number /= prime
if count != 0 and count%3 != 0:
return False
if number > 1:
add_primes()
is_cube(number, start_index)
return True
This will check emmediatly if a certain prime is in it a multitude of 3 tested with 124925014999 (4999**3) And still goes fast
I'm working on problem #3 on project euler, and I've run into a problem. It seems that the program is copying all the items from factors into prime_factors, instead of just the prime numbers. I assume this is because my is_prime function is not working properly. How can I make the function do what I want? Also, in the code, there is a line that I commented out. Do I need that line, or is it unnecessary? Finally, is the code as a whole sound (other than is_prime), or is it faulty?
The project euler question is: The prime factors of 13195 are 5, 7, 13 and 29. What is the largest prime factor of the number 600851475143 ?
A link to a previous question of mine on the same topic: https://stackoverflow.com/questions/24462105/project-euler-3-python?noredirect=1#comment37857323_24462105
thanks
import math
factors = []
prime_factors = []
def is_prime (x):
counter = 0
if x == 1:
return False
elif x == 2:
return True
for item in range (2, int(x)):
if int(x) % item == 0:
return False
else:
return True
number = int(input("Enter a number: "))
start = int(math.sqrt(number))
for item in range(2, start + 1):
if number % item == 0:
factors.append(item)
#factors.append(number/item) do i need this line?
for item in factors:
if is_prime(item) == True:
prime_factors.append(item)
print(prime_factors)
Yes, you need the commented line.
(It seems that on that case it's not necessary, but with other numbers the part of your code for getting factors would go wrong).
Check these references:
Prime numbers
Integer factorization
Why do we check up to the square root of a prime number to determine if it is prime or not
I got a very fast result on my computer with the following code:
#!/usr/bin/env python
import math
def square_root_as_int(x):
return int(math.sqrt(x))
def is_prime(number):
if number == 1:
return False
for x in range(2, square_root_as_int(number) + 1):
if x == number:
next
if number % x == 0:
return False
return True
def factors_of_(number):
factors = []
for x in range(2, square_root_as_int(number) + 1):
if number % x == 0:
factors.append(x)
factors.append(number/x)
return factors
factors = factors_of_(600851475143)
primes = []
for factor in factors:
if is_prime(factor):
primes.append(factor)
print max(primes)
# Bonus: "functional way"
print max(filter(lambda x: is_prime(x), factors_of_(600851475143)))
Your is_prime() returns early. Here's a fixed version:
def is_prime (x):
if x == 1:
return False
if x == 2:
return True
for item in range (2, int(x)):
if int(x) % item == 0:
return False
return True
you should not be using int(x) in the way that you currently are. i know you're forcing the int type because you want to convert from string input, but this will also allow the user to enter a float (decimal), and have it interpreted as either prime or not. that is bad behavior for the function. see my solution below. if you use eval to verify the input, you can just use x later, in place of int(x).
import math
factors = []
prime_factors = []
def is_prime (x):
x = eval(x) # this will cause a string like '5' to be evaluated as an integer.
# '5.2' will be evaluated as a float, on the other hand.
if type(x) != int:
raise Exception('Please enter an integer.') #prevents bad input
counter = 0 #this counter is not used. why is it initialized here?
if x == 1:
return False
elif x == 2:
return True
for item in range (2, x):
if x % item == 0:
return False
else:
return True
Use the while loop. n%i simply means n%i!=0
i = 2
n = 600851475143
while i*i <= n:
if n%i:
i+=1
else:
n //= i
print n