K-Means Clustering is an unsupervised machine
learning algorithm used to group data points into \(k\) distinct clusters. The algorithm
partitions a dataset into \(k\)
clusters by minimizing the variance within each cluster. It is commonly
used for pattern recognition, data compression, and finding structure in
data.
The key idea behind K-Means is to divide data points into clusters
such that data points in the same cluster are similar to each other,
while data points in different clusters are dissimilar.
The K-Means algorithm iteratively updates cluster centroids and
assigns data points to the nearest centroid based on the Euclidean
distance between the points and the centroids.
Steps of the K-Means Algorithm:
Choose the number of clusters \(k\).
Initialize: Randomly select \(k\) initial centroids.
Assign each data point to the nearest centroid
based on distance (typically Euclidean distance).
Update centroids by calculating the mean of all
points assigned to each cluster.
Repeat steps 3 and 4 until the centroids do not
change significantly (convergence).
Advantages:
Simple and efficient: K-Means is easy to
implement and works well with large datasets.
Scalable: It can handle a large number of
features and data points efficiently.
Flexible: It can adapt to different data
distributions and clusters.
Disadvantages:
Sensitive to the initial choice of centroids:
Different initializations can lead to different clusters (local
minima).
Requires choosing \(k\): The number of clusters \(k\) must be specified in advance.
Sensitive to outliers: Outliers can
significantly affect the cluster assignments.
Assumes spherical clusters: K-Means performs
best when clusters are circular or spherical, as it uses Euclidean
distance.
Applications:
Market segmentation: Grouping customers based on
purchasing behavior or demographic information.
Image compression: Reducing the number of colors
in an image by grouping pixels into color clusters.
Anomaly detection: Identifying outliers in
financial transactions or network traffic.
Pros:
Computationally fast and scalable.
Works well with large datasets.
Easy to interpret and visualize in low dimensions.
Cons:
Requires the number of clusters \(k\) to be pre-specified.
Struggles with non-convex or irregular-shaped clusters.
Sensitive to the scale of data and outliers.
K-Means Clustering Example in R
We will use K-Means to cluster data points based on two variables.
We’ll generate a dataset of random points and use the K-Means algorithm
to identify clusters.
Step 1: Create the Data
We’ll generate a dataset with two features (x and y) that can be
grouped into clusters.
# Load necessary library
set.seed(123)
# Generate random data points
x <- c(rnorm(50, mean = 1, sd = 0.5), rnorm(50, mean = 5, sd = 0.5), rnorm(50, mean = 9, sd = 0.5))
y <- c(rnorm(50, mean = 1, sd = 0.5), rnorm(50, mean = 5, sd = 0.5), rnorm(50, mean = 9, sd = 0.5))
# Combine into a data frame
data <- data.frame(x, y)
head(data)
Here, we generate 150 data points distributed around three centers:
(1, 1), (5, 5), and (9, 9).
Output (simplified):
K-means clustering with 3 clusters of sizes 50, 50, 50
Cluster means:
x y
1 1.052739 1.043346
2 9.034017 9.033384
3 4.963213 5.012003
Clustering vector:
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
...
Interpretation:
The algorithm has identified 3 clusters, each containing 50
points.
The cluster means (centroids) for the three
clusters are approximately (1,1), (5,5), and (9,9), which matches the
centers around which the data was generated.
The clustering vector indicates the cluster
assignment for each data point.
Step 3: Visualize the Clusters
We can visualize the results of K-Means clustering by plotting the
data points and coloring them based on their cluster assignment.
# Plot the data points and color them by cluster
plot(data$x, data$y, col = kmeans_result$cluster, pch = 19,
main = "K-Means Clustering Results",
xlab = "X", ylab = "Y")
# Add cluster centers to the plot
points(kmeans_result$centers[, 1], kmeans_result$centers[, 2], col = 1:3, pch = 8, cex = 2)

Interpretation:
The scatterplot shows the data points, with each point colored
based on its cluster assignment.
The large crosses represent the cluster centroids, showing where
the algorithm has placed the center of each cluster.
You can see that the K-Means algorithm has successfully grouped
the points into three clusters around their respective centers.
Choosing the Optimal Number of Clusters \(k\)
One common method for selecting the optimal number of clusters is the
Elbow Method, which involves plotting the total
within-cluster sum of squares (WSS) for different values of \(k\) and looking for an “elbow” point where
the WSS begins to decrease more slowly.
Step 4: Elbow Method to Determine \(k\)
We can compute the WSS for different values of \(k\) and plot the results to help determine
the optimal number of clusters.
# Compute within-cluster sum of squares (WSS) for different k values
wss <- sapply(1:10, function(k){
kmeans(data, centers = k)$tot.withinss
})
# Plot the Elbow Method
plot(1:10, wss, type = "b", pch = 19, frame = FALSE,
xlab = "Number of Clusters",
ylab = "Total Within-Cluster Sum of Squares",
main = "Elbow Method for Finding Optimal k")

Interpretation:
The Elbow Method plot shows the WSS for
different values of \(k\).
The point where the decrease in WSS becomes more gradual is the
“elbow” point, which suggests the optimal number of clusters.
In this case, the elbow typically occurs around \(k = 3\), confirming that 3 clusters is a
good choice for this dataset.
K-Means Algorithm Process Summary:
Choose \(k\), the number of
clusters.
Randomly initialize \(k\)
centroids.
Assign each point to the nearest centroid.
Recalculate the centroids based on the mean of points in each
cluster.
Repeat steps 3-4 until convergence.
Conclusion:
K-Means clustering is a powerful and widely-used unsupervised
learning algorithm for identifying patterns and groups in data. In R,
the kmeans()
function makes it easy to apply this algorithm
to your dataset, and visualizing the clusters can provide valuable
insights into the structure of the data.
LS0tDQp0aXRsZTogIkstTWVhbnMgQ2x1c3RlcmluZyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCg0KKipLLU1lYW5zIENsdXN0ZXJpbmcqKiBpcyBhbiB1bnN1cGVydmlzZWQgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gdXNlZCB0byBncm91cCBkYXRhIHBvaW50cyBpbnRvIFwoIGsgXCkgZGlzdGluY3QgY2x1c3RlcnMuIFRoZSBhbGdvcml0aG0gcGFydGl0aW9ucyBhIGRhdGFzZXQgaW50byBcKCBrIFwpIGNsdXN0ZXJzIGJ5IG1pbmltaXppbmcgdGhlIHZhcmlhbmNlIHdpdGhpbiBlYWNoIGNsdXN0ZXIuIEl0IGlzIGNvbW1vbmx5IHVzZWQgZm9yIHBhdHRlcm4gcmVjb2duaXRpb24sIGRhdGEgY29tcHJlc3Npb24sIGFuZCBmaW5kaW5nIHN0cnVjdHVyZSBpbiBkYXRhLg0KDQpUaGUga2V5IGlkZWEgYmVoaW5kIEstTWVhbnMgaXMgdG8gZGl2aWRlIGRhdGEgcG9pbnRzIGludG8gY2x1c3RlcnMgc3VjaCB0aGF0IGRhdGEgcG9pbnRzIGluIHRoZSBzYW1lIGNsdXN0ZXIgYXJlIHNpbWlsYXIgdG8gZWFjaCBvdGhlciwgd2hpbGUgZGF0YSBwb2ludHMgaW4gZGlmZmVyZW50IGNsdXN0ZXJzIGFyZSBkaXNzaW1pbGFyLg0KDQpUaGUgSy1NZWFucyBhbGdvcml0aG0gaXRlcmF0aXZlbHkgdXBkYXRlcyBjbHVzdGVyIGNlbnRyb2lkcyBhbmQgYXNzaWducyBkYXRhIHBvaW50cyB0byB0aGUgbmVhcmVzdCBjZW50cm9pZCBiYXNlZCBvbiB0aGUgRXVjbGlkZWFuIGRpc3RhbmNlIGJldHdlZW4gdGhlIHBvaW50cyBhbmQgdGhlIGNlbnRyb2lkcy4NCg0KIyMjIyAqKlN0ZXBzIG9mIHRoZSBLLU1lYW5zIEFsZ29yaXRobSoqOg0KDQoxLiAqKkNob29zZSB0aGUgbnVtYmVyIG9mIGNsdXN0ZXJzIFwoIGsgXCkqKi4NCg0KMi4gKipJbml0aWFsaXplKio6IFJhbmRvbWx5IHNlbGVjdCBcKCBrIFwpIGluaXRpYWwgY2VudHJvaWRzLg0KDQozLiAqKkFzc2lnbiBlYWNoIGRhdGEgcG9pbnQqKiB0byB0aGUgbmVhcmVzdCBjZW50cm9pZCBiYXNlZCBvbiBkaXN0YW5jZSAodHlwaWNhbGx5IEV1Y2xpZGVhbiBkaXN0YW5jZSkuDQoNCjQuICoqVXBkYXRlIGNlbnRyb2lkcyoqIGJ5IGNhbGN1bGF0aW5nIHRoZSBtZWFuIG9mIGFsbCBwb2ludHMgYXNzaWduZWQgdG8gZWFjaCBjbHVzdGVyLg0KDQo1LiAqKlJlcGVhdCBzdGVwcyAzIGFuZCA0KiogdW50aWwgdGhlIGNlbnRyb2lkcyBkbyBub3QgY2hhbmdlIHNpZ25pZmljYW50bHkgKGNvbnZlcmdlbmNlKS4NCg0KIyMjIyAqKkFkdmFudGFnZXMqKjoNCg0KLSAqKlNpbXBsZSBhbmQgZWZmaWNpZW50Kio6IEstTWVhbnMgaXMgZWFzeSB0byBpbXBsZW1lbnQgYW5kIHdvcmtzIHdlbGwgd2l0aCBsYXJnZSBkYXRhc2V0cy4NCg0KLSAqKlNjYWxhYmxlKio6IEl0IGNhbiBoYW5kbGUgYSBsYXJnZSBudW1iZXIgb2YgZmVhdHVyZXMgYW5kIGRhdGEgcG9pbnRzIGVmZmljaWVudGx5Lg0KDQotICoqRmxleGlibGUqKjogSXQgY2FuIGFkYXB0IHRvIGRpZmZlcmVudCBkYXRhIGRpc3RyaWJ1dGlvbnMgYW5kIGNsdXN0ZXJzLg0KDQojIyMjICoqRGlzYWR2YW50YWdlcyoqOg0KDQotICoqU2Vuc2l0aXZlIHRvIHRoZSBpbml0aWFsIGNob2ljZSBvZiBjZW50cm9pZHMqKjogRGlmZmVyZW50IGluaXRpYWxpemF0aW9ucyBjYW4gbGVhZCB0byBkaWZmZXJlbnQgY2x1c3RlcnMgKGxvY2FsIG1pbmltYSkuDQoNCi0gKipSZXF1aXJlcyBjaG9vc2luZyBcKCBrIFwpKio6IFRoZSBudW1iZXIgb2YgY2x1c3RlcnMgXCggayBcKSBtdXN0IGJlIHNwZWNpZmllZCBpbiBhZHZhbmNlLg0KDQotICoqU2Vuc2l0aXZlIHRvIG91dGxpZXJzKio6IE91dGxpZXJzIGNhbiBzaWduaWZpY2FudGx5IGFmZmVjdCB0aGUgY2x1c3RlciBhc3NpZ25tZW50cy4NCg0KLSAqKkFzc3VtZXMgc3BoZXJpY2FsIGNsdXN0ZXJzKio6IEstTWVhbnMgcGVyZm9ybXMgYmVzdCB3aGVuIGNsdXN0ZXJzIGFyZSBjaXJjdWxhciBvciBzcGhlcmljYWwsIGFzIGl0IHVzZXMgRXVjbGlkZWFuIGRpc3RhbmNlLg0KDQojIyMjICoqQXBwbGljYXRpb25zKio6DQoNCi0gKipNYXJrZXQgc2VnbWVudGF0aW9uKio6IEdyb3VwaW5nIGN1c3RvbWVycyBiYXNlZCBvbiBwdXJjaGFzaW5nIGJlaGF2aW9yIG9yIGRlbW9ncmFwaGljIGluZm9ybWF0aW9uLg0KDQotICoqSW1hZ2UgY29tcHJlc3Npb24qKjogUmVkdWNpbmcgdGhlIG51bWJlciBvZiBjb2xvcnMgaW4gYW4gaW1hZ2UgYnkgZ3JvdXBpbmcgcGl4ZWxzIGludG8gY29sb3IgY2x1c3RlcnMuDQoNCi0gKipBbm9tYWx5IGRldGVjdGlvbioqOiBJZGVudGlmeWluZyBvdXRsaWVycyBpbiBmaW5hbmNpYWwgdHJhbnNhY3Rpb25zIG9yIG5ldHdvcmsgdHJhZmZpYy4NCg0KIyMjIyAqKlByb3MqKjoNCg0KLSBDb21wdXRhdGlvbmFsbHkgZmFzdCBhbmQgc2NhbGFibGUuDQoNCi0gV29ya3Mgd2VsbCB3aXRoIGxhcmdlIGRhdGFzZXRzLg0KDQotIEVhc3kgdG8gaW50ZXJwcmV0IGFuZCB2aXN1YWxpemUgaW4gbG93IGRpbWVuc2lvbnMuDQoNCiMjIyMgKipDb25zKio6DQoNCi0gUmVxdWlyZXMgdGhlIG51bWJlciBvZiBjbHVzdGVycyBcKCBrIFwpIHRvIGJlIHByZS1zcGVjaWZpZWQuDQoNCi0gU3RydWdnbGVzIHdpdGggbm9uLWNvbnZleCBvciBpcnJlZ3VsYXItc2hhcGVkIGNsdXN0ZXJzLg0KDQotIFNlbnNpdGl2ZSB0byB0aGUgc2NhbGUgb2YgZGF0YSBhbmQgb3V0bGllcnMuDQoNCi0tLQ0KDQojIyMgKipLLU1lYW5zIENsdXN0ZXJpbmcgRXhhbXBsZSBpbiBSKioNCg0KV2Ugd2lsbCB1c2UgSy1NZWFucyB0byBjbHVzdGVyIGRhdGEgcG9pbnRzIGJhc2VkIG9uIHR3byB2YXJpYWJsZXMuIFdl4oCZbGwgZ2VuZXJhdGUgYSBkYXRhc2V0IG9mIHJhbmRvbSBwb2ludHMgYW5kIHVzZSB0aGUgSy1NZWFucyBhbGdvcml0aG0gdG8gaWRlbnRpZnkgY2x1c3RlcnMuDQoNCiMjIyMgKipTdGVwIDE6IENyZWF0ZSB0aGUgRGF0YSoqDQoNCldl4oCZbGwgZ2VuZXJhdGUgYSBkYXRhc2V0IHdpdGggdHdvIGZlYXR1cmVzICh4IGFuZCB5KSB0aGF0IGNhbiBiZSBncm91cGVkIGludG8gY2x1c3RlcnMuDQoNCmBgYHtyfQ0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJ5DQpzZXQuc2VlZCgxMjMpDQoNCiMgR2VuZXJhdGUgcmFuZG9tIGRhdGEgcG9pbnRzDQp4IDwtIGMocm5vcm0oNTAsIG1lYW4gPSAxLCBzZCA9IDAuNSksIHJub3JtKDUwLCBtZWFuID0gNSwgc2QgPSAwLjUpLCBybm9ybSg1MCwgbWVhbiA9IDksIHNkID0gMC41KSkNCnkgPC0gYyhybm9ybSg1MCwgbWVhbiA9IDEsIHNkID0gMC41KSwgcm5vcm0oNTAsIG1lYW4gPSA1LCBzZCA9IDAuNSksIHJub3JtKDUwLCBtZWFuID0gOSwgc2QgPSAwLjUpKQ0KDQojIENvbWJpbmUgaW50byBhIGRhdGEgZnJhbWUNCmRhdGEgPC0gZGF0YS5mcmFtZSh4LCB5KQ0KaGVhZChkYXRhKQ0KYGBgDQoNCg0KSGVyZSwgd2UgZ2VuZXJhdGUgMTUwIGRhdGEgcG9pbnRzIGRpc3RyaWJ1dGVkIGFyb3VuZCB0aHJlZSBjZW50ZXJzOiAoMSwgMSksICg1LCA1KSwgYW5kICg5LCA5KS4NCg0KIyMjIyAqKlN0ZXAgMjogUGVyZm9ybSBLLU1lYW5zIENsdXN0ZXJpbmcqKg0KDQpXZSB3aWxsIHVzZSB0aGUgYGttZWFucygpYCBmdW5jdGlvbiBpbiBSIHRvIGFwcGx5IEstTWVhbnMgY2x1c3RlcmluZyB0byBvdXIgZGF0YXNldC4gV2UgbmVlZCB0byBzcGVjaWZ5IHRoZSBudW1iZXIgb2YgY2x1c3RlcnMgXCggayBcKSwgd2hpY2ggd2XigJlsbCBzZXQgdG8gMy4NCg0KYGBge3J9DQojIEFwcGx5IEstTWVhbnMgY2x1c3RlcmluZyB3aXRoIDMgY2x1c3RlcnMNCmttZWFuc19yZXN1bHQgPC0ga21lYW5zKGRhdGEsIGNlbnRlcnMgPSAzKQ0KDQojIFByaW50IHRoZSByZXN1bHRzDQpwcmludChrbWVhbnNfcmVzdWx0KQ0KYGBgDQoNCg0KIyMjIyAqKk91dHB1dCoqIChzaW1wbGlmaWVkKToNCmBgYA0KSy1tZWFucyBjbHVzdGVyaW5nIHdpdGggMyBjbHVzdGVycyBvZiBzaXplcyA1MCwgNTAsIDUwDQoNCkNsdXN0ZXIgbWVhbnM6DQogICAgICAgICB4ICAgICAgICB5DQoxIDEuMDUyNzM5IDEuMDQzMzQ2DQoyIDkuMDM0MDE3IDkuMDMzMzg0DQozIDQuOTYzMjEzIDUuMDEyMDAzDQoNCkNsdXN0ZXJpbmcgdmVjdG9yOg0KIFsxXSAxIDEgMSAxIDEgMSAxIDEgMSAxIDEgMSAxIDEgMSAxIDEgMSAxIDEgMSAxIDEgMSAxIDEgMSAxIDEgMSAxIDEgMSAxIDENCi4uLg0KYGBgDQoNCiMjIyMgKipJbnRlcnByZXRhdGlvbioqOg0KDQotIFRoZSBhbGdvcml0aG0gaGFzIGlkZW50aWZpZWQgMyBjbHVzdGVycywgZWFjaCBjb250YWluaW5nIDUwIHBvaW50cy4NCg0KLSBUaGUgKipjbHVzdGVyIG1lYW5zKiogKGNlbnRyb2lkcykgZm9yIHRoZSB0aHJlZSBjbHVzdGVycyBhcmUgYXBwcm94aW1hdGVseSAoMSwxKSwgKDUsNSksIGFuZCAoOSw5KSwgd2hpY2ggbWF0Y2hlcyB0aGUgY2VudGVycyBhcm91bmQgd2hpY2ggdGhlIGRhdGEgd2FzIGdlbmVyYXRlZC4NCg0KLSBUaGUgKipjbHVzdGVyaW5nIHZlY3RvcioqIGluZGljYXRlcyB0aGUgY2x1c3RlciBhc3NpZ25tZW50IGZvciBlYWNoIGRhdGEgcG9pbnQuDQoNCiMjIyMgKipTdGVwIDM6IFZpc3VhbGl6ZSB0aGUgQ2x1c3RlcnMqKg0KDQpXZSBjYW4gdmlzdWFsaXplIHRoZSByZXN1bHRzIG9mIEstTWVhbnMgY2x1c3RlcmluZyBieSBwbG90dGluZyB0aGUgZGF0YSBwb2ludHMgYW5kIGNvbG9yaW5nIHRoZW0gYmFzZWQgb24gdGhlaXIgY2x1c3RlciBhc3NpZ25tZW50Lg0KDQpgYGB7cn0NCiMgUGxvdCB0aGUgZGF0YSBwb2ludHMgYW5kIGNvbG9yIHRoZW0gYnkgY2x1c3Rlcg0KcGxvdChkYXRhJHgsIGRhdGEkeSwgY29sID0ga21lYW5zX3Jlc3VsdCRjbHVzdGVyLCBwY2ggPSAxOSwNCiAgICAgbWFpbiA9ICJLLU1lYW5zIENsdXN0ZXJpbmcgUmVzdWx0cyIsDQogICAgIHhsYWIgPSAiWCIsIHlsYWIgPSAiWSIpDQoNCiMgQWRkIGNsdXN0ZXIgY2VudGVycyB0byB0aGUgcGxvdA0KcG9pbnRzKGttZWFuc19yZXN1bHQkY2VudGVyc1ssIDFdLCBrbWVhbnNfcmVzdWx0JGNlbnRlcnNbLCAyXSwgY29sID0gMTozLCBwY2ggPSA4LCBjZXggPSAyKQ0KYGBgDQoNCg0KIyMjIyAqKkludGVycHJldGF0aW9uKio6DQoNCi0gVGhlIHNjYXR0ZXJwbG90IHNob3dzIHRoZSBkYXRhIHBvaW50cywgd2l0aCBlYWNoIHBvaW50IGNvbG9yZWQgYmFzZWQgb24gaXRzIGNsdXN0ZXIgYXNzaWdubWVudC4NCg0KLSBUaGUgbGFyZ2UgY3Jvc3NlcyByZXByZXNlbnQgdGhlIGNsdXN0ZXIgY2VudHJvaWRzLCBzaG93aW5nIHdoZXJlIHRoZSBhbGdvcml0aG0gaGFzIHBsYWNlZCB0aGUgY2VudGVyIG9mIGVhY2ggY2x1c3Rlci4NCg0KLSBZb3UgY2FuIHNlZSB0aGF0IHRoZSBLLU1lYW5zIGFsZ29yaXRobSBoYXMgc3VjY2Vzc2Z1bGx5IGdyb3VwZWQgdGhlIHBvaW50cyBpbnRvIHRocmVlIGNsdXN0ZXJzIGFyb3VuZCB0aGVpciByZXNwZWN0aXZlIGNlbnRlcnMuDQoNCi0tLQ0KDQojIyMgKipDaG9vc2luZyB0aGUgT3B0aW1hbCBOdW1iZXIgb2YgQ2x1c3RlcnMgXCggayBcKSoqDQoNCk9uZSBjb21tb24gbWV0aG9kIGZvciBzZWxlY3RpbmcgdGhlIG9wdGltYWwgbnVtYmVyIG9mIGNsdXN0ZXJzIGlzIHRoZSAqKkVsYm93IE1ldGhvZCoqLCB3aGljaCBpbnZvbHZlcyBwbG90dGluZyB0aGUgdG90YWwgd2l0aGluLWNsdXN0ZXIgc3VtIG9mIHNxdWFyZXMgKFdTUykgZm9yIGRpZmZlcmVudCB2YWx1ZXMgb2YgXCggayBcKSBhbmQgbG9va2luZyBmb3IgYW4gImVsYm93IiBwb2ludCB3aGVyZSB0aGUgV1NTIGJlZ2lucyB0byBkZWNyZWFzZSBtb3JlIHNsb3dseS4NCg0KIyMjIyAqKlN0ZXAgNDogRWxib3cgTWV0aG9kIHRvIERldGVybWluZSBcKCBrIFwpKioNCg0KV2UgY2FuIGNvbXB1dGUgdGhlIFdTUyBmb3IgZGlmZmVyZW50IHZhbHVlcyBvZiBcKCBrIFwpIGFuZCBwbG90IHRoZSByZXN1bHRzIHRvIGhlbHAgZGV0ZXJtaW5lIHRoZSBvcHRpbWFsIG51bWJlciBvZiBjbHVzdGVycy4NCg0KYGBge3J9DQojIENvbXB1dGUgd2l0aGluLWNsdXN0ZXIgc3VtIG9mIHNxdWFyZXMgKFdTUykgZm9yIGRpZmZlcmVudCBrIHZhbHVlcw0Kd3NzIDwtIHNhcHBseSgxOjEwLCBmdW5jdGlvbihrKXsNCiAga21lYW5zKGRhdGEsIGNlbnRlcnMgPSBrKSR0b3Qud2l0aGluc3MNCn0pDQoNCiMgUGxvdCB0aGUgRWxib3cgTWV0aG9kDQpwbG90KDE6MTAsIHdzcywgdHlwZSA9ICJiIiwgcGNoID0gMTksIGZyYW1lID0gRkFMU0UsDQogICAgIHhsYWIgPSAiTnVtYmVyIG9mIENsdXN0ZXJzIiwNCiAgICAgeWxhYiA9ICJUb3RhbCBXaXRoaW4tQ2x1c3RlciBTdW0gb2YgU3F1YXJlcyIsDQogICAgIG1haW4gPSAiRWxib3cgTWV0aG9kIGZvciBGaW5kaW5nIE9wdGltYWwgayIpDQpgYGANCg0KDQojIyMjICoqSW50ZXJwcmV0YXRpb24qKjoNCg0KLSBUaGUgKipFbGJvdyBNZXRob2QqKiBwbG90IHNob3dzIHRoZSBXU1MgZm9yIGRpZmZlcmVudCB2YWx1ZXMgb2YgXCggayBcKS4gDQoNCi0gVGhlIHBvaW50IHdoZXJlIHRoZSBkZWNyZWFzZSBpbiBXU1MgYmVjb21lcyBtb3JlIGdyYWR1YWwgaXMgdGhlICJlbGJvdyIgcG9pbnQsIHdoaWNoIHN1Z2dlc3RzIHRoZSBvcHRpbWFsIG51bWJlciBvZiBjbHVzdGVycy4gDQoNCi0gSW4gdGhpcyBjYXNlLCB0aGUgZWxib3cgdHlwaWNhbGx5IG9jY3VycyBhcm91bmQgXCggayA9IDMgXCksIGNvbmZpcm1pbmcgdGhhdCAzIGNsdXN0ZXJzIGlzIGEgZ29vZCBjaG9pY2UgZm9yIHRoaXMgZGF0YXNldC4NCg0KLS0tDQoNCiMjIyAqKkstTWVhbnMgQWxnb3JpdGhtIFByb2Nlc3MgU3VtbWFyeSoqOg0KDQoxLiBDaG9vc2UgXCggayBcKSwgdGhlIG51bWJlciBvZiBjbHVzdGVycy4NCg0KMi4gUmFuZG9tbHkgaW5pdGlhbGl6ZSBcKCBrIFwpIGNlbnRyb2lkcy4NCg0KMy4gQXNzaWduIGVhY2ggcG9pbnQgdG8gdGhlIG5lYXJlc3QgY2VudHJvaWQuDQoNCjQuIFJlY2FsY3VsYXRlIHRoZSBjZW50cm9pZHMgYmFzZWQgb24gdGhlIG1lYW4gb2YgcG9pbnRzIGluIGVhY2ggY2x1c3Rlci4NCg0KNS4gUmVwZWF0IHN0ZXBzIDMtNCB1bnRpbCBjb252ZXJnZW5jZS4NCg0KLS0tDQoNCiMjIyAqKkNvbmNsdXNpb24qKjoNCkstTWVhbnMgY2x1c3RlcmluZyBpcyBhIHBvd2VyZnVsIGFuZCB3aWRlbHktdXNlZCB1bnN1cGVydmlzZWQgbGVhcm5pbmcgYWxnb3JpdGhtIGZvciBpZGVudGlmeWluZyBwYXR0ZXJucyBhbmQgZ3JvdXBzIGluIGRhdGEuIEluIFIsIHRoZSBga21lYW5zKClgIGZ1bmN0aW9uIG1ha2VzIGl0IGVhc3kgdG8gYXBwbHkgdGhpcyBhbGdvcml0aG0gdG8geW91ciBkYXRhc2V0LCBhbmQgdmlzdWFsaXppbmcgdGhlIGNsdXN0ZXJzIGNhbiBwcm92aWRlIHZhbHVhYmxlIGluc2lnaHRzIGludG8gdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YS4=