def abs(x):
    return x if x >= 0 else - x
tolerance = 0.00001
def fixed_point(f, first_guess):
    def close_enough(x, y):
        return abs(x - y) < tolerance
    def try_with(guess):
        next = f(guess)
        return next if close_enough(guess, next) else try_with(next)
    return try_with(first_guess)
dx = 0.00001
def deriv(g):
    return lambda x: (g(x + dx) - g(x)) / dx
def newton_transform(g):
    return lambda x: x - g(x) / deriv(g)(x)
def newtons_method(g, guess):
    return fixed_point(newton_transform(g), guess)
def cube(x):
    return x * x * x
def square(x): return x * x
# cubic to be written by student; see EXERCISE 1.40
def cubic(a, b, c):
    return lambda x: cube(x) + a * square(x) + b * x + c

print(newtons_method(cubic(1, -4, 0), 1))

# expected: 1.5615528128102987
