input: Write a function to implement the Gradient Descent Algorithm, which is used to find the local minimum of a function by iteratively adjusting the parameters based on the gradient. The function should take as input an array of x values, an array of y values, a learning rate, and the number of iterations. The function should return the updated slope (m_curr) and intercept (b_curr) after the specified number of iterations.
  assert gradient_descent([1, 2, 3, 4], [1, 3, 5, 7]) == (1.9999999999999862, 0.9999999999998505)
  assert gradient_descent([1, 3, 5, 7], [2, 4, 6, 8]) == (1.9999999999999862, 0.9999999999999252)
  assert gradient_descent([1, 2, 3], [1, 4, 9]) == (2.800000000000062, 0.4000000000000822)
  assert gradient_descent([], []) == (0, 0)
output: def gradient_descent(x, y, learning_rate=0.01, num_iterations=1000):
      m_curr = 0
      b_curr = 0
      n = len(x)
      
      if n == 0:
          return (0, 0)
      
      for _ in range(num_iterations):
          y_predicted = m_curr * x + b_curr
          md = -(2/n) * sum(x * (y - y_predicted))
          bd = -(2/n) * sum(y - y_predicted)
          m_curr = m_curr - learning_rate * md
          b_curr = b_curr - learning_rate * bd
      
      return (m_curr, b_curr)