text: import random
  import numpy as np
  
  def cluster_points(X, mu):
      clusters  = {}
      for x in X:
          bestmukey = min([(i[0], np.linalg.norm(x-mu[i[0]])) \
                      for i in enumerate(mu)], key=lambda t:t[1])[0]
          try:
              clusters[bestmukey].append(x)
          except KeyError:
              clusters[bestmukey] = [x]
      return clusters
  
  def reevaluate_centers(mu, clusters):
      newmu = []
      keys = sorted(clusters.keys())
      for k in keys:
          newmu.append(np.mean(clusters[k], axis = 0))
      return newmu
  
  def has_converged(mu, oldmu):
      if set([tuple(a) for a in mu]) == set([tuple(a) for a in oldmu]):
          return True
      return False
  
  def find_clusters(X, K):
      # Initialize to K random centers
      oldmu = random.sample(X, K)
      mu = random.sample(X, K)
      while not has_converged(mu, oldmu):
          oldmu = mu
          # Assign all points in X to clusters
          clusters = cluster_points(X, mu)
          # Reevaluate centers
          mu = reevaluate_centers(oldmu, clusters)
      return(mu, clusters)
  
  X = np.array([(random.uniform(-1, 1), random.uniform(-1, 1), random.uniform(-1, 1)) for i in range(20)])
  print X
  mu, clusters = find_clusters(X, 3)
  print mu
  
  