Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I was curious if anyone could fix my code, this is for project Euler Question 3 (What is the largest prime factor of the number 600851475143 ?), as of now, I am sticking to a program that will find all the prime factors in 100, but am getting an error message for divide by 0, in my head the code seems to work, but it isn't. Unless absolutely necessary, I'd like to keep the while loops. Thanks.
def isPrime(A):
x = 2
while x < A:
if A % x == 0:
return False
x += 1
return A
def isInt(x):
if x == int(x):
return True
return False
A = int(input("Number? "))
counter = 2
while counter <= A:
if isInt(A/isPrime(counter)) == True:
print(counter)
counter += 1
print ("Done")
It seems the key issue is that isPrime() sometimes returns a boolean, and other times returns the input (an integer). You should avoid having functions that do too many things at once - a function called isPrime() should just indicate whether the input is prime or not (i.e. always return a boolean). Some other suggestions inline:
def isPrime(n): # n is a common variable name to use for "some number"
x = 2
while x < n:
if n % x == 0:
return False
x += 1 # this isn't an ideal way to detect primes, can you think of any improvements?
return True
def isInt(n): # use consistent variables - you used A above and x here, which is confusing
return n == int(n) # you can just return the boolean result directly
input = int(input("Number? ")) # use meaningful variable names when possible
counter = 2
while counter <= input:
# I *think* this is what you were trying to do:
# if counter is prime and input/counter is an integer.
# If not you may need to play with this conditional a bit
# also no need to say ' == True' here
if isPrime(counter) and isInt(input/counter):
print(counter)
counter += 1
print ("Done")
This should run (whether it works or not, I leave to you!), but it's still not as efficient as it could be. As you get into harder Project Euler problems you'll need to start paying careful attention to efficiency and optimizations. I'll let you dig into this further, but here's two hints to get you started:
Incrementing by one every time is wasteful - if you know something is not divisible by 2 you also know it's not divisible by 4, 8, 16, and so on, yet your code will do those checks.
In general finding primes is expensive, and it's a very repetitive operation - can you re-use any work done to find one prime when finding the next one?
Related
I'm new to both Python and StackOverflow so I apologise if this question has been repeated too much or if it's not a good question. I'm doing a beginner's Python course and one of the tasks I have to do is to make a function that finds the next prime number after a given input. This is what I have so far:
def nextPrime(n):
num = n + 1
for i in range(1, 500):
for j in range(2, num):
if num%j == 0:
num = num + 1
return num
When I run it on the site's IDE, it's fine and everything works well but then when I submit the task, it says the runtime was too long and that I should optimise my code. But I'm not really sure how to do this, so would it be possible to get some feedback or any suggestions on how to make it run faster?
When your function finds the answer, it will continue checking the same number hundreds of times. This is why it is taking so long. Also, when you increase num, you should break out of the nested loop to that the new number is checked against the small factors first (which is more likely to eliminate it and would accelerate progress).
To make this simpler and more efficient, you should break down your problem in areas of concern. Checking if a number is prime or not should be implemented in its own separate function. This will make the code of your nextPrime() function much simpler:
def nextPrime(n):
n += 1
while not isPrime(n): n += 1
return n
Now you only need to implement an efficient isPrime() function:
def isPrime(x):
p,inc = 2,1
while p*p <= x:
if x % p == 0: return False
p,inc = p+inc,2
return x > 1
Looping from 1 to 500, especially because another loop runs through it, is not only inefficient, but also confines the range of the possible "next prime number" that you're trying to find. Therefore, you should make use of while loop and break which can be used to break out of the loop whenever you have found the prime number (of course, if it's stated that the number is less than 501 in the prompt, your approach totally makes sense).
Furthermore, you can make use of the fact that you only need check the integers less than or equal to the square root of the designated integer (which in python, is represented as num**0.5) to determine if that integer is prime, as the divisors of the integers always come in pair and the largest of the smaller divisor is always a square root, if it exists.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
divisors = []
def check_for_prime(x):
divisors = [x / d for d in list(range(x)) if x != any([0, 1, x])]
if isinstance(divisors, float):
yield x
When I try to run this code, it shows an error: 'list object cannot be interpreted as an integer'. How can I fix this so the loop can successfully divide everything?
It seems like you are trying to check if a given number is prime through list comprehension. There are a good bunch of things wrong with your logic-
divisors = [x / d for d in list(range(x)) if x != any([0, 1, x])]
I believe you're trying to find a list of divisors for x here. This makes no sense though, even if I assume that you thought x != any([0, 1, x]) means "if x is either 0, 1, or x" (that's not actually what this code means). Wouldn't that statement always be true? I mean x has got to be x (unless it's nan, but that's a different topic).
If you wanted to express "if x is either 0, 1 or x" in python, you'd use if x in [0, 1, x] (you shouldn't want to though since that makes 0 sense as explained above). Not any. Read what any does.
To get a list of divisors for x, you should instead do-
divisors = [d for d in range(2, math.floor(x/2) + 1) if x % d == 0]
Essentially, you start from 2 (not 0 because that's impossible, and not 1 because we want to avoid that for prime checking), and stop at half the given number (because after that point, you can't divide the given number and get an integral result). Throughout this range, you only add those d for which x % d is 0. I.E, the result is integral. Notice, 6 % 3 is 0, because 3 is indeed a divisor of 6.
I have 0 clue what the hell you're trying to do here though-
if isinstance(divisors, float):
yield x
You're checking whether or not divisors is a float? why? you already know it's a list, you made it in the previous line.
I think you want to know if the given number is a prime or not. In that case, you can just check if the length of divisors is more than 0.
return len(divisors) > 0
Edit: As #RiccardoBucco mentioned below. If you don't want the list of divisors at all, you can simply return as soon as you find a divisor. A simple loop will suffice for that.
for d in range(2, math.floor(x/2) + 1):
if x % d == 0:
# x is not prime
return False
# x is prime
return True
However, DO NOT forget to factor in the exceptional case when x = 1, 1 is not a prime number. Should be factored in both the for loop and the list comprehension method.
You are passing your list as the input argument to range, which expects an integer. Don't do that. Say for i in list.
This will always fail because you're creating a new list by using the comprehension in line 3. Line 4 will always evaluate to False because a list is obviously not a float.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I need to check if the given integer is a prime, and return True if so. If not, I need to find the smallest factor which is more than 1. I'm completely new to this and even though code compiles it fails several test cases.
def isPrime(n):
if (n <= 1) :
return n
if (n <= 3) :
return 1
if (n % 2 == 0 or n % 3 == 0) :
return 2
i = 5
while(i * i <= n) :
if (n % i == 0 or n % (i + 2) == 0) :
return i
i = i + 6
return True
A prime is a number that can only be divided by one and itself. So, if we test x, we should test every number y such that 1 < y < x. A good way to test this is to use a for loop. Here is an example:
def isPrime(n):
for i in range(2,n):
if n % i == 0:
return False # because that means that something divides into n perfectly
return True
There are a few problems with this:
isPrime(1) returns True
Any negative number will return True
The program gets quite a bit slower as the numbers get bigger. For example, it takes 0.145 seconds to complete isPrime(1000003), but primes take longer to process, because as soon as a factor is found, the entire function stops and returns, whereas for a prime to be found, it has to run through every iteration up to n.
I'll leave those problems to you for the moment. In the meantime, we need a way to return the smallest factor. This is actually very easily done:
def isPrime(n):
for i in range(2,n):
if n % i == 0:
return i # i at this iteration is equal to the smallest factor
return True
So isPrime(20) returns 2, and isPrime(19) returns True. Hopefully this satisfies your needs.
I am studying Python by the book "a beginner guide to python 3" written by Mr.John Hunt. In chapter 8, which is about recursion, there is an exercise, that demands a code in which a prime number is found by recursion. I wrote first code below independently, but the answer key is written in different structure. Because I am very doubtful about recursion, What is your analysis about these two? Which is more recursive?
My code:
def is_prime(n, holder = 1):
if n == 2:
return True
else:
if (n-1 + holder)%(n-1) == 0:
return False
else:
return is_prime(n-1, holder+1)
print('is_prime(9):', is_prime(9))
print('is_prime(31):', is_prime(31))
Answer key:
def is_prime(n, i=2):
# Base cases
if n <= 2:
return True if (n == 2) else False
if n % i == 0:
return False
if i * i > n:
return True
# Check for next divisor
return is_prime(n, i + 1)
print('is_prime(9):', is_prime(9))
print('is_prime(31):', is_prime(31))
My suggestion in this case would be not to use recursion at all. Whilst I understand that you want to use this as a learning example of how to use recursion, it is also important to learn when to use recursion.
Recursion has a maximum allowed depth, because the deeper the recursion, the more items need to be put on the call stack. As such, this is not a good example to use recursion for, because it is easy to reach the maximum in this case. Even the "model" example code suffers from this. The exact maximum recursion depth may be implementation-dependent, but for example, if I try to use it to compute is_prime(1046527) then I get an error:
RecursionError: maximum recursion depth exceeded while calling a Python object
and inserting a print(i) statement shows that it is encountered when i=998.
A simple non-recursive equivalent of the "model" example will not have this problem. (There are more efficient solutions, but this one is trying to stay close to the model solution apart from not using recursion.)
def is_prime(n):
if n == 2:
return True
i = 2
while i * i <= n:
if n % i == 0:
return False
i += 1
return True
(In practice you would probably also want to handle n<2 cases.)
If you want a better example of a problem to practise recursive programming, check out the Tower of Hanoi problem. In this case, you will find that using recursion allows you to make a simpler and cleaner solution than is possible without it, while being unlikely to involve exceeding the maximum recursion depth (you are unlikely to need to consider a tower 1000 disks high, because the solution would require a vast number of moves, 2^1000-1 or about 10^301).
As another good example of where recursion can be usefully employed, try using turtle graphics to draw a Koch snowflake.
I'd say the Answer Key needs improvement. We can make it faster and handle the base cases more cleanly:
def is_prime(n, i=3):
# Base cases
if n < 2:
return False
if n % 2 == 0:
return n == 2
if i * i > n:
return True
if n % i == 0:
return False
# Check for next divisor
return is_prime(n, i + 2)
The original answer key starts at 2 and counts up by 1 -- here we start at 3 and count up by 2.
As far as your answer goes, there's a different flaw to consider. Python's default stack depth is 1,000 frames, and your function fails shortly above input of 1,000. The solution above uses recursion more sparingly and can handle input of up to nearly 4,000,000 before hitting up against Python's default stack limit.
Yes your example seems to work correctly. Note However, that by the nature of the implementation, the answer key is more efficient. To verify that a number n is a prime number, your algorithm uses a maximum of n-1 function calls, while the provided answer stops after reaching the iteration count of sqrt(n). Checking higher numbers makes generally no sense since if n is dividable without remainder by a value a > sqrt(n) it has to also be dividable by b = n % a.
Furthermore, your code raises an exception for evaluating at n = 1 since the modulo of 0 is not defined.
I am writing a program that must find if a number is even or not. It needs to follow this template. I can get it to find if a number is even or not recursively
The key is that you need to return a boolean value:
def isEven(num):
if (num <= 0):
return (num == 0)
return isEven(num-2)
For larger numbers though this quickly exceeds the default maximum recursion depth for Python. That can be remedied by calling sys.setrecursionlimit(n) where n is the number of recursive calls you want to allow. n in turn is limited by the platform you are on.
Try this, it works for integer values with 0 <= n <= sys.getrecursionlimit()-2:
def even(n):
return True if n == 0 else odd(n - 1)
def odd(n):
return False if n == 0 else even(n - 1)
It's a nice example of a pair of mutually recursive functions. Not the most efficient way to find the answer, of course - but nevertheless interesting from an academic point of view.
This template will help. You need to fill in the commented lines. The one you have in the question won't work - you aren't passing anything into isEven. This will only work if n >= 0, otherwise it will crash your program. Easy enough to fix if you ever need to deal with negative numbers.
def isEven(n):
if n == 0:
# Number is even
elif n == 1:
# Number is odd
else:
# Call the function again, but with a different n
Taking up wim's challenge to find a "different" way to do this: The prototypical recursive pattern is foo(cdr(x)), with a base case for the empty list… so let's write it around that:
def isEven(num):
def isEvenLength(l):
if not l:
return True
return not isEvenLength(l[1:])
return isEvenLength(range(num))
A really dumb use case for recursion, but here is my version anyway
import random
def isEven(num):
if random.random() < 0.5:
# let's learn about recursion!
return isEven(num)
else:
# let's be sane!
return num % 2 == 0
disclaimer: if you submitted this you'd probably tick off the teacher and come across as a smartypants.