def cube(x):
    return x * x * x
def compose(f, g):
    return lambda x: f(g(x))
def repeated(f, n):
    return (lambda x: x) if n == 0 else compose(f, repeated(f, n - 1))
dx = 0.00001
def smooth(f):
    return lambda x: (f(x - dx) + f(x) + f(x + dx)) / 3
def n_fold_smooth(f, n):
    return repeated(smooth, n)(f)

print(n_fold_smooth(cube, 5)(4))

# expected: 64.00000000399997
