return [v_i + step_size * direction_i for v_i, direction_i in zip(v, direction)]


def sum_of_squares_gradient(v):
    return [2 * v_i for v_i in v]

if isMain:
    # pick a random starting point
    v = [random.randint(-10, 10) for _ in range(3)]

    tolerance = .00000001

    while True:
        gradient = sum_of_squares_gradient(v)
        next_v = step(v, gradient, -0.01)
        if Ch4.distance(next_v, v) < tolerance:
            break
        v = next_v
    print("Approx solutions: ", v)

# But what should the step size be?


# This is a safe apply function, just in case we try a bad step size
def safe(f):
    """
        Return a new function that is the same as f, except
        that it outputs infinity whenever f produces an error
    """
    def safe_f(*args, **kwargs):
        try: