Project Euler's number 3 - python

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.

Related

For-loop doesn't work as intended when replacing a variable with another

So I have this program where the first number you input is the amount of times the for-loop will run, and all the other times it checks if the number divides by 3 without a decimal point, and if true, it adds that number to the sum, then prints the final sum at the end.
a=int(input())
sum=0
for i in range (a):
a=int(input())
if a % 3 == 0:
sum=sum+a
print(sum)
But if I replace the "a" in for-loop with another variable(Let's say "b"), like this:
a=int(input())
sum=0
for i in range (a):
b=int(input())
if b % 3 == 0:
sum=sum+a
print(sum)
The code doesn't work as intended. I understand it like this: you enter the amount of times the for-loop will run (a); then each time you enter another number(b)(even though it's another variable), Python checks if it divides by 3 without a decimal point, and if true, adds it to the sum; then prints the final sum.
I just wanna know what's wrong in my thinking process here and why the code doesn't work with another variable.
welcome!
If you want to add 'b' to the sum, change it under the 'if' statement.
If you meant something else, please elaborate on what you want to achieve.
Good luck.

Finding prime numbers, I wrote an incorrect function and a correct one. But I am not sure why one is correct and one isn't

So the idea is to make a function that returns all prime numbers between any two numbers (inclusive).
Below, I'll put the function I wrote correctly, and the one I wrote incorrectly.
The mistake I made with the incorrect one is with the indentation of the "else" statement. But I'm not sure why one is correct and the other is not!
I'm also curious about the output I am getting from the incorrect function, which shows mostly duplicates of prime numbers but occasionally throws in a single number that is NOT a prime number, but rather a number divisible by 3 and another prime number. I have been trying to wrap my head around how the function produced this result (so I can understand the mistake), but I'm stumped!
Any help would be much appreciated
##This is the correct version: ##########################
def primefinder(start, end):
primes = []
for number in range(start, end +1):
if number > 1:
for i in range(2, number):
if number % i == 0:
break
else:
primes.append(number)
return primes
## This is the incorrect version:##############
def primefinder(start, end):
primes = []
for number in range(start, end +1):
if number > 1:
for i in range(2, number):
if number % i == 0:
break
else: ##<--This is my mistake##
primes.append(number)
return primes
Python is indentation-sensitive. If you change the indentation, then the code itself changes. Your first code has the else corresponding to the for, creating a for...else loop that only appends the prime to primes if the loop didn't break (if the loop encountered a break that means a factor was found so it's not prime).
In your incorrect version, the else is indented one extra, so it corresponds to the if, which means that as long as the number has a factor that it isn't divisible by (such as 8 not being divisible by 3), then it'll append to the list, once for every factor it isn't divisible by.
Any help would be much appreciated
When in doubt you might use help in interactive mode. In this case launch python and do help("for") to get following information:
The "for" statement
*******************
The "for" statement is used to iterate over the elements of a sequence
(such as a string, tuple or list) or other iterable object:
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
The expression list is evaluated once; it should yield an iterable
object. An iterator is created for the result of the
"expression_list". The suite is then executed once for each item
provided by the iterator, in the order returned by the iterator. Each
item in turn is assigned to the target list using the standard rules
for assignments (see Assignment statements), and then the suite is
executed. When the items are exhausted (which is immediately when the
sequence is empty or an iterator raises a "StopIteration" exception),
the suite in the "else" clause, if present, is executed, and the loop
terminates.
...
and so on, please note that this will work only if iteration ended due to exhaustion, not when you break-ed from your loop. Consider that
for x in [1,2,3]:
print(x)
else:
print("else")
will print "else" at end, whilst
for x in [1,2,3]:
print(x)
break
else:
print("else")
will not.

Trying to find the 1000th prime number

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

Python: determining if a number is prime [duplicate]

This question already has answers here:
How to create the most compact mapping n → isprime(n) up to a limit N?
(29 answers)
Closed 7 years ago.
I am new to Python and I'm attempting to write a code that checks to see whether or not a number is prime. So far, I've written this:
def main():
n = input("Enter number:")
isprime(n)
def isprime():
x = Prime
for m in range (1,n+1,1)
result = n % m
print result
main()
I'm not sure how to proceed after this. I know I have to define isprime. Any help would be greatly appreciated. Thank you!
Your first and biggest problem is that you need to list n as a parameter to isprime before you can use it within isprime, and before you can pass an argument in main. See the tutorial on Defining Functions for more details. But basically, it's like this:
def isprime(n):
Also, that x = Prime is going to raise a NameError, because there's nothing named Prime. Given that it doesn't actually do anything at all, you should just delete it.
Of course that won't make this a complete working prime testing function, but it is how to proceed from where you are.
The next step is to consider what to return from the function. If you find a value that divides n, then obviously n isn't prime, and therefore isprime is false. If you go through all possibilities and don't find anything that divides n, then isprime is true. So, with two return statements in the right places, you can finish the function.
Once it's at least always returning True or False, you have bugs to fix.*
Look at what numbers you get from range(1, n+1, 1). Two of those numbers are guaranteed to divide any n. How do you avoid that problem?
After you've got it working, then you can work on optimizing it. If you look up primality test on Wikipedia, you can see a really simple way to improve the naive trial division test. A bit of research will show the pros and cons of different algorithms. But if what you've got is fast enough for your purposes, it's usually not worth putting more effort into optimizing.
* You might want to consider writing a test program that calls isprime on a bunch of numbers and compares the results with the right answers (for answers you already know off the top of your head—1 is not prime, 2 is prime, 17 is prime, etc.). This is called Test Driven Development, and it's a great way to make sure you've covered all the possible cases—including outliers like 0, 1, 2, -3, etc.
Your isprime is quite close. The first line x = Prime is unnecessary, so let's get rid of that.
Now, let's take a look at what you're doing next:
You seem to want to check if there are any numbers that divide n perfectly. While this is the correct approach, you are including n and 1 in the numbers that you are testing. This is wrong for obvious reasons.
There is another error: you use n without ever defining it (I think you want it to be a parameter to your function). So let's put all this together:
def isprime(n):
for m in range(2, n):
if not n%m: # m divides n perfectly
return False
return True # if n were not prime, the function would have already returned
But going a step further, you don't really have to check every number between 2 and n-1. You just need to check the numbers between 2 and the square-root of n:
def isprime(n):
for m in range(2, int(n**0.5)+1):
if not n%m:
return False
return True

Modulus on a list, doable?

I'm trying to create a program which checks if the number is a prime number. My idea was to use the function that the square root of the number, divided by all numbers up to the square root defines if the number is a prime or not. (I hope you understand)
Anyway, I'm trying to find a way to use modulus on every character in my list. As an example
Prime % List(2,sqrtPrime) =/ 0 #I know this doesnt work, just a hint how i want it to work.
As the error if I run this is that I cant use modulus on a list, so how do i do it?
And also, will this idea go through every character from 2-sqrtPrime?
Thanks
What seems the optimal way to me, would look like:
rng = xrange(2, int(math.sqrt(n)) + 1)
is_prime = all(n % i for i in rng)
Main points are:
rng is a generator, not a list
expression within (...) is a generator as well, so no unnecessary intermediate lists are created
all will stop iterating as soon as the first divisor is found, thus no extra iterations
You could write a function that returns True if its argument is Prime and otherwise False, then run filter on the list.
import math
def isPrime(x):
for factor in range(2,math.floor(x**0.5)+1):
if x % factor == 0:
# x divides evenly, so
return False
return True
lst = [some, numbers, go, here]
primes_in_lst = filter(isPrime, lst)
Or if you're against filter as a rule (some people contend it's unpythonic) then you can put it in a list comp.
primes_in_lst = [num for num in lst if isPrime(num)] # exactly equivalent
and technically that isPrime function could be a lambda:
primes_in_lst = filter(lambda x: all(x%factor for factor in range(2,math.floor(x**0.5)+1)), lst)
But jeebus that's ugly.

Categories

Resources