Reducing by one recursion - python

I am currently working on a school assignment to generate the first 25 prime numbers using recursion. While the program I have written generates the prime numbers, an error occurs after the 23rd number.
RecursionError: maximum recursion depth exceeded in comparison
I have fixed this issue by extending the recursion depth on my own computer, however I realize that not everyone will have done the same. I have determined that I will instead shorten the amount of recursions running in the program. I am having trouble with this and would like to ask for help.
First.
def checkPrime(a, n, c):
Where a is the divisor, n is the possible prime, and c is the iteration.
if c <= 24:
if n % a <= 0:
if n == a:
print(n, end = ' ')
return checkPrime(2, n + 1, c + 1)
return checkPrime(2, n + 1, c)
return checkPrime(a + 1, n, c)
It basically checks the iteration, whether n is divisible by a, and if n is equal to the a. If n isn't divisible by a it recurs with a plus one. If n isn't equal to a it recurs with the next possible prime and resets the divisor to 2. If everything is True it prints the prime and recurs with the next possible prime, resets the divisor to 2, and add one to the counter.
I call the function like this:
checkPrime(2, 2, 0)
Two is the starting divisor and possible prime number and 0 is the iteration.
What I would like to do is be able to get rid of one of the recursions. I do not want to be told the exact line code I would need to use. If you would just point me in the right direction I would very much appreciate it. Thank you.

If you're allowed any and all, then your critical test is to see whether you have any valid divisor of the candidate number:
limit = ceil(sqrt(cand+1))
if not any([cand % divisor == 0 for divisor in range(2, limit)]):
# This is a prime
Can you take it from there?

Related

Recursive function to check if a given number is Fibonacci

I'm new to python and I'm am having problems building a recursive function that checks if a given number is a Fibonacci number.
This is my code.
def isFib(n):
if n <= 1:
return n
else:
return (n - 1) + (n - 2)
if isFib(n) == 1 or isFib(n) == isFib(n - 1) + isFib(n - 2):
return True
It should print True in both cases, but instead it print True and False, and I can't find what's wrong
print(all([isFib(i) for i in [1,2,3,5,8,13,21,34,55]]))
print(all([not isFib(2*i) for i in [1,2,3,5,8,13,21,34,55]]))
The first part of your function is an if statement. If True, it returns a value - if False, it also returns a value. So, the second part of your function cannot possible execute, and the function isn't recursive (since you don't call the function again in either return statement).
More generally, what you're doing will never work. The logic seems to be: "a Fibonacci number is the sum of the previous Fibonacci number and the number before that, so I can reverse that logic by computing n - 1 and n - 2 and if they are Fibonacci numbers, then so is n" - or something like that.
But that doesn't work: 5 is a Fibonacci number, but (5-1) is not, so the logic breaks right there. If you were thinking only the sum needed to be a Fibonacci number: 13 is a Fibonacci number, but (13-1) + (13-2) = 23 and that's not a Fibonacci number either.
An easy way to solve this would be to just generate a Fibonacci sequence and return True as soon as the number you're checking comes up:
def is_fib(n, seq=None):
if seq is None:
seq = [0, 1]
# n is Fibonacci if the last number in the sequence is
# or if the last number has not yet past n, then compute the next and try again
return n == seq[-1] or (seq[-1] < n and is_fib(n, seq + [seq[-2] + seq[-1]]))
print([is_fib(i) for i in [1,2,3,5,8,13,21,34,55]])
print(is_fib(23))

Problem with python code for finding largest prime factor of a number (Project Euler problem 3)

I'm currently trying to solve Project Euler problem 3 using python, which is trying to find the largest prime factor of a number. The method I'm using is essentially brute forcing my way through each integer less than the integer in question, checking if it's a factor of said integer, and then checking if it is prime. However, for some reason, my code doesn't seem to be working.
I've tried to use create a function which goes through each integer (i) less than a given integer (n), and if i is divisible by n, the function then proceeds to check if i is a prime number by going through every integer less or equal to i (x). if x is a factor of i, then the value is added to a zero-integer defined as (a). After that, if a ends up adding to equal i + 1, then that means the factor is prime, since the only numbers divisible were itself and 1. The code is as below:
def primefactor(n):
for i in range(1, n+1): #goes through each integer less than n
if n % i == 0: #checks if integer is a factor
for x in range(1, i+1): #another loop to check if the factor is prime
a = 0
primenumbers = []
if i % x == 0:
a += x
if a == i + 1:
primenumbers.append(i)
print(primenumbers)
primefactor(13195)
What i expected the output to be was for it to print a list of all of the prime factors of the number, in this case, [5, 7, 13, 29], but instead, all I got was an empty list, []
This issue with your code is you assign primenumbers to an empty list each iteration with primenumbers = [].
Also if you don't want to brute force it, a good method to solve solutions like this is to google a formula such as Formula for primes and you will find:
By Wilson's theorem, n+1 is prime if and only if n! mod(n + 1) = n.
So you can do something like this:
# This is just used as caching to make it faster
# it is not needed.
from functools import lru_cache
from math import factorial
#lru_cache()
def isprime(x):
n = x - 1
if n == factorial(n) % (n + 1):
return True
else:
return False
def primefactor(n):
primenumbers = []
for i in range(1, n + 1): #goes through each integer less than n
if n % i == 0: #checks if integer is a factor
isprime(i) and primenumbers.append(i)
print(primenumbers)
primefactor(13195)
Output:
[1, 5, 7, 13, 29]
There are also significantly faster solutions then this such that does go through all numbers 0 to n:
Algorithm to find Largest prime factor of a number

listing prime numbers from 3 to 21 in python 3

for x in range (3,21):
if(x%2==0):
print (x,'is a not a prime number')
else:
print (x,'is a prime number')
This is my code but when it prints it says 9 is a prime number and 15 is a prime number.
Which is wrong because they aren't so how do I fix that?
.
def isPrime(N):
i = 2
while i**2 <= N:
if N % i == 0:
return False
i+=1
return True
for i in range(3, 21 + 1):
if isPrime(i):
print(i, 'is prime')
else:
print(i, 'is not a prime number')
First of all, create a function for determining whether or not a given number is prime (this is not a requirement but just a good practice). That function is not that hard: it just starts at i = 2 (starting at 1 makes no sense because every number can be divided by it) and check if N can be divided by it. If that is the case, we have found a divisor of N and thus, it isnt prime. Otherwise, continue with the next number: i += 1. The most tricky part of the loop is the stoping condition: i**2 <= N: we dont have to look further, because if some j > i is a divisor of N, then there is some other k < i that is also a divisor of N: k * j == N. If such k exists, we will find it before getting to the point where i * i == N. Thats all. After that, just iterate over each number you want to check for primality.
Btw, the best way to check for the primality of a set of number is using the Sieve of Eratosthenes
Your code only checks if a number is even. All odd numbers are not prime. So write a for-loop that checks if a odd number is divisible by any of the odd number less than that. Sometying like:
For i in (3 to n): If n mod i == 0, n is not prime.

Euler Project #3 in Python

I'm trying to solve the Project Euler problem 3 in Python:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
I know my program is inefficient and oversized, but I just wanted to know why doesn't it work?
Here's the code:
def check(z):
# checks if the given integer is prime
for i in range(2, z):
if z % i == 0:
return False
break
i = i+1
return True
def primegen(y):
# generates a list of prime integers in the given range
tab = []
while y >= 2:
if check(y) == True:
tab.append(y)
i = i-1
def mainfuntion(x):
# main function; prints the largest prime factor of the given integer
primegen(x)
for i in range(len(tab)):
if x % tab[i] == 0:
print tab[i]
break
mainfuntion(600851475143)
And here's the error:
for i in range(2, z):
OverflowError: range() result has too many items
The reason is that a list in Python is limited to 536,870,912 elements (see How Big can a Python Array Get?) and when you create the range in your example, the number of elements exceeds that number, causing the error.
The fun of Project Euler is figuring out the stuff on your own (which I know you're doing :) ), so I will give one very small hint that will bypass that error. Think about what a factor of a number is - you know that it is impossible for 600851475142 to be a factor of 600851475143. Therefore you wouldn't have to check all the way up to that number. Following that logic, is there a way you can significantly reduce the range that you check? If you do a bit of research into the properties of prime factors, you may find something interesting :)
This is the code that I used!!
n = 600851475143
i = 2
while i * i < n:
while n % i == 0:
n = n / i
i = i + 1
print n
-M1K3
#seamonkey8: Your code can be improved. You can increase it by 2 rather than one. It makes a speed difference for really high numbers:
n,i = 6008514751231312143,2
while i*i <= n:
if n%i == 0:
n //= i
else:
i+=[1,2][i>2]

Python "OverflowError" [duplicate]

This question already has answers here:
`xrange(2**100)` -> OverflowError: long int too large to convert to int
(5 answers)
Closed 13 days ago.
I am just starting to learn to code in Python. I am trying to write some code to answer this Project Euler Question:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
My program works with the test case of 13195, but when I try to enter 600851475143, I get the error: "OverflowError: range() results has too many items"
Does anyone know how I can fix this?
Here is my code:
class Euler3:
"A class to find the largest prime factor of a given number"
n = 600851475143
primeFactors = []
for i in range(2,n):
if (n%i ==0):
primeFactors.append(i)
n = n/i
i = i -1 #reset i
print primeFactors
Any help or suggestions would be much appreciated!
The range function creates a list and tries to store it in memory. Creating a list many numbers long is what's causing the OverflowError. You can use xrange instead to get a generator which produces the numbers on demand.
That said, I think you'll find that your algorithm is way too slow for calculating large primes. There are a lot of prime number algorithms, but I might suggest checking out the Sieve of Eratosthenes as a starting point.
EDIT: Properly xrange actually doesn't return a generator, but an xrange object which behaves a lot like a generator. I'm not sure if you care, but it was bugging me that i wasn't precise!
I'm guessing you're using python 2 and not python 3 -- range(2,n) actually constructs a list! You don't have enough memory to store 600 billion numbers! xrange should be fine, though.
Also, your idea of i=i-1 doesn't work. For loops don't work like C, and that hack only works in C-style loops. The for loop iterates over range(2,n). If i gets the value 5 at once iteration, then no matter what you do to i, it still gets 6 the next time through.
Also, the list range(2,n) is constructed when you enter the loop. So when you modify n, that doesn't change anything.
You're going to have to rethink your logic a bit.
(if you don't believe me, try using 175 as a test case)
As a last comment, you should probably get in the habit of using the special integer division: n = n // i. Although / and // work the same in python 2, that is really deprecated behavior, and they don't work the same in python 3, where / will give you a floating point number.
You can fix the problem by using xrange instead of range
Your next problem will be that the program takes way too long to run because you need to break out of the loop under some condition
A better way to deal with repeat factors is to replace the if with a while
while (n%i ==0):
primeFactors.append(i)
n = n/i
n = 600851475143
primeFactors = []
for i in range(2,n):
i think you can optimize the function by noticing that
for i in range(2,n):
you can replace
range(2,n)
by
range(2,int(sqrt(n))+2)
because, you can see wiki...
This is the best way to find primes that I've found so far:
def isprime(n):
#make sure n is a positive integer
n = abs(int(n))
#0 and 1 are not primes
if n < 2:
return False
#2 is the only even prime number
if n == 2:
return True
#all other even numbers are not primes
if not n & 1:
return False
#range starts with 3 and only needs to go up to the square root of n
#for all odd numbers
for x in range (3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True #if it makes it through all the catches, it is a prime
This took me about 5 secs to get the answer.
import math
def is_prime_number(x):
for i in range(int(math.sqrt(x)), 2, -1):
if x % i == 0:
return False
return True
def next_prime_number(number):
#Returns the next prime number.
if number % 2 == 0 and number != 2:
number += 1
while not is_prime_number(number):
number += 2
return number
num = 600851475143
i = 2
while (i < long(math.sqrt(num) / 2)):
if num % i == 0:
largest = i
print largest
i = next_prime_number(i + 1)
xrange won't probably help you(or it may!),but the key thing here is to reliaze that you don't need to find the prime numbers up till 600851475143 or the factors of 600851475143,but it's prime factors,so...
Use the good old prime factorization method ,like so:
A=600851475143
n=2
fac=[]
while(n<=int(A)):
B=1
while(A%n==0):
B=0
A=A/n
if(B==0):
fac.append(n)
n=n+1
print max(fac)
This will return the argest prime factor almost instantly
I was battling with this Python "OverflowError", as well, working on this project. It was driving me nuts trying to come up with a combination that worked.
However, I did discover a clever, at least I think so :), way to do it.
Here is my code for this problem.
def IsNumberPrime(n):
bounds = int(math.sqrt(n))
for number in xrange(2,bounds+2):
if n % number == 0:
return False
return True
def GetListOfPrimeFactors(n):
primes = []
factors = GetListOfFactors(n)
if n % 2 == 0:
primes.append(2)
for entries in factors:
if IsNumberPrime(entries):
primes.append(entries)
return primes
GetListOfPrimeFactors(600851475143)
def GetListOfFactors(n):
factors = []
bounds = int(math.sqrt(n))
startNo = 2
while startNo <= bounds:
if n % startNo == 0:
factors.append(startNo)
startNo += 1
return factors
What I did was take the factors of the number entered and enter them into a list "factors". After that, I take the list of factors and determine which ones are primes and store them into a list, which is printed.
I hope this helps
-- Mike

Categories

Resources