The assignment is to write a recursive function that receives 2 whole non-negative numbers b, x
, and returns True
if there's a natural integer n
so that b**n=x
and False
if not. I'm not allowed to use any math operators or loops, except % to determine if a number is even or odd.
but i do have external functions that i can use. Which can add 2 numbers, multiply 2 numbers, and divides a number by 2. also i can write helper function that i can use in the main function.
this is what i got so far, but it only works if b
is in the form of 2^y
(2,4,8,16 etc)
def is_power(b, x):
if b == x:
return True
if b > x:
return False
return is_power(add(b, b), x) # the func 'add' just adds 2 numbers
Furthermore, the complexity needs to be O(logb * logx)
Thank you.
CodePudding user response:
You can essentially keep multiplying b
by b
until you reach, or pass, n
.
A recursive implementation of this, using a helper function, could look something like this:
def is_power(b, x):
if b == 1: # Check special case
return x == 1
return helper(1, b, x)
def helper(counter, b, x):
if counter == x:
return True
elif counter > x:
return False
else:
return helper(mul(counter, b), b, x) # mul is our special multiplication function
CodePudding user response:
Use the function you say you can use to multiply 2 numbers like:
power = False
result = b
while result < x:
result = yourMultiplyFunction(b,b)
if result == x:
power = True
break
print(power)
Question was EDITTED (can't use loops):
def powerOf(x,b):
if (b == 1) and (x == 1):
return True
elif ( b==1 ) or (x == 1):
return False
if yourMultiplyFunction(b, b) < x:
return powerOf(x, yourMultiplyFunction(b, b))
elif yourMultiplyFunction(b, b) > x:
return False
return True
CodePudding user response:
A solution that is O(logb * logx) would be slower than a naive sequential search
You can get O(logx) by simply doing this:
def is_power(b,x,bn=1):
if bn == x: return True
if bn > x: return False
return is_power(b,x,bn*b)
I suspect that the objective is to go faster than O(logx) and that the complexity requirement should be something like O(log(logx/logb)^2) which is equivalent to O(log(n)*log(n)).
To get a O(log(n)*log(n)) solution, you can convert the problem into a binary search by implementing a helper function to raise a number to a given power in O(log(n)) time and use it in the O(log(n)) search logic.
def raise_power(b,n): # recursive b^n O(logN)
if not n: return 1 # b^0 = 1
if n%2: return b*raise_power(b*b,n//2) # binary decomposition
return raise_power(b*b,n//2) # of power over base
def max_power(b,x):
return 2*max_power(b*b,x) if b<x else 1 # double n until b^n >= x
def is_power(b,x,minp=0,maxp=None): # bin-search on range minp..maxp
if maxp is None: maxp = max_power(b,x) # determine higher bound
if minp>maxp: return False # no matching power
n = (minp maxp)//2 # middle of exponent range
bn = raise_power(b,n) # compute power
if bn == x: return True # match found
if bn > x: return is_power(b,x,minp,n-1) # look in lower sub-range
return is_power(b,x,n 1,maxp) # look in upper sub-range
Note that you will need to convert the *, and //2 operations to their equivalent external functions in order to meet the requirements of your assignment