I am trying to write a script in python to find the 1000th prime number. I don't understand why this isn't working here. Basically while the mod is less than the square root of the number and still has a remainder, the mod goes up by one. This should continue until the mod equals the square root of the number. Then the check should remain at 0 and the number should be prime. Every time I try to run the script it tells me theres a system error.
import math
b=2
count=2
next_odd=3
next_prime=1
check = 0
while count<=10:
while b<float(math.sqrt(next_odd)):
if next_odd%b>0:
b+=1
if next_odd%b == 0:
check+=1
if check > 0:
next_prime=next_odd
next_odd+=2
print(next_prime)
b=2
count+=1`
I understand what you are trying to do, but unfortunately there were too many things wrong with your program. Here is a working version. I made minimal changes. Hopefully you can compare the below version with your own and see where you went wrong.
import math
count=2
next_odd=3
next_prime=1
while count<=1000:
b=1
check = 0
while b<float(math.sqrt(next_odd)):
b+=1
if next_odd%b == 0:
check+=1
if check == 0:
next_prime=next_odd
print(next_prime)
count+=1
next_odd+=2
With the above program, 1000th prime can be successfully determined to be 7919.
(first, I assume the tick on the end of your code is a typo in your stack overflow post, not the code itself)
Consider what happens when next_odd is prime. This block:
while b<float(math.sqrt(next_odd)):
if next_odd%b>0:
b+=1
if next_odd%b == 0:
check+=1
will increment b up until the square root of next_odd without ever incrementing check. That means that if check > 0: won't pass, and thus count never increments, and you then you just spin around in the
while count<=10:, skipping both if blocks because their conditions are false.
In other words, you don't actually say what to do when next_odd is prime. This is also an example of why while shouldn't really be used when all you want to do is increment through numbers (which is what you're using it for here). Try something like this:
max_num = 10000 # or whatever
for odd in range(3, max_num, 2):
factor_count = 0
for factor in range(2, math.floor(math.sqrt(max_num)) + 1):
if odd % factor == 0:
factor_count += 1
if factor_count == 0:
print(odd)
A couple points about this code:
There's no (non-constant) variables in the global scope. That makes it much easier to reason about how the script's state changes over time.
The use of for-loops over while-loops guarantees that our script won't get caught in an infinite loop due to an erroneous (or unaccounted for) condition.
The use of for-loops means that we don't have to worry about incrementing all of the variables ourselves, which dramatically reduces the amount of state that we have to manage.
Hope that helps!
Oh, note that there are much more efficient ways to compute primes also. See https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
Related
I am writing a recursive function to calculate the digital root of a given number:
def digital_root(num):
sum = 0
while num > 0:
sum += num % 10
num = num // 10
while sum > 10:
sum = digital_root(sum)
return sum
I am not sure if the second while should be replaced with an if statement, and if so, why? (and if not, why not?)
When I try both of the version, the return value is the same.
For example, for the number 10598, the output in both of them is 5.
Please make sure to accept the answer if it works tired of people not accepting my solutions, when it works for them
def digital_root(num):
#Base case for recursion.
# recursion always needs a base case
if len(str(num)) == 1:
return num
#Get sum of num by turning it into a string and looping through it,
#adding each index one by one
sum = 0
for i in str(num):
sum += int(i)
#get the digital root of the sum
return digital_root(sum)
def main():
print(digital_root(27518))
if __name__ == '__main__':
main()
There you go
So, first, please think what you're asking.
If relates to a condition, and while relates to perform a repeated action as long as a certain condition holds.
The digital root recursion stops only when the resulting digit sum is less than 10.
we need "if" for the base case of recursion.
but in this special case, you are using "while" as "if" and that works. but for readability, it is better to use "if".
the reason that it works:
both "while" and "if" have conditions
and the difference between them is just looping through the instructions
and it will be the same again because of the recursion.
I mean in this special case, due to that we have recursion, "if" acts like "while"
this is another answer for acounting the Digital root of a number using recursion:
def digital_root(n):
if(n < 10):
return n
n=n%10+digital_root(n//10)
return digital_root(n)
I'm doing a quiz from "Automate the Boring Stuff with Python", and after tinkering with the problem for a bit, I finally found a solution that worked (with a little help from a comp-sci buddy of mine). The quiz asks me to make program that executes a Collatz-sequence.
I understand the logic behind all of the code, EXCEPT for the final line.
Here's my code with a few comments:
def collatz(number):
if number % 2 == 0:
print(number // 2)
return number // 2
elif number % 2 == 1:
print(3 * number + 1)
return 3 * number + 1
guess = input("Your guess please ")
while guess != 1:
guess = collatz(int(guess))
The output of the program is a sequence of numbers, as the while-loop somehow re-iterates over the returned value of the function, and uses that for another computation.
My problem is with the last line. Here's how I understand it:
Once I enter the while-loop, my function "collatz" is called, using my input-value
The function is run, and my input is computed, and based on the input, I get either the even or odd calculation in return
Here's where my brain hurts!
Is the line "guess = collatz(...)" now constantly updating "guess" to be equal to the retuned value from the function? If this is the case, then I completely understand the flow. If it's not the case, then I don't understand how the returned value is constantly being used for new calculations.
Also, is this what is called "recursion"?
Short answer:
Yes.
Longer answer: (still short)
The collatz function is returning a value which is assigned to guess.
Also, this is not called recursion, recursion is a function which calls itself.
First, no, this is not a recursion. Recursion is a function that calls itself.
For instance this is a recursion:
def fibonacci(n):
if n == 0:
return 0
if n == 1:
return 1
return fibonacci(n-1) + fibonacci(n-2)
As you can see here fibonacci function will call fibonacci function ... But it also has an exit condition (n == 0, and n == 1). Without that, this would cause runtime error with message that maximum recursion depth exceeded. But if I am not mistaken, you can check what is the maximum depth of recursion with following command:
import sys
print(sys.getrecursionlimit())
On my computer, this number is 1000. If this number is to small for you, you can also set it with this command:
sys.setrecursionlimit(n)
About other thing. Your function is returning some calculated value and in your main loop, this is assigned to variable guess. So everytime, that main loop will go through, value of guess will also update
Can someone explain why this code works with the sample number 13195, but crashes when I use the problem's number
num = 13195
def isprime(num):
for i in range(2,num):
if num % i == 0:
ans = i
return ans
print isprime(isprime(isprime(num)))
In Python 2, range constructs a list. So the program is trying to contain an enormous list in memory, and it can't. Use xrange which will generate the numbers on demand for iteration instead of all at once.
You also need to end the loop early or it will spend forever checking so many numbers. So once you find a divisor, use it to divide the original number and make it smaller and thus manageable.
You need to assign a default value to ans.
When the input number is a prime number, the program never assigns anything to the variable ans. So that, when the function tries to return that variable, it is not actually defined.
Below is the code for printing n prime numbers in python. This program works fine, but i want to know the control flow. And the else statement does not match with it's previous if condition. If I try aligning it to the if condition, the execution throws an error. What exactly is happening here.
candidate = 3
count = 2
#n is the number of prime numbers to be printed.
n = 10
print("2")
while(count < n):
for x in range(2, candidate):
if(candidate % x == 0):
break
else:
print(str(candidate))
count +=1
if(count <= n):
candidate+=1
else belongs to for loop
If you read the Python doc, where the code comes from, you find there also the explanation.
You can read it as "what shall be executed, if the main loop completes without exceptions."
Python allows you to specify an else block for a for statement.
The else block is executed after the for, but only if the for terminates normally (not by a break).
Without this feature, you'd have to use an extraneous flag variable to keep track of this state. So, in your case, the else block would be executed iff (candidate % x == 0) was never true.
I have the following program:
def main():
print "Running"
primes = sieve(100000)
print "Sieve is done"
def sieve(n):
print "starting sieve"
primes = []
times = 0
numbers = range(2, n):
print "sieve array filled"
while len(numbers) > 0:
current = numbers[0]
primes.append(current)
numbers.remove(current)
times = times + 1
if (times % 10 == 0):
print str(times) + "th prime is " + str(current)
# Remove every multiple
for i in numbers:
if (i % current == 0):
numbers.remove(i)
When finding all the primes up to a large number (lets say ten thousand) I wanted to be able to see how far along the program is by looking at the output. So I decided I would print out every tenth prime. However, when printing it out, it waits until the very end of the program to print it. I added in sys.stdout.flush() right after the print statement but it didn't make any difference. I then tried running the script with python -u <file name> and still, no difference at all.
This is what I get as output:
Running
starting sieve
sieve array filled
Then after about a minute the rest of the output is shown at once.
Why can't I turn the buffer off? I'm trying to modify the code as little as possible.
Having tested a few things, I'm not sure that your problem is actually the output buffering, it's just the behaviour of your algorithm. Try printing current near the top of your while loop, and you'll see that the early numbers take a very long time to work through, and then as numbers gets shorter and shorter, each new value of current gets much faster to process and you start seeing the primes pop up.
Try:
while len(numbers) > 0:
current = numbers[0]
print current
primes.append(current)
numbers.remove(current)
The reason this is so slow is the loop where you remove elements from numbers:
# Remove every multiple
for i in numbers:
if (i % current == 0):
numbers.remove(i)
Every time you remove a number, Python has to go and shift all the elements after that number that you removed back one place. Every delete is O(n)*, and you do O(n) deletes, so each iteration of this step takes O(n^2) time.
If you replace this with a list comprehension, then Python builds a new list from the old list -- no moving involved -- which is an O(n) operation. Here's the way I would do that step:
# Remove every multiple
numbers = [i for i in numbers if (i % current) != 0]
With this change, your code runs way faster for me. It's done in under 5 seconds, and there's no output buffering problem.
*There's a nice table of time complexities for Python list operations here.
Try using sys.stdout.write instead of print. This should work better with sys.stdout.flush.