What is wrong with my primes number program? - python

def is_divisible(n, primes):
for i in range(1, len(primes)):
if n % primes[i] == 0:
return True
return False
primes = []
def find_primes(N):
for j in range(1, N):
if is_divisible(j, primes) == False:
primes.append(j)
return primes
print(find_primes(200))
It should tell if a number is prime. And just prints 1.

I think your issue is the indentation of the return statement. Here's your code fixed up:
def is_divisible(n, primes):
for i in range(0, len(primes)):
if n % primes[i] == 0:
return True
return False
def find_primes(N):
primes = []
for j in range(2, N):
if is_divisible(j, primes) == False:
primes.append(j)
return primes
Also avoid globals if you don't have to. find_primes doesnt need to access a global primes list it can declare it locally. Also, notice the range in find_primes that starts at 2 since every number is divisible by 1. Also, indendation matters. In both functions you do not iterate over the entire loop before returning the output (in find_primes) or the default (in is_divisible)

All numbers are divisible by 1. When your program checks if 1 is a prime it determines yes it is so it appends it to the array. Then, when it checks if the next number 2 is divisible by any of the existing primes it says yes, it is divisible by 1 therefore it is not a prime etc etc.

The first number you add is 1, every number is divisible by one and therefore is_divisible(x,1)== True and no number other then 1 is appended to the primes list.

In addition to the remark above (your program should start from 2), you do not want to return until you've completed the 'for j in range((2),N): ' loop. That is, you need to dedent the 'return primes' statement.

Your return primes line is inside the for loop, which means that it just check the first number (i.e. 1), and returns the result of that single calculation.
Your program should instead return the primes after looking at all the number, not just at the first one.

Related

How to create a piece of code which checks a number for its greatest prime factor?

I was trying to make a program which would check a number for its greatest prime factor. I was almost done when this error message came up. list index out of range.
What does this mean and what is wrong with my code?
Here is my code.
def is_prime(n):
for i in range(3, n):
if n % i == 0:
return False
return True
def Problem3():
x = 144
n = 2
not_a_factor = []
z = []
prime = []
not_a_prime = []
while n < x:
if x%n == 0:
z.append(n)
else:
not_a_factor.append(n)
n = n + 1
for i in z:
if is_prime(z[i]) == True:
prime.append(z[i])
else:
not_a_prime.append(z[i])
print(prime)
Problem3()
You're just a bit off. for-loops in Python iterate an object and return it's entities, not a pointer/ index.
So just use the thing you get from each iteration of 'z'
(Side note: might want to check out this post, it'll help you make your is_prime function more performant)
def is_prime(n):
for i in range(3, n):
if n % i == 0:
return False
return True
def Problem3():
x = 144
n = 2
not_a_factor = []
z = []
prime = []
not_a_prime = []
while n < x:
if x%n == 0:
z.append(n)
else:
not_a_factor.append(n)
n =+ 1 # Python version of n++
for i in z: # Python for-loop is more like a say "for each", no need for the indexing
if is_prime(i): # no need for '=='; Python will 'truthify' your object
prime.append(i)
else:
not_a_prime.append(i)
print(prime)
Problem3()
"list index out of range - what does this mean?"
The message list index out of range refers to an IndexError. Basically, this means that you are attempting to refer to an index in a list that doesn't exist.
Using your code as an example: you generate a list, z, containing the factors of the number 144. You then iterate through each element in this list (for i in z:). This means that for the:
1st iteration: i is the 1st element in z, which is 2;
2nd iteration: i is the 2nd element in z, which is 3;
and so on.
Then, you attempt if isprime(z[i]) == True:. So, as written, your program works like this:
1st iteration: if isprime(z[2]) == True:;
2nd iteration: if isprime(z[3]) == True:;
...
8th iteration: if isprime(z[16]) == True:
At this point, your code prompts an IndexError, because there are only 13 elements in z.
"what is wrong with my code?"
One way to get the result that you want is to iterate through range(len(z)) instead of each element of z. So, adjust the line for i in z to for i in range(len(z)).
Additionally, since prime is a list, and you want to return the greatest prime factor, change print(prime) to print(max(prime)).
These two changes will give you the result you are looking for.
Additional Learnings
Overall, your program could be written much more efficiently. If you want a simple algorithm to determine the greatest prime factor of a number, here is one possibility:
def greatest_prime_factor(n):
greatest_prime = 1
for i in range(n + 1):
# iterate through range(n). We skip index 0.
if i == 0:
continue
# determine if the number i is a factor of n.
if n % i == 0:
# determine if the number i is prime.
for i_ in range(2,i):
if i % i_ == 0:
break
else:
# update greatest_prime.
greatest_prime = max(greatest_prime, i)
return greatest_prime
print (greatest_prime_factor(144))
This algorithm saves a lot of memory space when compared with your original program by not initializing lists to store numbers that are primes, that aren't primes, etc. If you want to store those values, that's up to you; there are just far more efficient possibilities for what you appear to want to achieve.
Check this link for some more info on algorithmic efficiency and how to think about time and space complexity.

Why won't my code do literally anything?

I'm trying to write some code to compute the thousandth prime number and when I thought I was done I tried to run it but nothing is happening. I don't get errors or anything that should happen according to the code, just literally nothing. I'm running it in windows powershell if that matters. the code is here below. (Python 2.7)
n = 1
all_odd_integers = 2*n+1
prime_number = 2 #cause 3 is the second prime
while prime_number < 1000: #a while loop to get to prime thousand
for i in range (2, (all_odd_integers-1)): #because I want to divide all_odd_integers by all numbers except 1 and itsself and nothing bigger, but bigger than 0
if all_odd_integers % i == 0:
n += 1
print "not a prime" #because, like, if a number can be divided without a reminder it's not a prime
else:
n = n+1
prime_number += 1
print "a prime" #because exactly the opposite of the if-clause, here there is a reminder so prime
if prime_number == 1000:
print "the thousandth prime is %d" (all_odd_integers)
Your code isn't working because you have an infinite while loop, since your for loop isn't even being executed. You almost have the approach right for calculating the primes however.
If you want to print out every prime number as your current code would if it worked, you can much more easily implement something like this :
counter = 1
prime = 3
while counter != 1000:
for x in range(2,prime):
if prime%x == 0:
break
else:
print(prime)
counter += 1
prime += 2
Alternatively, if you only want to print out the thousandth prime I'm sure there are a plethora of more efficient ways, but I would lean towards something like this for simplicity and decent efficiency:
from math import sqrt
counter = 1
prime = 1
while counter < 1000:
prime += 2
for x in range(2,int(sqrt(prime+1)) + 1):
if prime%x == 0:
break
else:
counter += 1
print (prime)
I think you're thinking about this too hard. There are some errors to your code, but really it can all be boiled down to:
counter = 1
n = 2
while True:
n += 1
if all(n % i for i in xrange(2, n)): counter += 1
if counter == 1000: break
print "the thousandth prime is {0}".format(n)
This loops through all numbers between 2 and itself to see if any of them return a 0 remainder when n is divided by them. If none do, it's a prime and counter gets ticked, if not then it goes on to the next number. Once it finds 1000 primes it breaks and prints the thousandth prime is 7919
Some of the things wrong with your code:
all_odd_integers never changes. So when you do for i in range(2, (all_odd_integers-1)) it will never run anything except for i in range(2, 2) which is 0 because range excludes the higher number. all_odd_integers = 2*n+1 is only run once, when all_odd_integers is defined, it doesn't change when n does.
Even if all_odd_integers did update, why would you multiply it by two? Wikipedia has a prime defined as:
A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
If n was 3 then all_odd_integers would be 7? Why would 3 need to be divided by 4-6?
Just a note: there is no need to check if prime_number is equal to 1000 at the end since that's why the code block broke.
What if you start with n=2 and prime_number = 3? that way you'll reach the for loop.
Like the other anwserers, the condition in the while loop never changes.
Look at your range() call:
range (2, (all_odd_integers-1))
When you call range, there is a start (2) and a stop (all_odd_integers-1).
range(1,5) generates: 1,2,3,4
Look at all_odd_integers:
all_odd_integers = 2*n+1
2*n+1 means 2*1+1 because n = 1 so 2*n+1 = 3 therefore you are calling range(2,2) which gives [] and then the loop is never executed at all.
EDIT: More things
This function gives you your odd integers.
def odd_integers():
odd_integers = []
for i in xrange(1001):
if i/2 != int(i/2);
odd_integers.append(i)
return odd_integers
Here's your new for:
for i in odd_integers():
The condition in your while loop is always true. prime_number doesn't ever change. Look again at your code
for i in range (2, (all_odd_integers-1)):
What is this supposed to do if n=1 and therefore all_odd_integers-1 = 2?
The code under this loop is never executed.
EDIT:
To loop over odd integers just do this:
for i in xrange(1,1000,2):

Python "OverflowError" [duplicate]

This question already has answers here:
`xrange(2**100)` -> OverflowError: long int too large to convert to int
(5 answers)
Closed 13 days ago.
I am just starting to learn to code in Python. I am trying to write some code to answer this Project Euler Question:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
My program works with the test case of 13195, but when I try to enter 600851475143, I get the error: "OverflowError: range() results has too many items"
Does anyone know how I can fix this?
Here is my code:
class Euler3:
"A class to find the largest prime factor of a given number"
n = 600851475143
primeFactors = []
for i in range(2,n):
if (n%i ==0):
primeFactors.append(i)
n = n/i
i = i -1 #reset i
print primeFactors
Any help or suggestions would be much appreciated!
The range function creates a list and tries to store it in memory. Creating a list many numbers long is what's causing the OverflowError. You can use xrange instead to get a generator which produces the numbers on demand.
That said, I think you'll find that your algorithm is way too slow for calculating large primes. There are a lot of prime number algorithms, but I might suggest checking out the Sieve of Eratosthenes as a starting point.
EDIT: Properly xrange actually doesn't return a generator, but an xrange object which behaves a lot like a generator. I'm not sure if you care, but it was bugging me that i wasn't precise!
I'm guessing you're using python 2 and not python 3 -- range(2,n) actually constructs a list! You don't have enough memory to store 600 billion numbers! xrange should be fine, though.
Also, your idea of i=i-1 doesn't work. For loops don't work like C, and that hack only works in C-style loops. The for loop iterates over range(2,n). If i gets the value 5 at once iteration, then no matter what you do to i, it still gets 6 the next time through.
Also, the list range(2,n) is constructed when you enter the loop. So when you modify n, that doesn't change anything.
You're going to have to rethink your logic a bit.
(if you don't believe me, try using 175 as a test case)
As a last comment, you should probably get in the habit of using the special integer division: n = n // i. Although / and // work the same in python 2, that is really deprecated behavior, and they don't work the same in python 3, where / will give you a floating point number.
You can fix the problem by using xrange instead of range
Your next problem will be that the program takes way too long to run because you need to break out of the loop under some condition
A better way to deal with repeat factors is to replace the if with a while
while (n%i ==0):
primeFactors.append(i)
n = n/i
n = 600851475143
primeFactors = []
for i in range(2,n):
i think you can optimize the function by noticing that
for i in range(2,n):
you can replace
range(2,n)
by
range(2,int(sqrt(n))+2)
because, you can see wiki...
This is the best way to find primes that I've found so far:
def isprime(n):
#make sure n is a positive integer
n = abs(int(n))
#0 and 1 are not primes
if n < 2:
return False
#2 is the only even prime number
if n == 2:
return True
#all other even numbers are not primes
if not n & 1:
return False
#range starts with 3 and only needs to go up to the square root of n
#for all odd numbers
for x in range (3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True #if it makes it through all the catches, it is a prime
This took me about 5 secs to get the answer.
import math
def is_prime_number(x):
for i in range(int(math.sqrt(x)), 2, -1):
if x % i == 0:
return False
return True
def next_prime_number(number):
#Returns the next prime number.
if number % 2 == 0 and number != 2:
number += 1
while not is_prime_number(number):
number += 2
return number
num = 600851475143
i = 2
while (i < long(math.sqrt(num) / 2)):
if num % i == 0:
largest = i
print largest
i = next_prime_number(i + 1)
xrange won't probably help you(or it may!),but the key thing here is to reliaze that you don't need to find the prime numbers up till 600851475143 or the factors of 600851475143,but it's prime factors,so...
Use the good old prime factorization method ,like so:
A=600851475143
n=2
fac=[]
while(n<=int(A)):
B=1
while(A%n==0):
B=0
A=A/n
if(B==0):
fac.append(n)
n=n+1
print max(fac)
This will return the argest prime factor almost instantly
I was battling with this Python "OverflowError", as well, working on this project. It was driving me nuts trying to come up with a combination that worked.
However, I did discover a clever, at least I think so :), way to do it.
Here is my code for this problem.
def IsNumberPrime(n):
bounds = int(math.sqrt(n))
for number in xrange(2,bounds+2):
if n % number == 0:
return False
return True
def GetListOfPrimeFactors(n):
primes = []
factors = GetListOfFactors(n)
if n % 2 == 0:
primes.append(2)
for entries in factors:
if IsNumberPrime(entries):
primes.append(entries)
return primes
GetListOfPrimeFactors(600851475143)
def GetListOfFactors(n):
factors = []
bounds = int(math.sqrt(n))
startNo = 2
while startNo <= bounds:
if n % startNo == 0:
factors.append(startNo)
startNo += 1
return factors
What I did was take the factors of the number entered and enter them into a list "factors". After that, I take the list of factors and determine which ones are primes and store them into a list, which is printed.
I hope this helps
-- Mike

Prime number checker function is faulty

I wrote a function to calculate whether or not a number is prime, but try as it might, it just seems unable to give the correct response. It also prints the n value that is being incremented. Here is the code for the function (in Python, by the way):
def isPrime(x):
for n in range(1, x):
print n
if x % n == 0:
return False
return True
If I input
isPrime(17)
the function returns
1
False
What is going wrong here?
Every number is divisible by 1 and itself. A prime number is a natural number that has no positive divisors other than 1 and itself. Therefore, if you start your for-loop with 1, every number x will pass the condition x % 1 == 0 in the first iteration, returning False.
To fix it, you need to start your loop with 2 instead of 1. Also, as a side-note, you just need to loop from 2 to sqrt(x), since if there exists a number q > sqrt(x) that divides x, then there must also be a number p = x / q which also divides x, and p < sqrt(x).

Please help, this loop isn't working as expected and I don't know how to use booleans in Python

Am trying to write a piece of python code that calculate and print 1000 prime number from 2
however i only got 1999 as the last element in my result. I know there a lot of questions like this asked before but I wanna know why is my code is not working.
btw: how do i declare a boolean value in python? cant find a clue even googled···sad
mylist=[2]
num=1
count=0
while count<1000:
if num>1:
add=1
for i in mylist:
if num%i==0:
add=0
break
if add==1:
mylist=mylist+[num]
num=num+2
count=count+1
print mylist
Your loop should read while len(mylist) < 1000:, and remove all references to count. Either that, or you should only increment count every time you add a prime to the list.
Also, you don't 'declare' values in Python. You simply assign a value of the desired type to a variable, and poof, you have a variable of that type. In this case, True and False are boolean values and you can assign them to variables.
Here is my version in idiomatic (i.e. written the way an experienced Python programmer might write it) Python:
primes = [2]
candidate = 3
while len(primes) < 1000:
isprime = True
for testprime in primes:
if candidate % testprime == 0:
isprime = False
break
if isprime:
primes.append(candidate)
candidate = candidate + 2
print primes
If you want to write it in even terser and faster Python, do this:
import itertools
primes = [2]
candidate_iter = itertools.count(3, 2)
while len(primes) < 1000:
candidate = candidate_iter.next()
if all(candidate % testprime != 0 for testprime in primes):
primes.append(candidate)
print primes
If you're going to use Python, it's good to learn the Python idioms. I've used several below, including itertools.count, using not to test if something is equal to zero, else clauses on loops, and negative indexing to get the last item of a list.
Also, the Python standard is to use four-space indentation, as below; spaces around operators like =, ==, and %; and spaces after commas.
from itertools import count
mylist = [2]
# This will go up by 2s starting from 3: 3, 5, 7, 9...
for num in count(3, 2):
# For each prime already found
for i in mylist:
# if the prime is a factor of the number
if not num % i:
# don't add it
break
else:
# if none of the primes were factors
# add this number to the list of primes
mylist.append(num)
# if there are 1000 numbers in the list, we're done
if len(mylist) == 1000:
break
# print the 1000th prime
print mylist[-1]
The problem is that you're incrementing the variable count for each number in the set 1,3,5,...,2001. Instead you should increment the count only when add == 1
Here's the same as code for the later generations:
primes = [2] # initial list of primes
candidate = 1 # let's start at 1, could start at 3 as well
primesFound = 1 # We've actually found one already
while primesFound <= 1000: # continue till 1000 primes have been found
# using a counter instead of len(primes)
# maybe faster
if candidate > 1: # 1 is not a prime
isPrime = True
for i in primes: # iterate over all primes already found
if candidate % i == 0: # primes should not be divisable
isPrime = False # not a prime
break # no use going through the rest of the primes
if isPrime: # candidate is a prime so
primes = primes + [candidate] # add it to the primes list
primesFound += 1 # increment the prime counter
candidate += 2 # we can skip all even numbers
print primes # done.

Categories

Resources