I implemented the brute force solution, then realized that the solutions become cyclical starting at n = 516. Since the cycle length is just 2, all I needed to do was return the sum of those two numbers.
Use of the decimal module isn’t necessary. I initially used it to ensure that I was getting accurate values. However for the final answer, the only reason why I kept returning a decimal.Decimal was to make sure the tests pass.
import decimal
c = decimal.Decimal('30.403243784')
e = decimal.Decimal('1e-9')
def memoize(fn):
_cache = {}
def wrap(n):
if n in _cache:
return _cache[n]
ret = fn(n)
_cache[n] = ret
return ret
return wrap
@memoize
def f(n):
return int(2**(c-n**2)) * e
@memoize
def u(n):
if n == 0:
return -1
return f(u(n-1))
def solve(n):
if n > 515:
return decimal.Decimal('1.029461839') + decimal.Decimal('0.681175878')
return u(n) + u(n+1)
if __name__ == '__main__':
import sys
n = eval(sys.argv[1])
print(solve(n))
import pytest, decimal
from problem import solve
_test_solve = (
(10**0, decimal.Decimal('1.711242148')),
(10**1, decimal.Decimal('1.710098289')),
(10**2, decimal.Decimal('1.710575329')),
(10**3, decimal.Decimal('1.710637717')),
(10**4, decimal.Decimal('1.710637717')),
(10**5, decimal.Decimal('1.710637717')),
(10**6, decimal.Decimal('1.710637717')),
)
@pytest.mark.parametrize('n,expect', _test_solve)
def test_solve(n, expect):
assert expect == solve(n)