Creating a recursive function that removes odd digits of an integer - python

I just started working with recursive functions and I have to create a function that receives an integer and returns a new number that contains only the even digits. For example if it receives 23456, it should return 246. This is what I've tried:
def newInt(n):
dig = n % 10
if dig % 2 == 1:
return newInt(n//10)
elif dig % 2 == 0:
return str(n) + newInt(n//10)
print(newInt(32))
But I'm getting the following error:
RecursionError: maximum recursion depth exceeded in __instancecheck__
Any hints on what should I do to fix it?

You need a base case. There's also no need to convert any of the integers to strings. Here is a working version of newInt() that resolves both of these issues:
def newInt(n):
if not n:
return 0
dig = n % 10
if dig % 2 == 1:
return newInt(n // 10)
else:
return 10 * newInt(n // 10) + dig

Your issue is that you have no condition to stop recursion - every call to newInt results in another call. One way to stop would be to check if n is less than 10 and then just return n if it is even. For example:
def newInt(n):
if n < 10:
return n if n % 2 == 0 else 0
dig = n % 10
if dig % 2 == 1:
return newInt(n//10)
elif dig % 2 == 0:
return newInt(n//10) * 10 + dig
Note I have modified your function to return an integer rather than a string.

Here is a variant with divmod. Uncomment the print to see how it works:
def newInt(n):
d,r = divmod(n,10)
# print(n,d,r)
if d == 0:
return 0 if r%2 else r
if r % 2:
return newInt(d)
else:
return 10*newInt(d)+r
print(newInt(212033450))
Output: 22040

You don't even need to break out dig for each loop:
def newInt(n):
if n:
if n & 1:
return newInt(n // 10)
else:
return 10 * newInt(n // 10) + (n % 10)
return 0

This is a rewrite of #mozway's algortihm using Python 3.10 match..case syntax -
def newInt(n):
match divmod(n, 10):
case (0, r) if r & 1:
return 0
case (0, r):
return r
case (d, r) if r & 1:
return newInt(d)
case (d, r):
return 10 * newInt(d) + r
print(newInt(67120593306737201))
6200620
Note r & 1 is more efficient for testing if a number is even or odd. r % 2 performs division whereas & simply checks the first bit.

Related

Sum of Prime using Recursion in Python

The problem given is to determine whether two numbers m and n are prime or not, and if they are, give the sum of all prime numbers from m to n. I have already made a code for the first part:
def isPrime(n, i):
if n <= i:
return True if (n == 2) else False
if n % i == 0:
return False
if i * i > n:
return True
return isPrime(n, i + 1)
However, I don't know how to do the second part of the code. A clue that our professor gave to us was to call the first function in the second part of the code, like this:
def sumOfPrime(m, n):
**enter code here**
isPrime(m, 2)
isPrime(n, 2)
I've no idea how to know all the prime numbers from m to n. Also, we are only allowed to use recursion for this problem.
I assume your professor wants you to just test all numbers between m and n for primality, then add those that pass together.
def sumOfPrime(m, n):
if isPrime(m, 2) and isPrime(n, 2):
return sum(i for i in range(m, n + 1) if isPrime(i, 2))
Here is a fully recursive version:
def sumOfPrime(m,n):
if isPrime(n,2) and isPrime(m,2):
return sumOfPrimes(m,n)
def sumOfPrimes(m, n):
if m > n:
return 0
return (m if isPrime(m,2) else 0) + sumOfPrimes(m+1,n)
If only one function, maybe better with a nestet function:
def sumOfPrime(m,n):
def helper(m,n):
if m > n:
return 0
return (m if isPrime(m,2) else 0) + sumOfPrimes(m+1,n)
if isPrime(n,2) and isPrime(m,2):
return helper(m,n)
assert sumOfPrime(2,5) == 2 +3 + 5

python recursion (exponential)

Rapid exponentiation, I need to write an algorithm that can calculate n^b faster than n multiplications! The complexity of the algorithm will be O(logn).
I have a code, I was able to pass first 20 test (I can't see the numbers), but I can't improve the algorithm to pass last 5 tests. Any suggestions how can I improve it?
def quick_power(x, n):
if n == 0:
return 1
elif n == 1:
return x
elif n == 2:
return x * x
elif n % 2 != 0:
return x * quick_power(x, n - 1)
elif n % 2 == 0:
return quick_power(x, n // 2) * quick_power(x, n // 2)
x = int(input())
n = int(input())
print(quick_power(x, n))
Your idea is in the right direction and your code is in principle not wrong. The point is that you need to distinguish two states, even and odd
if n is even: x^n = (x^(n/2))^2
if n is odd: x^n = x*x^(n-1)
, which you actually did.
Without knowing your last 5 tests, it is hard to figure out why it failed. But you can try the following simplified code.
def quick_power(x, n):
if n == 0:
return 1
elif n % 2 == 0:
return quick_power(x, n / 2)**2
else:
return x * quick_power(x, n-1)
print(quick_power(3, 5))

Maximum recursion depth exceeded in python

I am trying to make power function by recursion.
But I got run time error like Maximum recursion depth exceeded.
I will appreciate any help!!
Here is my code.
def fast_power(a,n):
if(n==0):
return 1
else:
if(n%2==0):
return fast_power(fast_power(a,n/2),2)
else:
return fast_power(fast_power(a,n/2),2)*a
You should use n // 2 instead of n / 2:
>>> 5 // 2
2
>>> 5 / 2
2.5
(At least in python3)
The problem is that once you end up with floats it takes quite a while before you end up at 0 by dividing by 2:
>>> from itertools import count
>>> n = 5
>>> for i in count():
... n /= 2
... if n == 0:
... break
...
>>> i
1076
So as you can see you would need more than 1000 recursive calls to reach 0 from 5, and that's above the default recursion limit. Besides: that algorithm is meant to be run with integer numbers.
This said I'd write that function as something like:
def fast_power(a, n):
if n == 0:
return 1
tmp = fast_power(a, n//2)
tmp *= tmp
return a*tmp if n%2 else tmp
Which produces:
>>> fast_power(2, 7)
128
>>> fast_power(3, 7)
2187
>>> fast_power(13, 793)
22755080661651301134628922146701289018723006552429644877562239367125245900453849234455323305726135714456994505688015462580473825073733493280791059868764599730367896428134533515091867511617127882942739592792838327544860344501784014930389049910558877662640122357152582905314163703803827192606896583114428235695115603966134132126414026659477774724471137498587452807465366378927445362356200526278861707511302663034996964296170951925219431414726359869227380059895627848341129113432175217372073248096983111394024987891966713095153672274972773169033889294808595643958156933979639791684384157282173718024930353085371267915606772545626201802945545406048262062221518066352534122215300640672237064641040065334712571485001684857748001990405649808379706945473443683240715198330842716984731885709953720968428395490414067791229792734370523603401019458798402338043728152982948501103056283713360751853
I believe #Bakuriu's explanation of the problem is incomplete. Not his reimplementation, but his explanation of your bug(s). You might convince yourself of this by replacing / with // in your original code and try:
fast_power(2, 2)
it still exceeds the stack. Try expanding the stack ten fold:
sys.setrecursionlimit(10000)
it still exceeds the stack. The reason is you also have an infinte loop:
if (n % 2 == 0):
return fast_power(..., 2)
Since 2 % 2 == 0, this simply keeps recursing forever. Adding another base case:
if n == 2:
return a * a
fixes the problem. A complete solution:
def fast_power(a, n):
if n == 0:
return 1
# if n == 1:
# return a
if n == 2:
return a * a
if n % 2 == 0:
return fast_power(fast_power(a, n // 2), 2)
return a * fast_power(fast_power(a, n // 2), 2)

How to check if the number can be represented prime power (nth root is prime or not)

I am trying this problem for a while but getting wrong answer again and again.
number can be very large <=2^2014.
22086. Prime Power Test
Explanation about my algorithm:
For a Given number I am checking if the number can be represented as form of prime power or not.
So the the maximum limit to check for prime power is log n base 2.
Finally problem reduced to finding nth root of a number and if it is prime we have our answer else check for all i till log (n base 2) and exit.
I have used all sort of optimizations and have tested enormous test-cases and for all my algorithm gives correct answer
but Judge says wrong answer.
Spoj have another similar problem with small constraints n<=10^18 for which I already got accepted with Python and C++(Best solver in c++)
Here is My python code Please suggest me if I am doing something wrong I am not very proficient in python so my algorithm is a bit lengthy. Thanks in advance.
My Algorithm:
import math
import sys
import fractions
import random
import decimal
write = sys.stdout.write
def sieve(n):
sqrtn = int(n**0.5)
sieve = [True] * (n+1)
sieve[0] = False
sieve[1] = False
for i in range(2, sqrtn+1):
if sieve[i]:
m = n//i - i
sieve[i*i:n+1:i] = [False] * (m+1)
return sieve
def gcd(a, b):
while b:
a, b = b, a%b
return a
def mr_pass(a, s, d, n):
a_to_power = pow(a, d, n)
if a_to_power == 1:
return True
for i in range(s-1):
if a_to_power == n - 1:
return True
a_to_power = (a_to_power * a_to_power) % n
return a_to_power == n - 1
isprime=sieve(1000000)
sprime= [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]
def smooth_num(n):
c=0
for a in sprime:
if(n%a==0):
c+=1
if(c>=2):
return True;
return False
def is_prime(n):
if(n<1000000):
return isprime[n]
if any((n % p) == 0 for p in sprime):
return False
if n==2:
return True
d = n - 1
s = 0
while d % 2 == 0:
d >>= 1
s += 1
for repeat in range(10):
a=random.randint(1,n-1)
if not mr_pass(a, s, d, n):
return False
return True
def iroot(n,k):
hi = 1
while pow(hi, k) < n:
hi *= 2
lo = hi // 2
while hi - lo > 1:
mid = (lo + hi) // 2
midToK = (mid**k)
if midToK < n:
lo = mid
elif n < midToK:
hi = mid
else:
return mid
if (hi**k) == n:
return hi
else:
return lo
def isqrt(x):
n = int(x)
if n == 0:
return 0
a, b = divmod(n.bit_length(), 2)
x = pow(2,(a+b))
while True:
y = (x + n//x)>>1
if y >= x:
return x
x = y
maxx=2**1024;minn=2**64
def nth_rootp(n,k):
return int(round(math.exp(math.log(n)/k),0))
def main():
for cs in range(int(input())):
n=int(sys.stdin.readline().strip())
if(smooth_num(n)):
write("Invalid order\n")
continue;
order = 0;m=0
power =int(math.log(n,2))
for i in range(1,power+1):
if(n<=maxx):
if i==1:m=n
elif(i==2):m=isqrt(n)
elif(i==4):m=isqrt(isqrt(n))
elif(i==8):m=isqrt(isqrt(isqrt(n)))
elif(i==16):m=isqrt(isqrt(isqrt(isqrt(n))))
elif(i==32):m=isqrt(isqrt(isqrt(isqrt(isqrt(n)))))
elif(i==64):m=isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(n))))))
elif(i==128):m=isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(n)))))))
elif(i==256):m=isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(n))))))))
else:m=int(nth_rootp(n,i))
else:
if i==1:m=n
elif i==2:m=isqrt(n)
elif(i==4):m=isqrt(isqrt(n))
elif(i==8):m=isqrt(isqrt(isqrt(n)))
elif(i==16):m=isqrt(isqrt(isqrt(isqrt(n))))
elif(i==32):m=isqrt(isqrt(isqrt(isqrt(isqrt(n)))))
elif(i==64):m=isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(n))))))
elif(i==128):m=isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(n)))))))
elif(i==256):m=isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(isqrt(n))))))))
else:m=iroot(n,i)
if m<2:
order=0
break
if(is_prime(m) and n==(m**i)):
write("%d %d\n"%(m,i))
order = 1
break
if(order==0):
write("Invalid order\n")
main()
I'm not going to read all that code, though I suspect the problem is floating-point inaccuracy. Here is my program to determine if a number n is a prime power; it returns the prime p and the power k:
# prime power predicate
from random import randint
from fractions import gcd
def findWitness(n, k=5): # miller-rabin
s, d = 0, n-1
while d % 2 == 0:
s, d = s+1, d/2
for i in range(k):
a = randint(2, n-1)
x = pow(a, d, n)
if x == 1 or x == n-1: continue
for r in range(1, s):
x = (x * x) % n
if x == 1: return a
if x == n-1: break
else: return a
return 0
# returns p,k such that n=p**k, or 0,0
# assumes n is an integer greater than 1
def primePower(n):
def checkP(n, p):
k = 0
while n > 1 and n % p == 0:
n, k = n / p, k + 1
if n == 1: return p, k
else: return 0, 0
if n % 2 == 0: return checkP(n, 2)
q = n
while True:
a = findWitness(q)
if a == 0: return checkP(n, q)
d = gcd(pow(a,q,n)-a, q)
if d == 1 or d == q: return 0, 0
q = d
The program uses Fermat's Little Theorem and exploits the witness a to the compositeness of n that is found by the Miller-Rabin algorithm. It is given as Algorithm 1.7.5 in Henri Cohen's book A Course in Computational Algebraic Number Theory. You can see the program in action at http://ideone.com/cNzQYr.
this is not really an answer, but I don't have enough space to write it as a comment.
So, if the problem still not solved, you may try the following function for nth_rootp, though it is a bit ugly (it is just a binary search to find the precise value of the function):
def nth_rootp(n,k):
r = int(round(math.log(n,2)/k))
left = 2**(r-1)
right = 2**(r+1)
if left**k == n:
return left
if right**k == n:
return right
while left**k < n and right**k > n:
tmp = (left + right)/2
if tmp**k == n:
return tmp
if tmp == left or tmp == right:
return tmp
if tmp**k < n:
left = tmp
else:
if tmp**k > n:
right = tmp
your code look like a little overcomplicated for this task, I will not bother to check it, but the thing you need are the following
is_prime, naturally
a prime generator, optional
calculate the nth root of a number in a precise way
for the first one I recommend the deterministic form of the Miller-Rabin test with a appropriate set of witness to guaranty a exact result until 1543267864443420616877677640751301 (1.543 x 1033) for even bigger numbers you can use the probabilistic one or use a bigger list of witness chosen at your criteria
with all that a template for the solution is as follow
import math
def is_prime(n):
...
def sieve(n):
"list of all primes p such that p<n"
...
def inthroot(x,n):
"calculate floor(x**(1/n))"
...
def is_a_power(n):
"return (a,b) if n=a**b otherwise throw ValueError"
for b in sieve( math.log2(n) +1 ):
a = inthroot(n,b)
if a**b == n:
return a,b
raise ValueError("is not a power")
def smooth_factorization(n):
"return (p,e) where p is prime and n = p**e if such value exists, otherwise throw ValueError"
e=1
p=n
while True:
try:
p,n = is_a_power(p)
e = e*n
except ValueError:
break
if is_prime(p):
return p,e
raise ValueError
def main():
for test in range( int(input()) ):
try:
p,e = smooth_factorization( int(input()) )
print(p,e)
except ValueError:
print("Invalid order")
main()
And the code above should be self explanatory
Filling the blacks
As you are familiar with Miller-Rabin test, I will only mention that if you are interested you can find a implementation of the determinist version here just update the list of witness and you are ready to go.
For the sieve, just change the one you are using to return a list with primes number like this for instance [ p for p,is_p in enumerate(sieve) if is_p ]
With those out of the way, the only thing left is calculate the nth root of the number and to do that in a precise way we need to get rip of that pesky floating point arithmetic that only produce headaches, and the answer is implement the Nth root algorithm using only integer arithmetic, which is pretty similar to the one of isqrt that you already use, I guide myself with the one made by Mark Dickinson for cube root and generalize it and I get this
def inthroot(A, n) :
"calculate floor( A**(1/n) )"
#https://en.wikipedia.org/wiki/Nth_root_algorithm
#https://en.wikipedia.org/wiki/Nth_root#nth_root_algorithm
#https://stackoverflow.com/questions/35254566/wrong-answer-in-spoj-cubert/35276426#35276426
#https://stackoverflow.com/questions/39560902/imprecise-results-of-logarithm-and-power-functions-in-python/39561633#39561633
if A<0:
if n%2 == 0:
raise ValueError
return - inthroot(-A,n)
if A==0:
return 0
n1 = n-1
if A.bit_length() < 1024: # float(n) safe from overflow
xk = int( round( pow(A,1.0/n) ) )
xk = ( n1*xk + A//pow(xk,n1) )//n # Ensure xk >= floor(nthroot(A)).
else:
xk = 1 << -(-A.bit_length()//n) # 1 << sum(divmod(A.bit_length(),n))
# power of 2 closer but greater than the nth root of A
while True:
sig = A // pow(xk,n1)
if xk <= sig:
return xk
xk = ( n1*xk + sig )//n
and with all the above you can solve the problem without inconvenient
from sympy.ntheory import factorint
q=int(input("Give me the number q="))
fact=factorint(q) #We factor the number q=p_1^{n_1}*p_2^{n_2}*...
p_1=list(fact.keys()) #We create a list from keys to be the the numbers p_1,p_2,...
n_1=list(fact.values()) #We create a list from values to be the the numbers n_1,n_2,...
p=int(p_1[0])
n=int(n_1[0])
if q!=p**n: #Check if the number q=p_{1}[0]**n_{1}[0]=p**n.
print("The number "+str(q)+" is not a prime power")
else:
print("The number "+str(q)+" is a prime power")
print("The prime number p="+str(p))
print("The natural number n="+str(n))

How to added up a variable with multiple values together in Python Recursion Function?

So I was studying recursion function online. And the one question asks me to write a function to add up a number's digits together. For example (1023) -> 1 + 0 + 2 + 3 = 6. I used % and // get get rid of a digit each time. However, I don't know how to add them up together. The closest I can get is to print out each digit. Can anyone help me solve it or give me a hint please?
def digitalSum(n):
if n < 10:
sum_total = n
print(sum_total)
else:
sum_total = n % 10
digitalSum((n - (n % 10))//10)
print(sum_total)
digitalSum(1213)
Your function should return the current digit plus the sum of the rest of the digits:
def digitalSum(n):
if n < 10: return n
return n % 10 + digitalSum(n // 10)
print digitalSum(1213)
For completeness, you can also handle negative numbers:
def digitalSum(n):
if n < 0: sign = -1
else: sign = 1
n = abs(n)
if n < 10: return n
return sign * (n % 10 + digitalSum(n // 10))
print digitalSum(1213)
A correct version of your function is as follows:
from math import log10
def sum_digits(n, i=None):
if i is None:
i = int(log10(abs(n)))
e = float(10**i)
a, b = (n / e), (abs(n) % e)
if i == 0:
return int(a)
else:
return int(a) + sum_digits(b, (i - 1))
print sum_digits(1234)
print sum_digits(-1234)
Example:
$ python -i foo.py
10
8
>>>
Updated: Updated to properly (IHMO) cope with negative numbers. e.g: -1234 == -1 + 2 + 3 + 4 == 8
NB: Whilst this answer has been accepted (Thank you) I really think that perreal's answer should have been accepted for simplicity and clarity.
Also note: that whilst my solution handles negative numbers and summing their respective digits, perreal clearly points out in our comments that there are ate least three different ways to interpret the summing of digits of a negative number.

Categories