Search code examples
pythonfunctionwhile-loopgeneratortail-recursion

How to write a recursion function using 2 accumulators?


I'm new to Python and recursion is a foreign thing to me. For my assignment I have functions that involve tail recursion, a while loop, or a generator as specified by _t, _w, or _g if the function needs to be implemented using tail recursion, a while loop, or a generator.

My p functions and d functions produce the correct answers but I'm having issues with my c functions. I've included a picture of all of my functions to show what the c functions should look like. correct p functions incorrect c functions (NOTE: def c(n) was given to me so it is the only correct function so far correct d functions Here is the original problem information for all of the functions which also explains the base functions

My full code: def p(n): if n: return p(n-1) + 0.02*p(n-1) else: return 10000

#MUST be implemented with tail recursion
def p_t(n, acc=10000):
if n == 0:
    return acc
else:
    return p_t(n - 1, acc * 1.02)

#MUST be implemented with a WHILE LOOP
def p_w(n, acc=10000):
while n > 0:
    acc = acc * 1.02
    n = n - 1
return acc

#MUST be implemented with generator
def p_g():
p = 10000
yield p
while True:
   p = p + (0.02 * p)
   yield p

def c(n):
if n > 1:
    return 9*c(n-1) + 10**(n-1) - c(n-1)
else:
    return 9

#MUST be implemented with tail recursion
def c_t(n, acc1=9, acc2=0):
 if n == 1:
    return acc1
 else:
    return c_t(n - 1, 9 * acc1 + 10 ** (n - 2) - acc2, acc1)
    
#MUST be implemented with a WHILE LOOP
def c_w(n, acc1=9, acc2=0):
while n > 1:
    acc1, acc2 = 9 * acc1 + 10 * (n - 2) - acc2, acc1
    n = n - 1
return acc1

#MUST be implemented with generator
def c_g():
c = 9
yield c
i = 2
while True:
    c = 9 * c + 10 * (i - 1) - c
    yield c
    i = i + 1

def d(n):
if n:
    return 3*d(n-1) + 1
else:
    return 1

#MUST be implemented with tail recursion
def d_t(n, acc=1):
if n == 0:
    return acc
else:
    return d_t(n - 1, 3 * acc + 1)

#MUST be implemented with a WHILE LOOP 
def d_w(n, acc=1):
if n == 0: 
    return 1
else:
    x = 1
    while x <= n:
        acc = 3 * acc + 1
        x = x + 1
    return acc

#MUST be implemented with generator
def d_g():
d, n = 1, 1
yield d
while True:
    d = 3 * d + 1
    yield d
    n = n + 1

The test case for all the functions is:

#for i,j in zip(range(5),p_g()):
#     print(p(i),p_t(i),p_w(i),j)

# 10000 10000 10000 10000
# 10200.0 10200.0 10200.0 10200.0
# 10404.0 10404.0 10404.0 10404.0
# 10612.08 10612.08 10612.08 10612.08        
# 10824.3216 10824.3216 10824.3216 10824.3216

# for i,j in zip(range(1,7),c_g()):
#     print(c(i),c_t(i),c_w(i),j)

# 9 9 9 9
# 82 82 82 82
# 756 756 756 756
# 7048 7048 7048 7048
# 66384 66384 66384 66384
# 631072 631072 631072 631072


# for i,j in zip(range(5),d_g()):
#     print(d(i),d_t(i),d_w(i),j)
# 1 1 1 1
# 4 4 4 4
# 13 13 13 13
# 40 40 40 40
# 121 121 121 121

However for my c functions, instead of getting

#9 9 9 9
#82 82 82 82
# 756 756 756 756
# 7048 7048 7048 7048
# 66384 66384 66384 66384
# 631072 631072 631072 631072 

for all of the functions, mine are returning (the 0th position in each row is correct):

#9 9 9 9
#82 82 81 82
#756 811 810 676
#7048 14490 8089 5438
#66384 775962 79891 43544
#631072 64414531 781220 348402

Solution

  • you have 4 function named c.

    but each function is difference with other.

    in c_w and c_t uses big N first, so value is wrong

    and c_w and c_g is uses * instead of **

    so correct code like...

    def c(n):
        if n > 1:
            return 9 * c(n - 1) + 10 ** (n - 1) - c(n - 1)
        else:
            return 9
    
    
    # MUST be implemented with tail recursion
    def c_t(n, acc1=9, step=1):  # uses step to correct power
        if step <= n:
            return acc1
        else:
            return c_t(n, 9 * acc1 + 10 ** step - acc1, step + 1)
    
    
    # MUST be implemented with a WHILE LOOP
    def c_w(n, acc1=9):  # remove useless acc2 and use **
        iter = 1
        while iter < n:
            acc1 = 9 * acc1 + 10 ** iter - acc1
            iter = iter + 1
        return acc1
    
    
    # MUST be implemented with generator
    def c_g():  # uses **
        res = 9
        yield res
        i = 1
        while True:
            res = 9 * res + 10 ** i - res
            yield res
            i = i + 1
    
    
    for i, j in zip(range(1, 7), c_g()):
        print(c(i), c_t(i), c_w(i), j)
    
    
    

    result is

    9 9 9 9
    82 82 82 82
    756 756 756 756
    7048 7048 7048 7048
    66384 66384 66384 66384
    631072 631072 631072 631072