I'm receiving a "maximum recursion depth exceeded" error when executing my program to solve this problem. Project Euler's question #5 asks to find:
The smallest positive number that is evenly divisible by all of the numbers from 1 to 10.
I've tried to write a program that recursively checks if x is divisible by each integer 1-10, and if it doesn't then we call it again with x incremented by 1 and repeat until x is found. (In this case the answer is 2520, which is why I added the if statement.)
def euler5(x):
if x < 2521:
for i in range(1, 11):
if x % i == 0:
print(x)
else:
euler5(x+1)
else:
print(x)
x = 2
print(euler5(x))
The reason for this is that Python (or CPython, at least) has a limited stack size and no tail call optimization. So you cannot use unbounded recursion in Python, unlike Scheme (for example).
The solution is to use a regular loop:
x = 0
while True:
x += 1
# Put loop body here
In you defined function, you could you a loop even if you do not know math functions. However, your code is not efficient as program has to keep checking the values to see if it matches the condition. Recursion is not recommended as it should be flexible to be used with other values not just for this question. Euler questions are meant to train your coding practices.
A better method can be used to simplify your code:
from functools import reduce
from fractions import gcd
def lcm(a,b):
return a*b//gcd(a,b) #gcd is greatest common divisor AKA HCF
print (reduce(lcm, range(1, 20+1)))
Related
I wrote a program to find out the primes in a list of numbers, just so practice formatting and all. Here is my code:
from math import *
#Defining range to be checked
a = range(1,10)
#Opening empty list
b = []
#Wilsons method for primes
for n in a:
if ((factorial(n-1))+1)%n == 0:
b.append(n)
This code runs without issue and fairly fast, at least at this stage of use. However, when I include a while statement(see below), it is substantially slower.
from math import *
#Defining range to be checked
a = range(1,10)
#Opening empty list
b = []
#Wilson't method for primes
for n in a:
while n>1:
if ((factorial(n-1))+1)%n == 0:
b.append(n)
Could anyone explain why that would be the case?
n.b: I know there are more efficient method to find primes. I am just practicing formatting and all, although I don't mind improving my code.
edit: mistaken addition of less than symbol rather than the appropriate greater than symbol. Corrected.
As pointed out by several people your code will result in an infinite loop as the value of n does not change within your while-loop.
You are probably not looking for a while loop in the first place. It should be sufficient to use the for loop without the first iteration (n = 1). If you insist on including n=1, using an if statement is a possible workaround:
a=range(1,10)
b=[]
for n in a:
if n>1:
if ((factorial(n-1))+1)%n == 0:
b.append(n)
This question already has answers here:
Simple prime number generator in Python
(27 answers)
Closed 6 years ago.
I wrote this simple python function to calc:
def isPrime(number):
if number == 2:
return True
elif number > 1 and number % 2 != 0:
for current in range(3, number):
if number % current == 0:
return False
return True
And I'm calling it to print out the sum of all prime numbers from 1 to 2 million, as in project euler #10
However it's terribly slow, and I was wondering if I could tackle the same problem using generators? But I don't really understand generators in python completely..
Any help on how to solve this problem more efficiently would be appreciated! Thanks :)
Firstly, I suggest you use a better function to check whether a number is prime or not.
Here's a better modification, from https://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/ which is an excellent
explanation on generators in Python.
import math
def is_prime(number):
while True:
if number == 2:
return True
elif number > 1 and number % 2 != 0:
for current in range(3, int(math.sqrt(number) + 1), 2):
if number % current == 0:
return False
return True
return False
Secondly, you need to understand what a Generator actually does. Again Jeff Knupp explains it perfectly.
In short a generator is a function that does not "return" it simply "yields" and takes back control when the next() method is called on it.
So no variables that are created during the function are lost, and memory is saved by not creating the variables defined in the function again and again.
Then you can go on solving Euler 10, which is also explained in the link. :)
Good luck with the rest of the Eulers!
Another angle of attack on this problem is to try a different algorithm rather than attempting to optimize your current method. Learning more about generators is great, but you could also try solving this using a sieve, which can be quite efficient.
The general idea would be to "mark" all composite numbers (not prime), leaving behind the primes. It's pretty efficient, as my python implementation runs in ~3.5s
i m new to python and its great!. but i m facing difficulties in finding the result of this series:
1-x+(x^2)/2!-(x^3)/3!+(x^4)/4!-..............up to n terms
what i wrote was:
import math
a=input("ENter the no")
x=input("ENter value of x")
i=1
s=0
s1=0
s2=1
p=1
while(i<=a):
if(i%2!=0):
s=s-math.pow(x,i)/p*i
else:
s1=s1+math.pow(x,i)/p*i
i=i+1
else:
s2=s2+s1+s
print s2
please let me know of the correct program and the mistakes:)!! Thanks in advance.
let me know it without directly using the factorial function?
This is the Taylor's series development of exp(-x). Recognizing this gives you a good opportunity to check your result against math.exp(-x).
Simple syntax improvements
You don't need an 'else' after the while. Just add the code to be run after the loop at the same indentation level as before the while loop.
Mathematical problems
Most importantly, the computing of the factorial is simply never done. Writing p*i does not store in p the product of p and i. You need to do that.
Then, there is a problem with the operator precedence. When you write pow(...)/p*i, Python understands ( pow(...) / p ) * i, which is not what you mean.
Finally, most of the terms in the series cancel out, but you add all positive terms on one side and all negative terms on the other. This means that you will grow two very big values (and risk overflows if you were using integers), and then take the difference between them to get the result. Because double precision on a computer is finite, this is a bad practice precision-wise. It is better to keep all the terms in your sum with the same sort of orders of magnitudes.
Improved for correctness
import math
a=input("Enter the no")
x=input("Enter value of x")
s=1
p=1
for i in range(1,a):
p=p*i
if(i%2!=0):
s=s-math.pow(x,i)/p
else:
s=s+math.pow(x,i)/p
print s
print math.exp(-x)
Note how the use of a for loop and less intermedis-ry sums makes it all easier to read.
Removing the branch
pow(-x,i) is negative if i is uneven, positive otherwise. Thus -pow(x,i) if i%2 != 0 else pow(x,i) can be rewritten pow(-x,i). Removing an if in an inner loop is (almost ?) always a good thing, for performance. So a simplified version is :
import math
a=input("Enter the no")
x=input("Enter value of x")
s=1
p=1
for i in range(1,a):
p=p*i
s=s+math.pow(-x,i)/p
print s
print math.exp(-x)
That also has the benefit of making the code shorter (and thus more readable).
import math #imported to use the factorial function
def exp(x,n):
ans = 1 #initializing it with 1 because the first term is a constant:1
for i in xrange(1,n+1): #starts looping from 1 to n terms
ans+=(-1**i*(float(x)**i)/math.factorial(i)) #changing the sign of 1, adding.
# -1**i equals to 1 if i is even and -1 if i is odd
# ** operator stands for the pow() function , (2**3 =8)
# float(x) returns a floating value if value of x entered is integer
# You can remove this is you are already entering floating values.
# math.factorial() returns factorial of a given argument,
return ans
If you don't want to use the math.factorial() then you can try :
def exp(x,n):
ans = 1
dummy_factorial = 1
for i in xrange(1,n+1):
dummy_factorial*=i
print dummy_factorial
ans+=(-1**i*(float(x)**i)/(dummy_factorial))
return ans
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
I'm using Python 2.7.3 and have this function:
def f(n):
if n == 0:
return 0
else:
return (n % 3 == 0 or n % 5 == 0) * n + f(n - 1)
f(999)
It works until f(993), but not f(999). When I try, infinite amount of errors keep popping out. I don't get it. Can anyone tell me what's wrong?
Edit:
Thanks everyone for your answers. I guess i'm better off using iteration in python.
In Python, recursion is limited to 999 recursion call.
If you really want to change the limit of recursion call, you can use sys.setrecursionlimit(limit).
For example:
sys.setrecursionlimit(2000)
However, changing recursion limit can be dangerous. The stack frames might get too big.
From the doc:
This limit prevents infinite recursion from causing an overflow of the C stack and crashing Python. It can be set by setrecursionlimit().
What you can do is:
Like #Dan D. said, you better rewriting your code iteratively. Here is the reason why you should.
Better off using the iterative:
def f(n):
s = 0
while n > 0:
s += (n%3==0 or n%5==0)*n
n -= 1
return s
print f(999)
which outputs:
233168
Also one could write this with sum:
def f(n):
return sum((n%3==0 or n%5==0)*n for n in reversed(range(1,n+1)))
As you have already known from the other answers as to the reason for your code failure, and you have possibly got alternative solutions either by increasing the recursion limit or using an iterative solution
Alternatively, there is a smarter approach to your problem which requires a bit introspection to what you actually want to achieve
Sum all factors of 3 and 5 from 0 to N
Which simply boils down to
>>> def fn_ab(n):
numbers = [0]*n
numbers[0:n:3] = range(0,n,3)
numbers[0:n:5] = range(0,n,5)
return sum(numbers)