0

Here is a code that finds the value of the function T given by the recurrence relation for a given value of n:

def T(n):
  if n <= 0:
    return 1
  else:
    return T(n-1) + (n-1) * T(n-2)
    
print T(3)

#output
2

However, the code invokes the function T twice. I have added the print statement before the second return to show this:

def T(n):
  if n <= 0:
    return 1
  else:
    print (T(n-1) + (n-1) * T(n-2))
    return T(n-1) + (n-1) * T(n-2)
    
print T(3)

#output
1
2
1
2

Is there an efficient way of invoking the function T only once? I'm using Python 2. I'd like something short and simple, nothing too complicated.

  • 2
    Unrelated, but please use python3 – OneCricketeer Feb 20 '21 at 20:16
  • 1
    Pass an argument that is less than or equal to zero. What exactly do you expect from a recursive function? – duffymo Feb 20 '21 at 20:17
  • 1
    It invokes `T` *four* times, not two: twice each in the `print` and the `return`. Is your problem with the extra output? If so, then quit printing intermediate results from within the recursive function. You haven't explained what you're *really* trying to achieve. – Prune Feb 20 '21 at 20:18
  • @OneCricketeer - I am currently having problems with the Python 3 software that I'm using which is why I'm using Python 2 for the time being. –  Feb 20 '21 at 20:18
  • 1
    What kind of problems? Your code runs the exact same in python3 if you simply fixed the print statements – OneCricketeer Feb 20 '21 at 20:20
  • @OneCricketeer - I've stated that I'm using Python 2 so that users don't answer the question with functions that aren't compatible with python 2. –  Feb 20 '21 at 20:24
  • @Prune - I have edited my question. Is it clear now? –  Feb 20 '21 at 20:26

2 Answers2

3

You're going to call T 2^(n-1) times, for n >1, and there is no way to reduce that to only once without removing the recursion.

If you meant to say that you want to reduce the repetitive calls, such as T(3) calls T(2) and T(1) while T(2) also calls T(1), then you need to use a process called memoization

For example, using a dictionary of inputs to results.

seen = dict() 

def T(n):
  if n <= 0:
    return 1
  else:
    if n in seen:
        return seen[n] 
    else:
        result = T(n-1) + (n-1) * T(n-2)
        seen[n] = result
        return result 

print(T(3))
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • Could you explain what the `dict()` function does in this context? –  Feb 20 '21 at 20:35
  • 1
    Same as `T.cache = {}`. Defines an empty dictionary – OneCricketeer Feb 20 '21 at 20:35
  • 1
    I think this is good but I think memoization on the function would be cleaner (https://stackoverflow.com/questions/1988804/what-is-memoization-and-how-can-i-use-it-in-python) – jason m Feb 20 '21 at 21:02
1

You can redefine the function from T(n) = T(n-1) + (n-1)*T(n-2) to T(n+1) = T(n) + n*T(n-1) which will allow the recursion to move forward rather than backward provided you give it the current n and previous values. By only needing the previous value instead of the two previous values, the recursive progression is easier to grasp.

def T(N,n=1,Tm=1,Tn=1):  # n,Tm,Tn represent n,T(n-1),T(n)
    if n>N: return Tm    # stop at n=N+1 and return T(n-1)
    return T(N,n+1,Tn,Tn+n*Tm)

note: the function returns a when n>N in order to cover the case where N is zero.

Actually, this could also have been written without transposing the function by moving the stop condition to N+2 instead of N+1:

def T(N,n=2,Tn_2=1,Tn_1=1):   # n,Tn_2,Tn_1 represent n,T(n-2),T(n-1)
    if n==N+2: return Tn_2    # stop at n=N+2 and return T(n-2)
    return T(N,n+1,Tn_1,Tn_1+(n-1)*Tn_2)

which can be further simplified to:

def T(N,n=1,a=1,b=1): return T(N-1,n+1,b,a*n+b) if N else a
Alain T.
  • 40,517
  • 4
  • 31
  • 51
  • Also, could you explain the a, b, and c part of your code? This might just be the code I was looking for... –  Feb 20 '21 at 20:58
  • Changed the parameter names and added comments to better convey what's going on. – Alain T. Feb 20 '21 at 21:05
  • Also, why are the a,b, and n values set to 1? –  Feb 20 '21 at 21:12
  • Those are the initial states that correspond to T(0) – Alain T. Feb 20 '21 at 21:12
  • If I want to check each step of the recursion process, how do I do this? –  Feb 21 '21 at 03:09
  • 1
    You can print n, a and b at the beginning of the function – Alain T. Feb 21 '21 at 03:10
  • I'm sorry for asking so many questions, but is it possible for you to explain this in a bit more detail? "provided you give it the current n and previous values. By only needing the previous value instead of the two previous values, the recursive progression is easier to grasp." –  Feb 21 '21 at 03:40
  • 1
    What I meant by this is that the values we carry as parameters only need to represent T(n) and T(n-1) instead of T(n-1) and T(n-2) which would require that we define T(-1) and T(-2) at some point to cover the case of T(0) and T(1). By starting with the values of T(0) and T(1) and exiting at n>N, we don't need to define values for negative Ns. – Alain T. Feb 21 '21 at 04:00