I’m trying to learn Python by working through the problems on the Project Euler website. I know exactly what I want my code to do, and my method works on paper, but I can’t make the code work.
GitHub link: https://github.com/albyr/euler-python/blob/master/euler3.py
I have created two functions, one which works out the factors of the target number, and one which checks whether a given number is prime.
# Function that finds all the factors of a given number
def findfactors(n):
# for i in range(1,int(sqrt(n)+1)):
for i in range(1,n+1):
if n/i == int(n/i):
factors.append(i)
# Function that checks if a number is prime
def checkprime(n):
# Trial division
for i in range(2,int(sqrt(n)+1)):
if n/i == int(n/i):
# Number gives a remainder upon division and therefore is not prime
isprime = False
break
else:
isprime = True
if isprime == True:
return True
elif isprime == False:
return False
I’m sure that to experts that code looks horrible. But it works if I use the Python shell:
>>> checkprime(9)
False
>>> checkprime(79)
True
>>> checkprime(factors[3])
True
But when I run the program with F5 I get:
Traceback (most recent call last):
File "/home/alby/euler-python/euler3.py", line 45, in <module>
checkprime(factors[i])
File "/home/alby/euler-python/euler3.py", line 32, in checkprime
if isprime == True:
UnboundLocalError: local variable 'isprime' referenced before assignment
If I call the checkprime function from within the program with a hardcoded number (e.g. checkprime(77)) I get no output at all. I’m certain that this is something basic about the way that Python works that I don’t understand, but I cannot for the life of me work out what.
Any suggestions?
In your Github code, we can see that you’re trying to call
checkprime(1)(on the first iteration through your last loop).But look at your code:
If
n = 1, thenrange(2, int(sqrt(1)+1))isrange(2,2)which is empty… soisprimenever gets set, because the loop body never gets run.Keep in mind that the arguments to
range()are a half-open interval –range(x,y)is “integers starting at x and ending before y”. Thusrange(2,3) = [2]andrange(2,2) = [].Another issue here is that
findfactors()is returning1as the first factor – this is probably not what you want:For prime factorization checking, you probably want to start at
2, not1(since everything is divisible by 1).Also, this code is redundant:
You can really just write this as…
Or you can go one step better and never use
isprimein the first place – just replaceisprime = Truewithreturn Trueandisprime = Falsewithreturn False.Finally, a shorthand for
int(n/i)isn // i– Python’s//operator does integer division.