Home > OS >  recursively calculate if x is power of b
recursively calculate if x is power of b

Time:11-25

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

  • Related