input: Write a function to implement the Gradient Descent Algorithm. The function should take in the features (x), the target (y), a learning rate, and the number of iterations as parameters. It should return the final values of the slope (m) and the intercept (b). If the function runs successfully, it should print the values of the slope, intercept, and cost at each iteration.
  
  def gradient_descent(x, y, learning_rate=0.01, iterations=100):
      m_curr = b_curr = 0
      n = len(x)
      for i in range(iterations):
          y_predicted = m_curr * x + b_curr
          cost = (1/n) * sum([val**2 for val in (y-y_predicted)])
          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
          print ("m {}, b {}, cost {} iteration {}".format(m_curr,b_curr,cost, i))
      return m_curr, b_curr
  
  assert gradient_descent([1, 2, 3, 4, 5], [1, 4, 9, 16, 25], learning_rate=0.01, iterations=100) == (2.0, 0.0)
  assert gradient_descent([1, 2, 3], [2, 4, 6], learning_rate=0.01, iterations=50) == (2.0, 0.0)
  assert gradient_descent([], [], learning_rate=0.01, iterations=50) == (0.0, 0.0)
  assert gradient_descent([1, 2, 3, 4], [1, 4, 9, 16], learning_rate=0.02, iterations=200) == (3.0, 0.0)
  assert gradient_descent([1, 2, 3, 4, 5], [2, 4, 6, 8, 10], learning_rate=0.01, iterations=100) == (2.0, 0.0)
output: def gradient_descent(x, y, learning_rate=0.01, iterations=100):
      m_curr = b_curr = 0
      n = len(x)
      for i in range(iterations):
          y_predicted = m_curr * x + b_curr
          cost = (1/n) * sum([val**2 for val in (y-y_predicted)])
          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
          print ("m {}, b {}, cost {} iteration {}".format(m_curr,b_curr,cost, i))
      return m_curr, b_curr