Using Recursive Functions in Python to find Factors of a Given Number - python-3.x

Have tried searching for this, but can't find exactly what I'm looking for.
I want to make a function that will recursively find the factors of a number; for example, the factors of 12 are 1, 2, 3, 4, 6 & 12.
I can write this fairly simply using a for loop with an if statement:
#a function to find the factors of a given number
def print_factors(x):
print ("The factors of %s are:" % number)
for i in range(1, x + 1):
if number % i == 0: #if the number divided by i is zero, then i is a factor of that number
print (i)
number = int(input("Enter a number: "))
print (print_factors(number))
However, when I try to change it to a recursive function, I am getting just a loop of the "The factors of x are:" statement. This is what I currently have:
#uses recursive function to print all the letters of an integer
def print_factors(x): #function to print factors of the number with the argument n
print ("The factors of %s are:" % number)
while print_factors(x) != 0: #to break the recursion loop
for i in range(1,x + 1):
if x % i == 0:
print (i)
number = int(input("Enter a number: "))
print_factors(number)
The error must be coming in either when I am calling the function again, or to do with the while loop (as far as I understand, you need a while loop in a recursive function, in order to break it?)

There are quite many problems with your recursive approach. In fact its not recursive at all.
1) Your function doesn't return anything but your while loop has a comparision while print_factors(x) != 0:
2) Even if your function was returning a value, it would never get to the point of evaluating it and comparing due to the way you have coded.
You are constantly calling your function with the same parameter over and over which is why you are getting a loop of print statements.
In a recursive approach, you define a problem in terms of a simpler version of itself.
And you need a base case to break out of recursive function, not a while loop.
Here is a very naive recursive approach.
def factors(x,i):
if i==0:
return
if x%i == 0:
print(i)
return factors (x,i-1) #simpler version of the problem
factors(12,12)

I think we do using below method:
def findfactor(n):
factorizeDict
def factorize(acc, x):
if(n%x == 0 and n/x >= x):
if(n/x > x):
acc += [x, n//x]
return factorize(acc, x+1)
else:
acc += [x]
return acc
elif(n%x != 0):
return factorize(acc, x+1)
else:
return acc
return factorize(list(), 1)

def factors(x,i=None) :
if i is None :
print('the factors of %s are : ' %x)
print(x,end=' ')
i = int(x/2)
if i == 0 :
return
if x % i == 0 :
print(i,end=' ')
return factors(x,i-1)
num1 = int(input('enter number : '))
print(factors(num1))

Recursion is a functional heritage and so using it with functional style yields the best results. This means avoiding things like mutations, variable reassignments, and other side effects. That said, here's how I'd write factors -
def factors(n, m = 2):
if m >= n:
return
if n % m == 0:
yield m
yield from factors(n, m + 1)
print(list(factors(10))) # [2,5]
print(list(factors(24))) # [2,3,4,6,8,12]
print(list(factors(99))) # [3,9,11,33]
And here's prime_factors -
def prime_factors(n, m = 2):
if m > n:
return
elif n % m == 0:
yield m
yield from prime_factors(n // m, m)
else:
yield from prime_factors(n, m + 1)
print(list(prime_factors(10))) # [2,5]
print(list(prime_factors(24))) # [2,2,2,3]
print(list(prime_factors(99))) # [3,3,11]

def fact (n , a = 2):
if n <= a :
return n
elif n % a != 0 :
return fact(n , a + 1 )
elif n % a == 0:
return str(a) + f" * {str(fact(n / a , a ))}"

Here is another way. The 'x' is the number you want to find the factors of. The 'c = 1' is used as a counter, using it we'll divide your number by 1, then by 2, all the way up to and including your nubmer, and if the modular returns a 0, then we know that number is a factor, so we print it out.
def factors (x,c=1):
if c == x: return x
else:
if x%c == 0: print(c)
return factors(x,c+1)

Related

I want to return the sum of all indexes in n via recursion. How do I do this?

def final_sum(n):
n = str(n)
if int(n) == 0:
return 0
else:
x = int(n[0])
return x + int(final_sum(n[1:]))
print(final_sum(123))
For example, if my n is 123, I should be getting 6. But I am having an error in this code. Can anyone help? I have to use recursive function. So tell me what's wrong with the code.
in return x + int(final_sum(n[1:])), n[1:] is str type
in the beginning of the function, with n = str(n), you assume the input is an int
Besides, you did not consider the case that n[1:] can be empty in return x + int(final_sum(n[1:])).
Here is an anwser based on your code
def final_sum(n):
if n == 0:
return 0
n = str(n)
x = int(n[0])
if len(n)==1:
return x
else:
return x + final_sum(int(n[1:]))
Here is another version using % operation
def final_sum(n):
if n < 10:
return n
return n % 10 + final_sum(n // 10)
First of all, at the beggining I would do this instead of casting back and forth:
def final_sum(n):
if n<10:
return n
You see, the problem is, in the last recursive iteration, you are passing this to the function:
final_sum("")
When you should be passing an int. I think this is happening because your last cast is backwards and you never check how many digits the number has. So the code should look like this:
def final_sum(n):
if n<10:
return n
n = str(n)
x = int(n[0])
return x + final_sum(int(n[1:]))
print(final_sum(123))

how to fix ' find the prime factors of a number' in Python

I tried to find the prime factor for a number by the following code:
def pf(n):
f=[]
while n != 1:
for i in range(2, n+1):
if n%i == 0:
f.append(i)
n //=i
return f
The output for pf(8) is [2, 4], rather than [2,2,2] as my expect.
The output for pf(16) is [2,4,2], rather than [2,2,2,2].
can anyone help me to figure out what's wrong with my code?
If you break inside the loop, you will get what you want :
def pf(n):
f=[]
while n != 1:
for i in range(2, n+1):
if n%i == 0:
f.append(i)
n //=i
break
return f
Why was it wrong ?
in you first for loop, 8 is can be divied by 2, so n is equal to 4. And when i is then equals to 4, then 4 is added as a prime factor
Other implementation:
I prefer this implementation :)
def pf(n):
f=[]
i = 2
while n != 1:
if n%i == 0:
f.append(i)
n //=i
else:
i += 1
return f
This implementation avoids you to recompute the numbers in range you already know is not dividable by.

Python generator only returning first instance of yield

This code should produce all prime numbers in order when 'next' is called, but it only produces 2, the first prime number of the list. The list works properly to produce prime numbers.
def genPrime():
x = 1
primeList = [2]
while True:
x += 1
tempList = []
for i in range(len(primeList)):
tempList.append(x % primeList[i])
if min(tempList) > 0:
next = primeList[-1]
yield next
primeList.append(x)
prime = genPrime()
print(prime.__next__())
That's exactly what a generator is supposed to do. .__next__() only returns the next item, just as the name says.
Try:
print(prime.__next__())
print(prime.__next__())
print(prime.__next__())
You will see that you get them one by one.
Further, it is important that .__next__() is not meant to be called directly. The correct way is:
print(next(prime))
print(next(prime))
print(next(prime))
If you want them all, do:
for p in prime:
print(p)
Further, while not part of the answer, I give you a couple of programming tips:
for i in range(len(primeList)):
tempList.append(x % primeList[i])
has an unnecessary indirection. Just do
for prime in primeList:
tempList.append(x % prime)
Also, the entire tempList is unnecessary.
Just use a for-else construct:
def genPrime():
x = 1
primeList = []
while True:
x += 1
for prime in primeList:
if x % prime == 0:
break
else:
yield x
primeList.append(x)

Finding the logical error in my code to get first 50 primes

I'm trying to write my own formula to find a prime number, but it does not completely work and I cannot find the flaw in my logic. Bare in mind I have taken a look around but cannot find an algorithm that I find similar to mine.
My code:
#Challenge 7
prime = []
num = 0
found = False
while found == False:
if num == 0 or num == 1:
num+=1
else:
for value in range(2, num+1):
if len(prime) == 50:
print('Found all')
found = True
break
if num % value == 0:
num+=1
else:
if num not in prime:
prime.append(num)
else:
pass
print(prime)
This code works for first few primes (3, 5, 7...)
but it also gives incorrect values like 10, and I don't understand why. If someone could explain it to me so that I can understand where the logical mistake is, I'd appreciate it.
The error comes from this part
if num % value == 0:
num+=1
else:
if num not in prime:
prime.append(num)
else:
pass
You assume that the integer is a prime as soon as we find the first occurence of a non-divisor. But the def for primes is that every integer in the interval [2..prime] is a non-divisor. How do we check if any number does not have any divisors?
def isPrime(x):
for v in range(2, x):
if (x % v == 0):
return False;
return True;
Something like this would work to check if any given number is a prime or not. And since we now have taken the isPrime part out of the main loop, we no longer need a for loop inside the while. Something like this would do
def isPrime(x):
for v in range(2, x):
if (x % v == 0):
return False;
return True;
prime = [}
num = 2
found = False
while found == False:
if len(prime) == 50:
print("found all")
found = True
break
if(isPrime(num)):
print(num)
prime.append(num)
num+=1
else:
num+=1
If you set a breakpoint for when num == 10 you will see the problem clearly.
When you start doing you division check inside of for value in range(2, num + 1): the second number is 3, so num (10) modulo value (3) is 1, which is your test for determining a prime. What your test should be is that it not divisible by any number less than it (less than half is actually sufficient since you check with 2 anyway).
So, consider instead:
else:
is_indivisible = True
# loop through all numbers less than it not including itself
# (because x % x == 0)
for value in range(2, num - 1):
# it is only indivisible if it was previously indivisible
# And the check is same as before, modulo != 0
is_indivisible = is_indivisible and (num % value != 0)
if not is_indivisible:
break
# if it is indivisible and it doesn't exist in prime list yet
if is_indivisible and num not in prime:
prime.append(num)
# move on to the next number
num += 1

How to fix "maximum recursion depth exceeded" error in python code?

While I was running the code, I got a "maximum recursion depth exceeded in comparison" error. I'm not exactly sure which part of the code to look at to fix this problem. This numToBinary function is basically supposed to convert a number n to a binary number with bit size k. I would greatly appreciate any input on how I can resolve this issue!
def numToBinary(k, n):
''' converts number to binary number bit size k'''
def binary(n):
if n == 0:
return ''
elif n%2 == 1:
return binary(n/2)+'1'
else:
return binary(n/2)+ '0'
temp = binary(n)
if len(temp) <= k:
answer = '0' * (k - len(temp)) + temp
elif len(temp) > k:
answer = temp[-k:]
return answer
print (numToBinary(6, 10))
You need floor division, double /, in python3 / does truediv so you are getting floats from n/2:
def binary(n):
if n == 0:
return ''
elif n%2 == 1:
return binary(n//2) + '1' # // floor
else:
return binary(n//2)+ '0' # // floor
Once you make the change, it will work fine:
In [50]: numToBinary(6, 10)
Out[50]: '001010'
You can also use else in place of the elif, if the len of temp is not <= then it has to be greater than:
def numToBinary(k, n):
''' converts number to binary number bit size k'''
def binary(n):
if n == 0:
return ''
elif n % 2 == 1:
return binary(n//2)+'1'
else:
return binary(n//2) + '0'
temp = binary(n)
if len(temp) <= k:
answer = '0' * (k - len(temp)) + temp
else:
answer = temp[-k:]
return answer
If you wanted to see exactly what was happening you should put a print in you own code, if you added a print(n) in binary you would see a lot of output like:
5.125332723668738e-143
2.562666361834369e-143
1.2813331809171846e-143
6.406665904585923e-144
3.2033329522929615e-144
Which meant you eventually hit the recursion limit.

Resources