0

I was wondering if someone could help me rewrite this code as non-recursive so it can compute higher numbers, my current code looks like this:

def T(n):
    if n < 3:
        return n
    return T(n - 1) + 2 * T(n - 2) - T(n - 3)

The function is designed for the purpose of arithmetic where T(0) = 0, T(1) = 1, T(2) = 2, T(3) = 4, T(5) = 7 etc...

I want to be able to compute values as high as T(1000) for example, I didn't know if there was a simplistic way to rewrite the code or if it would just be a case of computing the values? Any help would be appreciated, I'm currently getting the error 'maximum recursion depth exceeded'

ThomasL123
  • 25
  • 4
  • Please state what you're trying to do? We can hardly help if we don't know what the code does. – Emmanuel Mar 25 '22 at 15:19
  • Sorry will add into the main body of the question now! – ThomasL123 Mar 25 '22 at 15:20
  • it is a linear 3d order differential equation... you can handle it as eigenvalue-vector problem which solution will be _explicit_ and not recursive – cards Mar 25 '22 at 15:22

3 Answers3

4

Use a "rolling" method where you keep track of the last three results and as you add the new result, you also kick the oldest:

def T(n):
    if n < 3:
        return n
    a, b, c = 0, 1, 2
    for i in range(2, n):
        a, b, c = b, c, c + 2*b - a
    return c
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thanks! Is there anyway to count how many times T(n) is called for any n? – ThomasL123 Mar 25 '22 at 15:46
  • Was just confused as obviously there's multiple T(n) being called each time? – ThomasL123 Mar 25 '22 at 15:48
  • In this version there is no recursion, so that count is always 1. In the recursive version (without caching), the number of calls has an exponential order in terms of `n`. But they don't all count towards filling the call stack, as some calls will finish before others will start. The use of the call stack in the recursive version is O(n). – trincot Mar 25 '22 at 15:56
1

There is a decorator for caching the function values so you can use your function with no modification:

from functools import lru_cache
@lru_cache(maxsize=None)
def T(n):
    if n < 3:
        return n
    return T(n - 1) + 2 * T(n - 2) - T(n - 3)

from python 3.9 onwards:

from functools import cache
@cache

Then you can run:

T(1000)

And will finish the execution extremely fast without any modification.

Ziur Olpa
  • 1,839
  • 1
  • 12
  • 27
  • 1
    But this doesn't fix the issue of too many recursions, which is what OP asked about! – Pranav Hosangadi Mar 25 '22 at 15:27
  • True, is not the best solution I guess, and also lru_cache may save non necessary information, but there is no real recursion so you can change the recursion limit if you want. But I thought is still a nice approach for the problem. – Ziur Olpa Mar 25 '22 at 15:36
1

It would be better to use dynamic programming.

def t(n):
    if n <3:
        return n
    temp = [0] * (n +1)
    temp[1], temp [2] = 1,2
    for i in range(3,n+1,1):
        temp[i] = temp[i - 1] + 2 * temp[i - 2] - temp[i - 3]
    return temp[n]