Question 1

acs <- read.csv("HW3data.csv")
state <- acs$State
data <- select(acs, -State)

a.

pca.sc <- prcomp(data, scale = TRUE)
data_pca <- pca.sc$x[ , 1:7]
row.names(data_pca) <- state

b.

dists <- dist(data_pca)

c.

hclust.sing <- hclust(dists, method = "single")
par(mar = c(.5, 2, .5, 1)) 
plot(hclust.sing, hang = -1, sub = "", main = "")
  abline(h = hclust.sing$height[51 - 7], lty = 2)

d.

Under single linkage, clusters are considered close if just one of their values is close to the value of another cluster. So clusters that merge together only need to share one similar observation, and the distance between those observations must be within our cut height distance. Therefore, clusters that share no observations within the cut height distance will not merge with each other, and so every cluster that has merged into one, must have at least one observation within the cut height distance to another observation in its cluster. Since cluster 1 and 3 obviously didn’t merge that means they share no observations within the cut height distance, which we can check for here.

clus.sing <- cutree(hclust.sing, h = hclust.sing$height[51 - 7])
  table(clus.sing)
clus.sing
 1  2  3  4  5  6  7 
41  1  5  1  1  1  1 
d.mat <- as.matrix(dists)
min(d.mat[which(clus.sing == 1), which(clus.sing == 3)])
[1] 3.851532

The smallest distance between any two observations in cluster 1 and cluster 3 is 3.85 which is greater than our cut height distance of 3.77.

e.

The distance between Arizona and Florida, and Texas and California, are both less than the cut height distance.

d.mat[which(clus.sing == 3), which(clus.sing == 3)]
            Arizona California  Florida   Nevada    Texas
Arizona    0.000000   4.919295 2.837324 3.706277 3.994248
California 4.919295   0.000000 4.725443 7.192576 2.925050
Florida    2.837324   4.725443 0.000000 4.482842 3.770813
Nevada     3.706277   7.192576 4.482842 0.000000 6.559933
Texas      3.994248   2.925050 3.770813 6.559933 0.000000

f. 

Complete linkage has stricter conditions than single linkage. Complete linkage looks at the distance between the two farthest observations in clusters. So instead of merging clusters with one similar observation it merges clusters with all similar observations. This results in a more spaced out dendrogram since clusters must be more similar to merge than under single linkage. Under single linkage clusters were able to merge much quicker.

hclust.com <- hclust(dists, method = "complete")
par(mar = c(.5, 2, .5, 1)) 
plot(hclust.com, hang = -1, sub = "", main = "")
  abline(h = 7.5, lty = 2)

g.

With a cut height of 7.5, we would have 9 clusters. The three states in their own clusters are the District of Columbia, Alaska, and Hawaii. This tells us these states are fairly different than most states.

clus.com <- cutree(hclust.com, h = 7.5)
  table(clus.com)
clus.com
 1  2  3  4  5  6  7  8  9 
 7  1  6 13  1 14  1  4  4 

h.

The maximum distance between observations in cluster 8 and 9 is 7.89 which is greater than our cut height distance. So these clusters can’t and didn’t merge at our cut height.

max(d.mat[which(clus.com == 8), which(clus.com == 9)])
[1] 7.894893

i.

Looking at the distances between all the observations in cluster 8, you’ll notice all distances are less than the cut height distance.

d.mat[which(clus.com == 8), which(clus.com == 8)]
                 Maine Minnesota New Hampshire  Vermont
Maine         0.000000  4.240758      3.901416 2.949826
Minnesota     4.240758  0.000000      1.781645 4.887299
New Hampshire 3.901416  1.781645      0.000000 3.965155
Vermont       2.949826  4.887299      3.965155 0.000000

j.

The function choose 9 clusters. States with the lowest maximum cluster probabilities are the ones the model is least confident about assigning to a single cluster. Their probabilities are more spread out across multiple clusters, meaning they don’t strongly fit into any one cluster and may lie between clusters or have mixed characteristics. The states with the min maxes are Oregon, Maryland, and Maine, so these states didn’t strongly fit into one single cluster as well as the others.

gmm_model <- Mclust(data_pca)
probs <- apply(gmm_model$z, 1, max)
sort(probs)[1:3]
   Oregon  Maryland     Maine 
0.7499619 0.8475613 0.9154546 

k.

There does appear to be an elbow in the k-distance plot around 6.8. We got 1 cluster and 3 noise points. To no surprise, the three outlier states were Alaska, District of Columbia, and Hawaii.

minPts <- 2*ncol(data_pca)
kNNdistplot(data_pca, k = minPts - 1)
  abline(h = 6.8, lty = 2)

db <- dbscan(data_pca, eps = 6.8, minPts = minPts)
  print(db)
DBSCAN clustering for 51 objects.
Parameters: eps = 6.8, minPts = 14
Using euclidean distances and borderpoints = TRUE
The clustering contains 1 cluster(s) and 3 noise points.

 0  1 
 3 48 

Available fields: cluster, eps, minPts, metric, borderPoints
state[db$cluster == 0]
[1] "Alaska"               "District of Columbia" "Hawaii"              

l.

Once again, the three outlier states were Alaska, District of Columbia, and Hawaii.

lof_scores <- lof(data_pca, minPts = 8)
sort(head(order(lof_scores, decreasing = TRUE), n = 3))
[1]  2  9 12
state[c(2,9,12)]
[1] "Alaska"               "District of Columbia" "Hawaii"              
LS0tCnRpdGxlOiAiSG9tZXdvcmsgNCIKYXV0aG9yOiAiQ2hhcmxpZSBNb3JnYW4iCmRhdGU6ICIgRHVlOiAwMy8yOS8yNiIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6IAogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNAogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogbm8KICAgIHRvY19jb2xsYXBzZWQ6IHllcwogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIHNtb290aF9zY3JvbGw6IHllcwogICAgdGhlbWU6IGx1bWVuCiAgcGRmX2RvY3VtZW50OiAKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBmaWdfd2lkdGg6IDMKICAgIGZpZ19oZWlnaHQ6IDMKICB3b3JkX2RvY3VtZW50OiAKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGtlZXBfbWQ6IHllcwplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0KI1RPQzo6YmVmb3JlIHsKICBjb250ZW50OiAiVGFibGUgb2YgQ29udGVudHMiOwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGZvbnQtc2l6ZTogMS4yZW07CiAgZGlzcGxheTogYmxvY2s7CiAgY29sb3I6IG5hdnk7CiAgbWFyZ2luLWJvdHRvbTogMTBweDsKfQoKCmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47CiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7CiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOwogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOwp9CgpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLwogIGZvbnQtc2l6ZTogMjJweDsKICBmb250LXdlaWdodDogYm9sZDsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOwp9CgpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMTVweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogc3lzdGVtLXVpOwogIGNvbG9yOiBuYXZ5OwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgZm9udC1zaXplOiAxOHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cgpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQoKLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0KCnAgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9Cgp9CmBgYAoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCAKIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuCmlmICghcmVxdWlyZSgia25pdHIiKSkgewogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpCiAgIGxpYnJhcnkoa25pdHIpCn0KaWYgKCFyZXF1aXJlKCJmYWN0b2V4dHJhIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJmYWN0b2V4dHJhIikKICBsaWJyYXJ5KGZhY3RvZXh0cmEpCn0KCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQogIGxpYnJhcnkodGlkeXZlcnNlKQp9CgppZiAoIXJlcXVpcmUoIkZhY3RvTWluZVIiKSkgewogIGluc3RhbGwucGFja2FnZXMoIkZhY3RvTWluZVIiKQogIGxpYnJhcnkoRmFjdG9NaW5lUikKfQoKaWYgKCFyZXF1aXJlKCJjb3JycGxvdCIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygiY29ycnBsb3QiKQogIGxpYnJhcnkoY29ycnBsb3QpCn0KCmlmICghcmVxdWlyZSgibWljZSIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygibWljZSIpCiAgbGlicmFyeShtaWNlKQp9CgppZiAoIXJlcXVpcmUoImthYmxlRXh0cmEiKSkgewogIGluc3RhbGwucGFja2FnZXMoImthYmxlRXh0cmEiKQogIGxpYnJhcnkoa2FibGVFeHRyYSkKfQoKaWYgKCFyZXF1aXJlKCJjbHVzdGVyIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJjbHVzdGVyIikKICBsaWJyYXJ5KGNsdXN0ZXIpCn0KCmlmICghcmVxdWlyZSgibWNsdXN0IikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJtY2x1c3QiKQogIGxpYnJhcnkobWNsdXN0KQp9CgppZiAoIXJlcXVpcmUoImRic2NhbiIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygiZGJzY2FuIikKICBsaWJyYXJ5KGRic2NhbikKfQojIyMjCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3UgY2FuIGNob29zZSB0byBpbmNsdWRlIHRoZSB3YXJuaW5nIG1lc3NhZ2VzIGluCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIAogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICAgICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gdGhlIG91dHB1dCBmaWxlLgogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BCiAgICAgICAgICAgICAgICAgICAgICApICAKCmBgYAoKIyBRdWVzdGlvbiAxCmBgYHtyLCByZXN1bHRzID0gJ2hpZGUnfQphY3MgPC0gcmVhZC5jc3YoIkhXM2RhdGEuY3N2IikKc3RhdGUgPC0gYWNzJFN0YXRlCmRhdGEgPC0gc2VsZWN0KGFjcywgLVN0YXRlKQpgYGAKCiMjIGEuCmBgYHtyfQpwY2Euc2MgPC0gcHJjb21wKGRhdGEsIHNjYWxlID0gVFJVRSkKZGF0YV9wY2EgPC0gcGNhLnNjJHhbICwgMTo3XQpyb3cubmFtZXMoZGF0YV9wY2EpIDwtIHN0YXRlCmBgYAoKIyMgYi4KYGBge3J9CmRpc3RzIDwtIGRpc3QoZGF0YV9wY2EpCmBgYAoKIyMgYy4KYGBge3J9CmhjbHVzdC5zaW5nIDwtIGhjbHVzdChkaXN0cywgbWV0aG9kID0gInNpbmdsZSIpCnBhcihtYXIgPSBjKC41LCAyLCAuNSwgMSkpIApwbG90KGhjbHVzdC5zaW5nLCBoYW5nID0gLTEsIHN1YiA9ICIiLCBtYWluID0gIiIpCiAgYWJsaW5lKGggPSBoY2x1c3Quc2luZyRoZWlnaHRbNTEgLSA3XSwgbHR5ID0gMikKYGBgCgojIyBkLgpVbmRlciBzaW5nbGUgbGlua2FnZSwgY2x1c3RlcnMgYXJlIGNvbnNpZGVyZWQgY2xvc2UgaWYganVzdCBvbmUgb2YgdGhlaXIgdmFsdWVzIGlzIGNsb3NlIHRvIHRoZSB2YWx1ZSBvZiBhbm90aGVyIGNsdXN0ZXIuIFNvIGNsdXN0ZXJzIHRoYXQgbWVyZ2UgdG9nZXRoZXIgb25seSBuZWVkIHRvIHNoYXJlIG9uZSBzaW1pbGFyIG9ic2VydmF0aW9uLCBhbmQgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhvc2Ugb2JzZXJ2YXRpb25zIG11c3QgYmUgd2l0aGluIG91ciBjdXQgaGVpZ2h0IGRpc3RhbmNlLiBUaGVyZWZvcmUsIGNsdXN0ZXJzIHRoYXQgc2hhcmUgbm8gb2JzZXJ2YXRpb25zIHdpdGhpbiB0aGUgY3V0IGhlaWdodCBkaXN0YW5jZSB3aWxsIG5vdCBtZXJnZSB3aXRoIGVhY2ggb3RoZXIsIGFuZCBzbyBldmVyeSBjbHVzdGVyIHRoYXQgaGFzIG1lcmdlZCBpbnRvIG9uZSwgbXVzdCBoYXZlIGF0IGxlYXN0IG9uZSBvYnNlcnZhdGlvbiB3aXRoaW4gdGhlIGN1dCBoZWlnaHQgZGlzdGFuY2UgdG8gYW5vdGhlciBvYnNlcnZhdGlvbiBpbiBpdHMgY2x1c3Rlci4gU2luY2UgY2x1c3RlciAxIGFuZCAzIG9idmlvdXNseSBkaWRuJ3QgbWVyZ2UgdGhhdCBtZWFucyB0aGV5IHNoYXJlIG5vIG9ic2VydmF0aW9ucyB3aXRoaW4gdGhlIGN1dCBoZWlnaHQgZGlzdGFuY2UsIHdoaWNoIHdlIGNhbiBjaGVjayBmb3IgaGVyZS4KYGBge3J9CmNsdXMuc2luZyA8LSBjdXRyZWUoaGNsdXN0LnNpbmcsIGggPSBoY2x1c3Quc2luZyRoZWlnaHRbNTEgLSA3XSkKICB0YWJsZShjbHVzLnNpbmcpCmQubWF0IDwtIGFzLm1hdHJpeChkaXN0cykKbWluKGQubWF0W3doaWNoKGNsdXMuc2luZyA9PSAxKSwgd2hpY2goY2x1cy5zaW5nID09IDMpXSkKYGBgClRoZSBzbWFsbGVzdCBkaXN0YW5jZSBiZXR3ZWVuIGFueSB0d28gb2JzZXJ2YXRpb25zIGluIGNsdXN0ZXIgMSBhbmQgY2x1c3RlciAzIGlzIDMuODUgd2hpY2ggaXMgZ3JlYXRlciB0aGFuIG91ciBjdXQgaGVpZ2h0IGRpc3RhbmNlIG9mIDMuNzcuCgojIyBlLgpUaGUgZGlzdGFuY2UgYmV0d2VlbiBBcml6b25hIGFuZCBGbG9yaWRhLCBhbmQgVGV4YXMgYW5kIENhbGlmb3JuaWEsIGFyZSBib3RoIGxlc3MgdGhhbiB0aGUgY3V0IGhlaWdodCBkaXN0YW5jZS4KYGBge3J9CmQubWF0W3doaWNoKGNsdXMuc2luZyA9PSAzKSwgd2hpY2goY2x1cy5zaW5nID09IDMpXQpgYGAKIyMgZi4gCkNvbXBsZXRlIGxpbmthZ2UgaGFzIHN0cmljdGVyIGNvbmRpdGlvbnMgdGhhbiBzaW5nbGUgbGlua2FnZS4gQ29tcGxldGUgbGlua2FnZSBsb29rcyBhdCB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgdHdvIGZhcnRoZXN0IG9ic2VydmF0aW9ucyBpbiBjbHVzdGVycy4gU28gaW5zdGVhZCBvZiBtZXJnaW5nIGNsdXN0ZXJzIHdpdGggb25lIHNpbWlsYXIgb2JzZXJ2YXRpb24gaXQgbWVyZ2VzIGNsdXN0ZXJzIHdpdGggYWxsIHNpbWlsYXIgb2JzZXJ2YXRpb25zLiBUaGlzIHJlc3VsdHMgaW4gYSBtb3JlIHNwYWNlZCBvdXQgZGVuZHJvZ3JhbSBzaW5jZSBjbHVzdGVycyBtdXN0IGJlIG1vcmUgc2ltaWxhciB0byBtZXJnZSB0aGFuIHVuZGVyIHNpbmdsZSBsaW5rYWdlLiBVbmRlciBzaW5nbGUgbGlua2FnZSBjbHVzdGVycyB3ZXJlIGFibGUgdG8gbWVyZ2UgbXVjaCBxdWlja2VyLgpgYGB7cn0KaGNsdXN0LmNvbSA8LSBoY2x1c3QoZGlzdHMsIG1ldGhvZCA9ICJjb21wbGV0ZSIpCnBhcihtYXIgPSBjKC41LCAyLCAuNSwgMSkpIApwbG90KGhjbHVzdC5jb20sIGhhbmcgPSAtMSwgc3ViID0gIiIsIG1haW4gPSAiIikKICBhYmxpbmUoaCA9IDcuNSwgbHR5ID0gMikKYGBgCgojIyBnLgpXaXRoIGEgY3V0IGhlaWdodCBvZiA3LjUsIHdlIHdvdWxkIGhhdmUgOSBjbHVzdGVycy4gVGhlIHRocmVlIHN0YXRlcyBpbiB0aGVpciBvd24gY2x1c3RlcnMgYXJlIHRoZSBEaXN0cmljdCBvZiBDb2x1bWJpYSwgQWxhc2thLCBhbmQgSGF3YWlpLiBUaGlzIHRlbGxzIHVzIHRoZXNlIHN0YXRlcyBhcmUgZmFpcmx5IGRpZmZlcmVudCB0aGFuIG1vc3Qgc3RhdGVzLiAKYGBge3J9CmNsdXMuY29tIDwtIGN1dHJlZShoY2x1c3QuY29tLCBoID0gNy41KQogIHRhYmxlKGNsdXMuY29tKQpgYGAKCiMjIGguClRoZSBtYXhpbXVtIGRpc3RhbmNlIGJldHdlZW4gb2JzZXJ2YXRpb25zIGluIGNsdXN0ZXIgOCBhbmQgOSBpcyA3Ljg5IHdoaWNoIGlzIGdyZWF0ZXIgdGhhbiBvdXIgY3V0IGhlaWdodCBkaXN0YW5jZS4gU28gdGhlc2UgY2x1c3RlcnMgY2FuJ3QgYW5kIGRpZG4ndCBtZXJnZSBhdCBvdXIgY3V0IGhlaWdodC4KYGBge3J9Cm1heChkLm1hdFt3aGljaChjbHVzLmNvbSA9PSA4KSwgd2hpY2goY2x1cy5jb20gPT0gOSldKQpgYGAKCiMjIGkuCkxvb2tpbmcgYXQgdGhlIGRpc3RhbmNlcyBiZXR3ZWVuIGFsbCB0aGUgb2JzZXJ2YXRpb25zIGluIGNsdXN0ZXIgOCwgeW91J2xsIG5vdGljZSBhbGwgZGlzdGFuY2VzIGFyZSBsZXNzIHRoYW4gdGhlIGN1dCBoZWlnaHQgZGlzdGFuY2UuIApgYGB7cn0KZC5tYXRbd2hpY2goY2x1cy5jb20gPT0gOCksIHdoaWNoKGNsdXMuY29tID09IDgpXQpgYGAKIyMgai4KVGhlIGZ1bmN0aW9uIGNob29zZSA5IGNsdXN0ZXJzLiBTdGF0ZXMgd2l0aCB0aGUgbG93ZXN0IG1heGltdW0gY2x1c3RlciBwcm9iYWJpbGl0aWVzIGFyZSB0aGUgb25lcyB0aGUgbW9kZWwgaXMgbGVhc3QgY29uZmlkZW50IGFib3V0IGFzc2lnbmluZyB0byBhIHNpbmdsZSBjbHVzdGVyLiBUaGVpciBwcm9iYWJpbGl0aWVzIGFyZSBtb3JlIHNwcmVhZCBvdXQgYWNyb3NzIG11bHRpcGxlIGNsdXN0ZXJzLCBtZWFuaW5nIHRoZXkgZG9u4oCZdCBzdHJvbmdseSBmaXQgaW50byBhbnkgb25lIGNsdXN0ZXIgYW5kIG1heSBsaWUgYmV0d2VlbiBjbHVzdGVycyBvciBoYXZlIG1peGVkIGNoYXJhY3RlcmlzdGljcy4gVGhlIHN0YXRlcyB3aXRoIHRoZSBtaW4gbWF4ZXMgYXJlIE9yZWdvbiwgTWFyeWxhbmQsIGFuZCBNYWluZSwgc28gdGhlc2Ugc3RhdGVzIGRpZG4ndCBzdHJvbmdseSBmaXQgaW50byBvbmUgc2luZ2xlIGNsdXN0ZXIgYXMgd2VsbCBhcyB0aGUgb3RoZXJzLgpgYGB7cn0KZ21tX21vZGVsIDwtIE1jbHVzdChkYXRhX3BjYSkKcHJvYnMgPC0gYXBwbHkoZ21tX21vZGVsJHosIDEsIG1heCkKc29ydChwcm9icylbMTozXQpgYGAKCiMjIGsuClRoZXJlIGRvZXMgYXBwZWFyIHRvIGJlIGFuIGVsYm93IGluIHRoZSBrLWRpc3RhbmNlIHBsb3QgYXJvdW5kIDYuOC4gV2UgZ290IDEgY2x1c3RlciBhbmQgMyBub2lzZSBwb2ludHMuIFRvIG5vIHN1cnByaXNlLCB0aGUgdGhyZWUgb3V0bGllciBzdGF0ZXMgd2VyZSBBbGFza2EsIERpc3RyaWN0IG9mIENvbHVtYmlhLCBhbmQgSGF3YWlpLgpgYGB7cn0KbWluUHRzIDwtIDIqbmNvbChkYXRhX3BjYSkKa05OZGlzdHBsb3QoZGF0YV9wY2EsIGsgPSBtaW5QdHMgLSAxKQogIGFibGluZShoID0gNi44LCBsdHkgPSAyKQpkYiA8LSBkYnNjYW4oZGF0YV9wY2EsIGVwcyA9IDYuOCwgbWluUHRzID0gbWluUHRzKQogIHByaW50KGRiKQogIApzdGF0ZVtkYiRjbHVzdGVyID09IDBdCmBgYAojIyBsLgpPbmNlIGFnYWluLCB0aGUgdGhyZWUgb3V0bGllciBzdGF0ZXMgd2VyZSBBbGFza2EsIERpc3RyaWN0IG9mIENvbHVtYmlhLCBhbmQgSGF3YWlpLgpgYGB7cn0KbG9mX3Njb3JlcyA8LSBsb2YoZGF0YV9wY2EsIG1pblB0cyA9IDgpCnNvcnQoaGVhZChvcmRlcihsb2Zfc2NvcmVzLCBkZWNyZWFzaW5nID0gVFJVRSksIG4gPSAzKSkKc3RhdGVbYygyLDksMTIpXQpgYGA=