input: Write a function to perform k-means clustering on a given dataset. The function should initialize centroids randomly, assign each data point to the nearest centroid, and update the centroids until convergence. The function should return the cluster assignments and the final centroids. If the dataset is empty, return None for both cluster assignments and centroids.
  
  def kmeans(k, data):
      if len(data) == 0:
          return None, None
      centroids = data[np.random.randint(low=0, high=len(data), size=k)]
      prev_centroids = np.zeros(centroids.shape)
      clusters = np.zeros(len(data))
      distances = np.zeros((len(data), k))
      while not np.allclose(centroids, prev_centroids):
          prev_centroids = centroids
          for idx, centroid in enumerate(centroids):
              distances[:, idx] = np.linalg.norm(data - centroid, axis=1)
          clusters = np.argmin(distances, axis=1)
          for idx in range(k):
              centroids[idx] = np.mean(data[clusters == idx], axis=0)
      return clusters, centroids
      
  assert kmeans(3, np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]]))[0] is not None
  assert kmeans(3, np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]]))[1] is not None
  assert kmeans(1, np.array([])) == (None, None)
output: def kmeans(k, data):
      if len(data) == 0:
          return None, None
      centroids = data[np.random.randint(low=0, high=len(data), size=k)]
      prev_centroids = np.zeros(centroids.shape)
      clusters = np.zeros(len(data))
      distances = np.zeros((len(data), k))
      while not np.allclose(centroids, prev_centroids):
          prev_centroids = centroids
          for idx, centroid in enumerate(centroids):
              distances[:, idx] = np.linalg.norm(data - centroid, axis=1)
          clusters = np.argmin(distances, axis=1)
          for idx in range(k):
              centroids[idx] = np.mean(data[clusters == idx], axis=0)
      return clusters, centroids