code: 
  """simple docstring"""
  import warnings
  
  import numpy as np
  import pandas as pd
  from matplotlib import pyplot as plt
  from sklearn.metrics import pairwise_distances
  
  warnings.filterwarnings('''ignore''')
  
  __magic_name__		       =				"""K-MEANS-CLUST/ """
  
  
  
  
  def     __lowerCamelCase  (		UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__=None      ):
  
  
  	"""simple docstring"""
  
  
  
  
  
  
  	if seed is not None:  # useful for obtaining consistent results
  		np.random.seed(UpperCamelCase__      )
  	_UpperCAmelCase =						data.shape[0]  # number of data points
  
  	# Pick K indices from range [0, N).
  	_UpperCAmelCase =						np.random.randint(0				,     UpperCamelCase__				,     UpperCamelCase__      )
  
  	# Keep centroids as dense format, as many entries will be nonzero due to averaging.
  	# As long as at least one document in a cluster contains a word,
  	# it will carry a nonzero weight in the TF-IDF vector of the centroid.
  	_UpperCAmelCase =						data[rand_indices, :]
  
  	return centroids
  
  
  
  
  def     __lowerCamelCase  (		UpperCamelCase__				,     UpperCamelCase__      ):
  
  
  	"""simple docstring"""
  
  
  
  
  
  
  	return pairwise_distances(UpperCamelCase__				,     UpperCamelCase__				,     metric="euclidean"      )
  
  
  
  
  def     __lowerCamelCase  (		UpperCamelCase__				,     UpperCamelCase__      ):
  
  
  	"""simple docstring"""
  
  
  
  
  
  
  	_UpperCAmelCase =						centroid_pairwise_dist(UpperCamelCase__				,     UpperCamelCase__      )
  
  	# Compute cluster assignments for each data point:
  	# Fill in the blank (RHS only)
  	_UpperCAmelCase =						np.argmin(UpperCamelCase__				,     axis=1      )
  
  	return cluster_assignment
  
  
  
  
  def     __lowerCamelCase  (		UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__      ):
  
  
  	"""simple docstring"""
  
  
  
  
  
  
  	_UpperCAmelCase =						[]
  	for i in range(UpperCamelCase__      ):
  		# Select all data points that belong to cluster i. Fill in the blank (RHS only)
  		_UpperCAmelCase =						data[cluster_assignment == i]
  		# Compute the mean of the data points. Fill in the blank (RHS only)
  		_UpperCAmelCase =						member_data_points.mean(axis=0      )
  		new_centroids.append(UpperCamelCase__      )
  	_UpperCAmelCase =						np.array(UpperCamelCase__      )
  
  	return new_centroids
  
  
  
  
  def     __lowerCamelCase  (		UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__      ):
  
  
  	"""simple docstring"""
  
  
  
  
  
  
  	_UpperCAmelCase =						0.0
  	for i in range(UpperCamelCase__      ):
  		# Select all data points that belong to cluster i. Fill in the blank (RHS only)
  		_UpperCAmelCase =						data[cluster_assignment == i, :]
  
  		if member_data_points.shape[0] > 0:  # check if i-th cluster is non-empty
  			# Compute distances from centroid to data points (RHS only)
  			_UpperCAmelCase =						pairwise_distances(
  			    UpperCamelCase__				,     [centroids[i]]				,     metric="euclidean"      )
  			_UpperCAmelCase =						distances**2
  			heterogeneity += np.sum(UpperCamelCase__      )
  
  	return heterogeneity
  
  
  
  
  def     __lowerCamelCase  (		UpperCamelCase__				,     UpperCamelCase__      ):
  
  
  	"""simple docstring"""
  
  
  
  
  
  
  	plt.figure(figsize=(7, 4)      )
  	plt.plot(UpperCamelCase__				,     linewidth=4      )
  	plt.xlabel("# Iterations"      )
  	plt.ylabel("Heterogeneity"      )
  	plt.title(f"Heterogeneity of clustering over time, K={k:d}"      )
  	plt.rcParams.update({"font.size": 16}      )
  	plt.show()
  
  
  
  
  def     __lowerCamelCase  (		UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__=500				,     UpperCamelCase__=None				,     UpperCamelCase__=False      ):
  
  
  	"""simple docstring"""
  
  
  
  
  
  
  	_UpperCAmelCase =						initial_centroids[:]
  	_UpperCAmelCase =						None
  
  	for itr in range(UpperCamelCase__      ):
  		if verbose:
  			print(UpperCamelCase__				,     end=""      )
  
  		# 1. Make cluster assignments using nearest centroids
  		_UpperCAmelCase =						assign_clusters(UpperCamelCase__				,     UpperCamelCase__      )
  
  		# 2. Compute a new centroid for each of the k clusters, averaging all data
  		#    points assigned to that cluster.
  		_UpperCAmelCase =						revise_centroids(UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__      )
  
  		# Check for convergence: if none of the assignments changed, stop
  		if (
  		    prev_cluster_assignment is not None
  		    and (prev_cluster_assignment == cluster_assignment).all()
  		):
  			break
  
  		# Print number of new assignments
  		if prev_cluster_assignment is not None:
  			_UpperCAmelCase =						np.sum(prev_cluster_assignment != cluster_assignment      )
  			if verbose:
  				print(
  				    f"    {num_changed:5d} elements changed their cluster assignment."      )
  
          # Record heterogeneity convergence metric
  		if record_heterogeneity is not None:
  			# YOUR CODE HERE
  			_UpperCAmelCase =						compute_heterogeneity(UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__      )
  			record_heterogeneity.append(UpperCamelCase__      )
  
  		_UpperCAmelCase =						cluster_assignment[:]
  
  	return centroids, cluster_assignment
  
  
  # Mock test below
  if False:  # change to true to run this test case.
  	from sklearn import datasets as ds
  
  	__magic_name__		       =				ds.load_iris()
  	__magic_name__		       =				3
  	__magic_name__		       =				[]
  	__magic_name__		       =				get_initial_centroids(dataset['''data'''], k, seed=0)
  	__magic_name__		       =				kmeans(
  	    dataset['''data'''],
  	    k,
  	    initial_centroids,
  	    maxiter=4_00,
  	    record_heterogeneity=heterogeneity,
  	    verbose=True,
  	)
  	plot_heterogeneity(heterogeneity, k)
  
  
  
  
  def     __lowerCamelCase  (		UpperCamelCase__				,     UpperCamelCase__				,     UpperCamelCase__=None      ):
  
  
  	"""simple docstring"""
  
  
  
  
  
  
  	if fill_missing_report:
  		_UpperCAmelCase =						df.fillna(value=UpperCamelCase__      )
  	_UpperCAmelCase =						1
  	_UpperCAmelCase =						df.select_dtypes(np.number      ).columns
  	_UpperCAmelCase =						(
  	    df.groupby(["Cluster"]      )[  # construct report dataframe
  	        numeric_cols
  	    ]  # group by cluster number
  	    .agg(
  	        [
  	            ("sum", np.sum),
  	            ("mean_with_zeros", lambda UpperCamelCase__      : np.mean(np.nan_to_num(UpperCamelCase__      )      )),
  	            ("mean_without_zeros", lambda UpperCamelCase__      : x.replace(0				,     np.NaN      ).mean()),
  	            (
  	                "mean_25-75",
  	                lambda UpperCamelCase__      : np.mean(
  	                    np.nan_to_num(
  	                        sorted(UpperCamelCase__      )[
  	                            round(len(UpperCamelCase__      ) * 25 / 100      ) : round(len(UpperCamelCase__      ) * 75 / 100      )
  	                        ]      )      ),
  	            ),
  	            ("mean_with_na", np.mean),
  	            ("min", lambda UpperCamelCase__      : x.min()),
  	            ("5%", lambda UpperCamelCase__      : x.quantile(0.05      )),
  	            ("25%", lambda UpperCamelCase__      : x.quantile(0.25      )),
  	            ("50%", lambda UpperCamelCase__      : x.quantile(0.50      )),
  	            ("75%", lambda UpperCamelCase__      : x.quantile(0.75      )),
  	            ("95%", lambda UpperCamelCase__      : x.quantile(0.95      )),
  	            ("max", lambda UpperCamelCase__      : x.max()),
  	            ("count", lambda UpperCamelCase__      : x.count()),
  	            ("stdev", lambda UpperCamelCase__      : x.std()),
  	            ("mode", lambda UpperCamelCase__      : x.mode()[0]),
  	            ("median", lambda UpperCamelCase__      : x.median()),
  	            ("# > 0", lambda UpperCamelCase__      : (x > 0).sum()),
  	        ]      )
  	    .T.reset_index()
  	    .rename(index=UpperCamelCase__				,     columns={"level_0": "Features", "level_1": "Type"}      )
  	)  # rename columns
  	# calculate the size of cluster(count of clientID's)
  	_UpperCAmelCase =						report[
  	    (report["Features"] == "dummy") & (report["Type"] == "count")
  	].copy()  # avoid SettingWithCopyWarning
  	_UpperCAmelCase =						(
  	    "ClusterSize"  # rename created cluster df to match report column names
  	)
  	_UpperCAmelCase =						"# of Customers"
  	_UpperCAmelCase =						pd.DataFrame(
  	    clustersize.iloc[:, 2:].values
  	    / clustersize.iloc[:, 2:].values.sum()      )
  	_UpperCAmelCase =						"% of Customers"  # rename created cluster df to match report column names
  	_UpperCAmelCase =						"ClusterProportion"
  	_UpperCAmelCase =						clusterproportion.columns.tolist()
  	_UpperCAmelCase =						cols[-2:] + cols[:-2]
  	_UpperCAmelCase =						clusterproportion[cols]  # rearrange columns to match report
  	_UpperCAmelCase =						report.columns
  	_UpperCAmelCase =						pd.DataFrame(
  	    abs(
  	        report[report["Type"] == "count"].iloc[:, 2:].values
  	        - clustersize.iloc[:, 2:].values      )      )  # generating df with count of nan values
  	_UpperCAmelCase =						0
  	_UpperCAmelCase =						"# of nan"
  	_UpperCAmelCase =						report[
  	    report["Type"] == "count"
  	].Features.tolist()  # filling values in order to match report
  	_UpperCAmelCase =						a.columns.tolist()
  	_UpperCAmelCase =						cols[-2:] + cols[:-2]
  	_UpperCAmelCase =						a[cols]  # rearrange columns to match report
  	_UpperCAmelCase =						report.columns  # rename columns to match report
  	_UpperCAmelCase =						report.drop(
  	    report[report.Type == "count"].index      )  # drop count values except cluster size
  	_UpperCAmelCase =						pd.concat(
  	    [report, a, clustersize, clusterproportion]				,     axis=0      )  # concat report with clustert size and nan values
  	_UpperCAmelCase =						report["Features"].isin(UpperCamelCase__      )
  	_UpperCAmelCase =						report.columns.tolist()
  	_UpperCAmelCase =						cols[0:2] + cols[-1:] + cols[2:-1]
  	_UpperCAmelCase =						report[cols]
  	_UpperCAmelCase =						{
  	    "ClusterSize": 9,
  	    "ClusterProportion": 8,
  	    "mean_with_zeros": 7,
  	    "mean_with_na": 6,
  	    "max": 5,
  	    "50%": 4,
  	    "min": 3,
  	    "25%": 2,
  	    "75%": 1,
  	    "# of nan": 0,
  	    "# > 0": -1,
  	    "sum_with_na": -2,
  	}
  	_UpperCAmelCase =						(
  	    report.assign(
  	        Sortera=lambda UpperCamelCase__      : x.Type.map(UpperCamelCase__      )				,     Sortera=lambda UpperCamelCase__      : list(reversed(range(len(UpperCamelCase__      )      )      )      )				,     )
  	    .sort_values(["Sorter1", "Mark", "Sorter2"]				,     ascending=UpperCamelCase__      )
  	    .drop(["Sorter1", "Sorter2"]				,     axis=1      )
  	)
  	_UpperCAmelCase =						""
  	_UpperCAmelCase =						report.reset_index()
  	_UpperCAmelCase =						report.drop(columns=["index"]      )
  	return report
  
  
  if __name__ == "__main__":
  	import doctest
  
  	doctest.testmod()
  
  
  
  
  
style_context: 
  """simple docstring"""
  def     __lowerCamelCase  (		UpperCamelCase__ = 400_0000      ):
  
  
  	"""simple docstring"""
  
  
  
  
  
  
  	_UpperCAmelCase =						1
  	_UpperCAmelCase =						2
  	_UpperCAmelCase =						0
  	while j <= n:
  		if j % 2 == 0:
  			total += j
  		_UpperCAmelCase ,      _UpperCAmelCase =						j, i + j
  
  	return total
  
  
  if __name__ == "__main__":
  			print(f'''{solution() = }''')
  
  
  
  
  