ansur_men$bmi <- (ansur_men$weightkg/10)/(ansur_men$stature/1000)**2
ansur_women$bmi <- (ansur_women$weightkg/10)/(ansur_women$stature/1000)**2
summary(ansur_men$bmi)
Min. 1st Qu. Median Mean 3rd Qu. Max.
15.35 24.87 27.46 27.69 30.29 43.45
summary(ansur_women$bmi)
Min. 1st Qu. Median Mean 3rd Qu. Max.
16.37 23.08 25.27 25.50 27.61 40.78
merge(ansur_men, ansur_women, all=T)
length(names(ansur_women)) == length(names(ansur_men))
[1] TRUE
nrow(ansur) == nrow(ansur_men) + nrow(ansur_women)
[1] TRUE
summary(ansur_men[,1:10])
subjectid abdominalextensiondepthsitting acromialheight acromionradialelength anklecircumference axillaheight balloffootcircumference balloffootlength biacromialbreadth bicepscircumferenceflexed
Min. :10027 Min. :163.0 Min. :1194 Min. :270.0 Min. :156.0 Min. :1106 Min. :186 Min. :156.0 Min. :337.0 Min. :246.0
1st Qu.:14270 1st Qu.:227.0 1st Qu.:1398 1st Qu.:324.0 1st Qu.:219.2 1st Qu.:1289 1st Qu.:243 1st Qu.:194.0 1st Qu.:403.0 1st Qu.:335.0
Median :17237 Median :251.0 Median :1439 Median :335.0 Median :228.0 Median :1328 Median :252 Median :201.0 Median :415.0 Median :357.0
Mean :20003 Mean :254.7 Mean :1441 Mean :335.2 Mean :229.3 Mean :1329 Mean :252 Mean :200.9 Mean :415.7 Mean :358.1
3rd Qu.:27316 3rd Qu.:279.0 3rd Qu.:1481 3rd Qu.:346.0 3rd Qu.:239.0 3rd Qu.:1367 3rd Qu.:261 3rd Qu.:208.0 3rd Qu.:428.0 3rd Qu.:380.0
Max. :29452 Max. :451.0 Max. :1683 Max. :393.0 Max. :293.0 Max. :1553 Max. :306 Max. :245.0 Max. :489.0 Max. :490.0
sapply(ansur_men[c("stature", "sittingheight", "weightkg","bmi")], mean)
stature sittingheight weightkg bmi
1756.21460 918.28981 855.23959 27.68631
sapply(ansur_women[c("stature", "sittingheight", "weightkg","bmi")], mean)
stature sittingheight weightkg bmi
1628.47331 856.62588 677.58207 25.49597
sapply(ansur_men[c("stature", "sittingheight", "weightkg","bmi")], sd)
stature sittingheight weightkg bmi
68.550788 35.698183 142.206992 4.039462
sapply(ansur_women[c("stature", "sittingheight", "weightkg","bmi")], sd)
stature sittingheight weightkg bmi
64.199512 33.054242 109.846458 3.491673
#Compute the following quantiles for stature, sittingheight, weightkg, and BMI for women: 0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99
sapply(ansur_women[c("stature", "sittingheight", "weightkg","bmi")], quantile, probs = c(0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99))
stature sittingheight weightkg bmi
1% 1482.55 784.00 466.55 18.80290
5% 1525.00 803.00 513.00 20.25971
10% 1547.00 813.00 546.00 21.28893
25% 1586.25 834.00 601.00 23.07754
50% 1626.00 857.00 668.00 25.26675
75% 1672.00 879.00 745.75 27.60936
90% 1713.00 900.00 824.00 29.91074
95% 1740.00 912.00 870.75 31.65882
99% 1777.60 932.15 974.50 34.81696
#Compute the following quantiles for stature, sittingheight, weightkg, and BMI for women: 0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99
# compute some quantiles
qlist_stature <- c(0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99)
qvals_stature <- quantile(ansur_women$stature, qlist_stature)
women_stature_mean <- mean(ansur_women$stature)
women_stature_sd <- sd(ansur_women$stature)
par(las=1, bty='n')
with(ansur_women, plot(density(stature), main="women", xlab="Stature (mm)"))
# add the quantiles to the plot
abline(v=qvals_stature)
text(qvals_stature, sapply(qvals_stature,toString), y=c(seq(0.001,0.004, 0.001), seq(0.003, 0.001, -0.001)) )
curve(dnorm(x, mean=women_stature_mean, sd=women_stature_sd),
col="darkblue", lwd=2, add=TRUE, yaxt="n")
# and as a bonus let's add the quantiles from the normal approximation
qvals_women_norm <- qnorm(qlist, mean=women_stature_mean, sd=women_stature_sd)
abline(v=qvals_women_norm, col='blue')
text(qvals_stature, sapply(qvals_women_norm,function(x) substr(toString(x), 1, 4)), y=0.0015+c(seq(0.001,0.004, 0.001), seq(0.003, 0.001, -0.001)), col='blue' )

# compute some quantiles
qlist_sittingheight <- c(0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99)
qvals_sittingheight <- quantile(ansur_women$sittingheight, qlist_sittingheight)
women_sittingheight_mean <- mean(ansur_women$sittingheight)
women_sittingheight_sd <- sd(ansur_women$sittingheight)
par(las=1, bty='n')
with(ansur_women, plot(density(sittingheight), main="women", xlab="sittingheight (mm)"))
# add the quantiles to the plot
abline(v=qvals_sittingheight)
text(qvals_sittingheight, sapply(qvals_sittingheight,toString), y=c(seq(0.001,0.004, 0.001), seq(0.003, 0.001, -0.001)) )
curve(dnorm(x, mean=women_sittingheight_mean, sd=women_sittingheight_sd),
col="darkorange", lwd=2, add=TRUE, yaxt="n")
# and as a bonus let's add the quantiles from the normal approximation
qvals_women_norm <- qnorm(qlist, mean=women_sittingheight_mean, sd=women_sittingheight_sd)
abline(v=qvals_women_norm, col='darkorange')
text(qvals_sittingheight, sapply(qvals_women_norm,function(x) substr(toString(x), 1, 4)), y=0.0015+c(seq(0.001,0.004, 0.001), seq(0.003, 0.001, -0.001)), col='darkorange' )

# compute some quantiles
qlist_weightkg <- c(0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99)
qvals_weightkg <- quantile(ansur_women$weightkg, qlist_weightkg)
women_weightkg_mean <- mean(ansur_women$weightkg)
women_weightkg_sd <- sd(ansur_women$weightkg)
par(las=1, bty='n')
with(ansur_women, plot(density(weightkg), main="women", xlab="weight (kg)"))
# add the quantiles to the plot
abline(v=qvals_weightkg)
text(qvals_weightkg, sapply(qvals_weightkg,toString), y=c(seq(0.001,0.004, 0.001), seq(0.003, 0.001, -0.001)) )
curve(dnorm(x, mean=women_weightkg_mean, sd=women_weightkg_sd),
col="red", lwd=2, add=TRUE, yaxt="n")
# and as a bonus let's add the quantiles from the normal approximation
qvals_women_norm <- qnorm(qlist, mean=women_weightkg_mean, sd=women_weightkg_sd)
abline(v=qvals_women_norm, col='red')
text(qvals_weightkg, sapply(qvals_women_norm,function(x) substr(toString(x), 1, 4)), y=0.0015+c(seq(0.001,0.004, 0.001), seq(0.003, 0.001, -0.001)), col='red' )

qlist_bmi <- c(0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99)
qvals_bmi <- quantile(ansur_women$bmi, qlist_bmi)
women_bmi_mean <- mean(ansur_women$bmi)
women_stature_sd <- sd(ansur_women$bmi)
par(las=1, bty='n')
with(ansur_women, plot(density(bmi), main="women", xlab="bmi (kg/m2)"))
abline(v=qvals_bmi)
text(qvals_bmi, sapply(qvals_bmi,toString), y=c(seq(0.01,0.04, 0.01), seq(0.03, 0.01, -0.01)) )
curve(dnorm(x, mean=women_bmi_mean, sd=women_bmi_sd),
col="red", lwd=2, add=TRUE, yaxt="n")
qvals_women_norm <- qnorm(qlist, mean=women_bmi_mean, sd=women_bmi_sd)
abline(v=qvals_women_norm, col='red')
text(qvals_bmi, sapply(qvals_women_norm,function(x) substr(toString(x), 1, 4)), y=0.015+c(seq(0.01,0.04, 0.01), seq(0.03, 0.01, -0.01)), col='red' )

##### Answer for question 2:
# ranked from the closest to normally distributed by inspecting the plots are:
#1- setting height
#2- stature
#3- BMI
#4- Weight (kg)
#Make a plot of knee height sitting vs buttock-knee length for men.
#Add lines showing the 95th%ile of each variable.DONE
#What percentage of men in this dataset have both knee height and buttock-knee length less than the respective 95th%iles? Hints: If v is a vector of boolean (True/False) values, mean(v) returns the fraction that are true (sum(v) returns the number that are true). The ampersand (&) is “and” in conditionals.
plot(ansur_men$kneeheightsitting,ansur_men$buttockkneelength, pch=20, main=paste("r =", cor(ansur_men$kneeheightsitting, ansur_men$buttockkneelength)))
abline(h=quantile(ansur_men$buttockkneelength, 0.95))
abline(v=quantile(ansur_men$kneeheightsitting, 0.95))

NA
NA
NA
vec <- ansur_men$kneeheightsitting < quantile(ansur_men$kneeheightsitting, 0.95) & ansur_men$buttockkneelength < quantile(ansur_men$buttockkneelength, 0.95)
mean(vec)
[1] 0.9272415
# In this case, with a correlation between the variables of 0.84, the percentage accommodated on both variables is only slightly smaller than the univariate accommodation (0.93 vs. 0.95).
#Repeat this analysis with buttock-politeal length and hip breadth for women, except assess the number of women who have buttock popliteal length greater than the 5th percentile and hip breadth sitting less than the 95th percentile. Is this the value you expect? Why is the fraction of the population who meet the criteria different for this analysis than for the preceding male analysis? Hints: look at the quadrants of the plots; what are the correlations between the variables?
par(las=1, bty='n')
plot(ansur_women$buttockpopliteallength, ansur_women$hipbreadthsitting, pch=20, main=paste("r =", cor(ansur_women$buttockpopliteallength, ansur_women$hipbreadthsitting)))
abline(v=quantile(ansur_women$buttockpopliteallength, 0.05))
abline(h=quantile(ansur_women$hipbreadthsitting, 0.95))

#Why is the fraction of the population who meet the criteria different for this analysis than for the preceding male analysis? Hints: look at the quadrants of the plots; what are the correlations between the variables?
# Answer: by looking at the plot, especially at the corner, we see women disacommodated on the both variables are fully seperate, no omwen in the women poplulation is disacoomodated on both. Therefore, the correlation is weak.
male_means <- apply(a2m[,7:ncol(a2m)], 2, mean)
female_means <- apply(a2f[,7:ncol(a2f)], 2, mean)
mean_diffs <- male_means-female_means
Warning in male_means - female_means :
longer object length is not a multiple of shorter object length
which.max(mean_diffs)
weightkg
86
which.min(mean_diffs)
hipbreadthsitting
46
difference <- mean_diffs/(male_means+female_means)
Warning in male_means + female_means :
longer object length is not a multiple of shorter object length
which.max(difference)
Weightlbs
91
which.min(difference)
hipbreadthsitting
46
#######Answer for question 4:
#if you were to pick a single dimension by which to classify a soldier as male or female, which should you pick? Which would be the worst choice?
## According to the results, the smallest fraction is the hip breadth sitting, therefore it is the best distinguish between females and males.
#The weight in Kg is the largest fraction between mean and women, therefore its not suitable as a distinguish.
# I am surprised about the results, because I thought the weight could be one of the largest different between men and women.
male_hipbreadthlength_sd <- sd(ansur_men$hipbreadthsitting)
female_hipbreadthlsitting_mean <- mean(ansur_men$hipbreadthsitting)
female_hipbreadthlength_sd <- sd(ansur_men$hipbreadthsitting)
male_hipbreadthsitting_mean <- mean(ansur_men$hipbreadthsitting)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCmBgYHtyfQ0KYW5zdXJfbWVuJGJtaSA8LSAoYW5zdXJfbWVuJHdlaWdodGtnLzEwKS8oYW5zdXJfbWVuJHN0YXR1cmUvMTAwMCkqKjINCmFuc3VyX3dvbWVuJGJtaSA8LSAoYW5zdXJfd29tZW4kd2VpZ2h0a2cvMTApLyhhbnN1cl93b21lbiRzdGF0dXJlLzEwMDApKioyDQpzdW1tYXJ5KGFuc3VyX21lbiRibWkpDQpzdW1tYXJ5KGFuc3VyX3dvbWVuJGJtaSkNCmBgYA0KYGBge3J9DQptZXJnZShhbnN1cl9tZW4sIGFuc3VyX3dvbWVuLCBhbGw9VCkNCmBgYA0KYGBge3J9DQpsZW5ndGgobmFtZXMoYW5zdXJfd29tZW4pKSA9PSBsZW5ndGgobmFtZXMoYW5zdXJfbWVuKSkNCmBgYA0KYGBge3J9DQpucm93KGFuc3VyKSA9PSBucm93KGFuc3VyX21lbikgKyBucm93KGFuc3VyX3dvbWVuKQ0KYGBgDQpgYGB7cn0NCnN1bW1hcnkoYW5zdXJfbWVuWywxOjEwXSkNCmBgYA0KYGBge3J9DQpzYXBwbHkoYW5zdXJfbWVuW2MoInN0YXR1cmUiLCAic2l0dGluZ2hlaWdodCIsICJ3ZWlnaHRrZyIsImJtaSIpXSwgbWVhbikNCnNhcHBseShhbnN1cl93b21lbltjKCJzdGF0dXJlIiwgInNpdHRpbmdoZWlnaHQiLCAid2VpZ2h0a2ciLCJibWkiKV0sIG1lYW4pDQpzYXBwbHkoYW5zdXJfbWVuW2MoInN0YXR1cmUiLCAic2l0dGluZ2hlaWdodCIsICJ3ZWlnaHRrZyIsImJtaSIpXSwgc2QpDQpzYXBwbHkoYW5zdXJfd29tZW5bYygic3RhdHVyZSIsICJzaXR0aW5naGVpZ2h0IiwgIndlaWdodGtnIiwiYm1pIildLCBzZCkNCmBgYA0KYGBge3J9DQojQ29tcHV0ZSB0aGUgZm9sbG93aW5nIHF1YW50aWxlcyBmb3Igc3RhdHVyZSwgc2l0dGluZ2hlaWdodCwgd2VpZ2h0a2csIGFuZCBCTUkgZm9yIHdvbWVuOiAwLjAxLCAwLjA1LCAwLjEsIDAuMjUsIDAuNSwgMC43NSwgMC45LCAwLjk1LCAwLjk5DQoNCnNhcHBseShhbnN1cl93b21lbltjKCJzdGF0dXJlIiwgInNpdHRpbmdoZWlnaHQiLCAid2VpZ2h0a2ciLCJibWkiKV0sIHF1YW50aWxlLCBwcm9icyA9IGMoMC4wMSwgMC4wNSwgMC4xLCAwLjI1LCAwLjUsIDAuNzUsIDAuOSwgMC45NSwgMC45OSkpDQoNCmBgYA0KYGBge3J9DQojQ29tcHV0ZSB0aGUgZm9sbG93aW5nIHF1YW50aWxlcyBmb3Igc3RhdHVyZSwgc2l0dGluZ2hlaWdodCwgd2VpZ2h0a2csIGFuZCBCTUkgZm9yIHdvbWVuOiAwLjAxLCAwLjA1LCAwLjEsIDAuMjUsIDAuNSwgMC43NSwgMC45LCAwLjk1LCAwLjk5DQoNCg0KcWxpc3Rfc3RhdHVyZSA8LSBjKDAuMDEsIDAuMDUsIDAuMSwgMC4yNSwgMC41LCAwLjc1LCAwLjksIDAuOTUsIDAuOTkpDQpxdmFsc19zdGF0dXJlIDwtIHF1YW50aWxlKGFuc3VyX3dvbWVuJHN0YXR1cmUsIHFsaXN0X3N0YXR1cmUpDQp3b21lbl9zdGF0dXJlX21lYW4gPC0gbWVhbihhbnN1cl93b21lbiRzdGF0dXJlKQ0Kd29tZW5fc3RhdHVyZV9zZCA8LSAgc2QoYW5zdXJfd29tZW4kc3RhdHVyZSkNCnBhcihsYXM9MSwgYnR5PSduJykNCndpdGgoYW5zdXJfd29tZW4sIHBsb3QoZGVuc2l0eShzdGF0dXJlKSwgbWFpbj0id29tZW4iLCB4bGFiPSJTdGF0dXJlIChtbSkiKSkNCg0KYWJsaW5lKHY9cXZhbHNfc3RhdHVyZSkNCnRleHQocXZhbHNfc3RhdHVyZSwgc2FwcGx5KHF2YWxzX3N0YXR1cmUsdG9TdHJpbmcpLCB5PWMoc2VxKDAuMDAxLDAuMDA0LCAwLjAwMSksIHNlcSgwLjAwMywgMC4wMDEsIC0wLjAwMSkpICkNCmN1cnZlKGRub3JtKHgsIG1lYW49d29tZW5fc3RhdHVyZV9tZWFuLCBzZD13b21lbl9zdGF0dXJlX3NkKSwgDQogICAgICBjb2w9ImRhcmtibHVlIiwgbHdkPTIsIGFkZD1UUlVFLCB5YXh0PSJuIikNCg0KcXZhbHNfd29tZW5fbm9ybSA8LSBxbm9ybShxbGlzdCwgbWVhbj13b21lbl9zdGF0dXJlX21lYW4sIHNkPXdvbWVuX3N0YXR1cmVfc2QpDQphYmxpbmUodj1xdmFsc193b21lbl9ub3JtLCBjb2w9J2JsdWUnKQ0KdGV4dChxdmFsc19zdGF0dXJlLCBzYXBwbHkocXZhbHNfd29tZW5fbm9ybSxmdW5jdGlvbih4KSBzdWJzdHIodG9TdHJpbmcoeCksIDEsIDQpKSwgeT0wLjAwMTUrYyhzZXEoMC4wMDEsMC4wMDQsIDAuMDAxKSwgc2VxKDAuMDAzLCAwLjAwMSwgLTAuMDAxKSksIGNvbD0nYmx1ZScgKQ0KYGBgDQpgYGB7cn0NCg0KcWxpc3Rfc2l0dGluZ2hlaWdodCA8LSBjKDAuMDEsIDAuMDUsIDAuMSwgMC4yNSwgMC41LCAwLjc1LCAwLjksIDAuOTUsIDAuOTkpDQpxdmFsc19zaXR0aW5naGVpZ2h0IDwtIHF1YW50aWxlKGFuc3VyX3dvbWVuJHNpdHRpbmdoZWlnaHQsIHFsaXN0X3NpdHRpbmdoZWlnaHQpDQp3b21lbl9zaXR0aW5naGVpZ2h0X21lYW4gPC0gbWVhbihhbnN1cl93b21lbiRzaXR0aW5naGVpZ2h0KQ0Kd29tZW5fc2l0dGluZ2hlaWdodF9zZCA8LSAgc2QoYW5zdXJfd29tZW4kc2l0dGluZ2hlaWdodCkNCnBhcihsYXM9MSwgYnR5PSduJykNCndpdGgoYW5zdXJfd29tZW4sIHBsb3QoZGVuc2l0eShzaXR0aW5naGVpZ2h0KSwgbWFpbj0id29tZW4iLCB4bGFiPSJzaXR0aW5naGVpZ2h0IChtbSkiKSkNCg0KYWJsaW5lKHY9cXZhbHNfc2l0dGluZ2hlaWdodCkNCnRleHQocXZhbHNfc2l0dGluZ2hlaWdodCwgc2FwcGx5KHF2YWxzX3NpdHRpbmdoZWlnaHQsdG9TdHJpbmcpLCB5PWMoc2VxKDAuMDAxLDAuMDA0LCAwLjAwMSksIHNlcSgwLjAwMywgMC4wMDEsIC0wLjAwMSkpICkNCmN1cnZlKGRub3JtKHgsIG1lYW49d29tZW5fc2l0dGluZ2hlaWdodF9tZWFuLCBzZD13b21lbl9zaXR0aW5naGVpZ2h0X3NkKSwgDQogICAgICBjb2w9ImRhcmtvcmFuZ2UiLCBsd2Q9MiwgYWRkPVRSVUUsIHlheHQ9Im4iKQ0KDQpxdmFsc193b21lbl9ub3JtIDwtIHFub3JtKHFsaXN0LCBtZWFuPXdvbWVuX3NpdHRpbmdoZWlnaHRfbWVhbiwgc2Q9d29tZW5fc2l0dGluZ2hlaWdodF9zZCkNCmFibGluZSh2PXF2YWxzX3dvbWVuX25vcm0sIGNvbD0nZGFya29yYW5nZScpDQp0ZXh0KHF2YWxzX3NpdHRpbmdoZWlnaHQsIHNhcHBseShxdmFsc193b21lbl9ub3JtLGZ1bmN0aW9uKHgpIHN1YnN0cih0b1N0cmluZyh4KSwgMSwgNCkpLCB5PTAuMDAxNStjKHNlcSgwLjAwMSwwLjAwNCwgMC4wMDEpLCBzZXEoMC4wMDMsIDAuMDAxLCAtMC4wMDEpKSwgY29sPSdkYXJrb3JhbmdlJyApDQpgYGANCg0KYGBge3J9DQoNCnFsaXN0X3dlaWdodGtnIDwtIGMoMC4wMSwgMC4wNSwgMC4xLCAwLjI1LCAwLjUsIDAuNzUsIDAuOSwgMC45NSwgMC45OSkNCnF2YWxzX3dlaWdodGtnIDwtIHF1YW50aWxlKGFuc3VyX3dvbWVuJHdlaWdodGtnLCBxbGlzdF93ZWlnaHRrZykNCndvbWVuX3dlaWdodGtnX21lYW4gPC0gbWVhbihhbnN1cl93b21lbiR3ZWlnaHRrZykNCndvbWVuX3dlaWdodGtnX3NkIDwtICBzZChhbnN1cl93b21lbiR3ZWlnaHRrZykNCnBhcihsYXM9MSwgYnR5PSduJykNCndpdGgoYW5zdXJfd29tZW4sIHBsb3QoZGVuc2l0eSh3ZWlnaHRrZyksIG1haW49IndvbWVuIiwgeGxhYj0id2VpZ2h0IChrZykiKSkNCg0KYWJsaW5lKHY9cXZhbHNfd2VpZ2h0a2cpDQp0ZXh0KHF2YWxzX3dlaWdodGtnLCBzYXBwbHkocXZhbHNfd2VpZ2h0a2csdG9TdHJpbmcpLCB5PWMoc2VxKDAuMDAxLDAuMDA0LCAwLjAwMSksIHNlcSgwLjAwMywgMC4wMDEsIC0wLjAwMSkpICkNCmN1cnZlKGRub3JtKHgsIG1lYW49d29tZW5fd2VpZ2h0a2dfbWVhbiwgc2Q9d29tZW5fd2VpZ2h0a2dfc2QpLCANCiAgICAgIGNvbD0icmVkIiwgbHdkPTIsIGFkZD1UUlVFLCB5YXh0PSJuIikNCg0KcXZhbHNfd29tZW5fbm9ybSA8LSBxbm9ybShxbGlzdCwgbWVhbj13b21lbl93ZWlnaHRrZ19tZWFuLCBzZD13b21lbl93ZWlnaHRrZ19zZCkNCmFibGluZSh2PXF2YWxzX3dvbWVuX25vcm0sIGNvbD0ncmVkJykNCnRleHQocXZhbHNfd2VpZ2h0a2csIHNhcHBseShxdmFsc193b21lbl9ub3JtLGZ1bmN0aW9uKHgpIHN1YnN0cih0b1N0cmluZyh4KSwgMSwgNCkpLCB5PTAuMDAxNStjKHNlcSgwLjAwMSwwLjAwNCwgMC4wMDEpLCBzZXEoMC4wMDMsIDAuMDAxLCAtMC4wMDEpKSwgY29sPSdyZWQnICkNCmBgYA0KYGBge3J9DQoNCg0KcWxpc3RfYm1pIDwtIGMoMC4wMSwgMC4wNSwgMC4xLCAwLjI1LCAwLjUsIDAuNzUsIDAuOSwgMC45NSwgMC45OSkNCnF2YWxzX2JtaSA8LSBxdWFudGlsZShhbnN1cl93b21lbiRibWksIHFsaXN0X2JtaSkNCndvbWVuX2JtaV9tZWFuIDwtIG1lYW4oYW5zdXJfd29tZW4kYm1pKQ0Kd29tZW5fc3RhdHVyZV9zZCA8LSAgc2QoYW5zdXJfd29tZW4kYm1pKQ0KcGFyKGxhcz0xLCBidHk9J24nKQ0Kd2l0aChhbnN1cl93b21lbiwgcGxvdChkZW5zaXR5KGJtaSksIG1haW49IndvbWVuIiwgeGxhYj0iYm1pIChrZy9tMikiKSkNCg0KYWJsaW5lKHY9cXZhbHNfYm1pKQ0KdGV4dChxdmFsc19ibWksIHNhcHBseShxdmFsc19ibWksdG9TdHJpbmcpLCAgeT1jKHNlcSgwLjAxLDAuMDQsIDAuMDEpLCBzZXEoMC4wMywgMC4wMSwgLTAuMDEpKSApDQpjdXJ2ZShkbm9ybSh4LCBtZWFuPXdvbWVuX2JtaV9tZWFuLCBzZD13b21lbl9ibWlfc2QpLCANCiAgICAgIGNvbD0icmVkIiwgbHdkPTIsIGFkZD1UUlVFLCB5YXh0PSJuIikNCg0KcXZhbHNfd29tZW5fbm9ybSA8LSBxbm9ybShxbGlzdCwgbWVhbj13b21lbl9ibWlfbWVhbiwgc2Q9d29tZW5fYm1pX3NkKQ0KYWJsaW5lKHY9cXZhbHNfd29tZW5fbm9ybSwgY29sPSdyZWQnKQ0KdGV4dChxdmFsc19ibWksIHNhcHBseShxdmFsc193b21lbl9ub3JtLGZ1bmN0aW9uKHgpIHN1YnN0cih0b1N0cmluZyh4KSwgMSwgNCkpLCB5PTAuMDE1K2Moc2VxKDAuMDEsMC4wNCwgMC4wMSksIHNlcSgwLjAzLCAwLjAxLCAtMC4wMSkpLCBjb2w9J3JlZCcgKQ0KDQpgYGANCmBgYHtyfQ0KIyMjIyMgQW5zd2VyIGZvciBxdWVzdGlvbiAyOg0KDQojIHJhbmtlZCBmcm9tIHRoZSBjbG9zZXN0IHRvIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGJ5IGluc3BlY3RpbmcgdGhlIHBsb3RzIGFyZTogDQojMS0gc2V0dGluZyBoZWlnaHQgDQojMi0gc3RhdHVyZQ0KIzMtIEJNSSANCiM0LSBXZWlnaHQgKGtnKQ0KYGBgDQoNCg0KYGBge3J9DQojTWFrZSBhIHBsb3Qgb2Yga25lZSBoZWlnaHQgc2l0dGluZyB2cyBidXR0b2NrLWtuZWUgbGVuZ3RoIGZvciBtZW4uDQojQWRkIGxpbmVzIHNob3dpbmcgdGhlIDk1dGglaWxlIG9mIGVhY2ggdmFyaWFibGUuRE9ORQ0KI1doYXQgcGVyY2VudGFnZSBvZiBtZW4gaW4gdGhpcyBkYXRhc2V0IGhhdmUgYm90aCBrbmVlIGhlaWdodCBhbmQgYnV0dG9jay1rbmVlIGxlbmd0aCBsZXNzIHRoYW4gdGhlIHJlc3BlY3RpdmUgOTV0aCVpbGVzPyBIaW50czogSWYgdiBpcyBhIHZlY3RvciBvZiBib29sZWFuIChUcnVlL0ZhbHNlKSB2YWx1ZXMsIG1lYW4odikgcmV0dXJucyB0aGUgZnJhY3Rpb24gdGhhdCBhcmUgdHJ1ZSAoc3VtKHYpIHJldHVybnMgdGhlIG51bWJlciB0aGF0IGFyZSB0cnVlKS4gVGhlIGFtcGVyc2FuZCAoJikgaXMg4oCcYW5k4oCdIGluIGNvbmRpdGlvbmFscy4NCg0KDQoNCg0KDQpwbG90KGFuc3VyX21lbiRrbmVlaGVpZ2h0c2l0dGluZyxhbnN1cl9tZW4kYnV0dG9ja2tuZWVsZW5ndGgsIHBjaD0yMCwgbWFpbj1wYXN0ZSgiciA9IiwgY29yKGFuc3VyX21lbiRrbmVlaGVpZ2h0c2l0dGluZywgYW5zdXJfbWVuJGJ1dHRvY2trbmVlbGVuZ3RoKSkpDQphYmxpbmUoaD1xdWFudGlsZShhbnN1cl9tZW4kYnV0dG9ja2tuZWVsZW5ndGgsIDAuOTUpKQ0KYWJsaW5lKHY9cXVhbnRpbGUoYW5zdXJfbWVuJGtuZWVoZWlnaHRzaXR0aW5nLCAwLjk1KSkNCg0KDQoNCmBgYA0KYGBge3J9DQp2ZWMgPC0gYW5zdXJfbWVuJGtuZWVoZWlnaHRzaXR0aW5nIDwgcXVhbnRpbGUoYW5zdXJfbWVuJGtuZWVoZWlnaHRzaXR0aW5nLCAwLjk1KSAmIGFuc3VyX21lbiRidXR0b2Nra25lZWxlbmd0aCA8IHF1YW50aWxlKGFuc3VyX21lbiRidXR0b2Nra25lZWxlbmd0aCwgMC45NSkNCm1lYW4odmVjKQ0KIyBJbiB0aGlzIGNhc2UsIHdpdGggYSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMgb2YgMC44NCwgdGhlIHBlcmNlbnRhZ2UgYWNjb21tb2RhdGVkIG9uIGJvdGggdmFyaWFibGVzIGlzIG9ubHkgc2xpZ2h0bHkgc21hbGxlciB0aGFuIHRoZSB1bml2YXJpYXRlIGFjY29tbW9kYXRpb24gKDAuOTMgdnMuIDAuOTUpLCB3aGljaCBpcyAwLjkyLg0KYGBgDQoNCmBgYHtyfQ0KI1JlcGVhdCB0aGlzIGFuYWx5c2lzIHdpdGggYnV0dG9jay1wb2xpdGVhbCBsZW5ndGggYW5kIGhpcCBicmVhZHRoIGZvciB3b21lbiwgZXhjZXB0IGFzc2VzcyB0aGUgbnVtYmVyIG9mIHdvbWVuIHdobyBoYXZlIGJ1dHRvY2sgcG9wbGl0ZWFsIGxlbmd0aCBncmVhdGVyIHRoYW4gdGhlIDV0aCBwZXJjZW50aWxlIGFuZCBoaXAgYnJlYWR0aCBzaXR0aW5nIGxlc3MgdGhhbiB0aGUgOTV0aCBwZXJjZW50aWxlLiBJcyB0aGlzIHRoZSB2YWx1ZSB5b3UgZXhwZWN0PyANCnBhcihsYXM9MSwgYnR5PSduJykNCnBsb3QoYW5zdXJfd29tZW4kYnV0dG9ja3BvcGxpdGVhbGxlbmd0aCwgYW5zdXJfd29tZW4kaGlwYnJlYWR0aHNpdHRpbmcsIHBjaD0yMCwgIG1haW49cGFzdGUoInIgPSIsIGNvcihhbnN1cl93b21lbiRidXR0b2NrcG9wbGl0ZWFsbGVuZ3RoLCBhbnN1cl93b21lbiRoaXBicmVhZHRoc2l0dGluZykpKQ0KYWJsaW5lKHY9cXVhbnRpbGUoYW5zdXJfd29tZW4kYnV0dG9ja3BvcGxpdGVhbGxlbmd0aCwgMC4wNSkpDQphYmxpbmUoaD1xdWFudGlsZShhbnN1cl93b21lbiRoaXBicmVhZHRoc2l0dGluZywgMC45NSkpDQpgYGANCmBgYHtyfQ0KI1doeSBpcyB0aGUgZnJhY3Rpb24gb2YgdGhlIHBvcHVsYXRpb24gd2hvIG1lZXQgdGhlIGNyaXRlcmlhIGRpZmZlcmVudCBmb3IgdGhpcyBhbmFseXNpcyB0aGFuIGZvciB0aGUgcHJlY2VkaW5nIG1hbGUgYW5hbHlzaXM/IEhpbnRzOiBsb29rIGF0IHRoZSBxdWFkcmFudHMgb2YgdGhlIHBsb3RzOyB3aGF0IGFyZSB0aGUgY29ycmVsYXRpb25zIGJldHdlZW4gdGhlIHZhcmlhYmxlcz8NCg0KIyBBbnN3ZXI6IGJ5IGxvb2tpbmcgYXQgdGhlIHBsb3QsIGVzcGVjaWFsbHkgYXQgdGhlIGNvcm5lciwgd2Ugc2VlIHdvbWVuIGRpc2Fjb21tb2RhdGVkIG9uIHRoZSBib3RoIHZhcmlhYmxlcyBhcmUgZnVsbHkgc2VwZXJhdGUsIG5vIG9td2VuIGluIHRoZSB3b21lbiBwb3BsdWxhdGlvbiBpcyBkaXNhY29vbW9kYXRlZCBvbiBib3RoLiBUaGVyZWZvcmUsIHRoZSBjb3JyZWxhdGlvbiBpcyB3ZWFrLiANCmBgYA0KDQoNCmBgYHtyfQ0KbWFsZV9tZWFucyA8LSBhcHBseShhMm1bLDc6bmNvbChhMm0pXSwgMiwgbWVhbikNCmZlbWFsZV9tZWFucyA8LSBhcHBseShhMmZbLDc6bmNvbChhMmYpXSwgMiwgbWVhbikNCm1lYW5fZGlmZnMgPC0gbWFsZV9tZWFucy1mZW1hbGVfbWVhbnMNCndoaWNoLm1heChtZWFuX2RpZmZzKQ0Kd2hpY2gubWluKG1lYW5fZGlmZnMpDQpkaWZmZXJlbmNlIDwtIG1lYW5fZGlmZnMvKG1hbGVfbWVhbnMrZmVtYWxlX21lYW5zKQ0Kd2hpY2gubWF4KGRpZmZlcmVuY2UpDQp3aGljaC5taW4oZGlmZmVyZW5jZSkNCg0KDQpgYGANCmBgYHtyfQ0KIyMjIyMjI0Fuc3dlciBmb3IgcXVlc3Rpb24gNDogDQoNCiNpZiB5b3Ugd2VyZSB0byBwaWNrIGEgc2luZ2xlIGRpbWVuc2lvbiBieSB3aGljaCB0byBjbGFzc2lmeSBhIHNvbGRpZXIgYXMgbWFsZSBvciBmZW1hbGUsIHdoaWNoIHNob3VsZCB5b3UgcGljaz8gV2hpY2ggd291bGQgYmUgdGhlIHdvcnN0IGNob2ljZT8NCiMjIEFjY29yZGluZyB0byB0aGUgcmVzdWx0cywgdGhlIHNtYWxsZXN0IGZyYWN0aW9uIGlzIHRoZSBoaXAgYnJlYWR0aCBzaXR0aW5nLCB0aGVyZWZvcmUgaXQgaXMgdGhlIGJlc3QgZGlzdGluZ3Vpc2ggYmV0d2VlbiBmZW1hbGVzIGFuZCBtYWxlcy4NCg0KI1RoZSB3ZWlnaHQgaW4gS2cgaXMgdGhlIGxhcmdlc3QgZnJhY3Rpb24gYmV0d2VlbiBtZWFuIGFuZCB3b21lbiwgdGhlcmVmb3JlIGl0cyBub3Qgc3VpdGFibGUgYXMgYSBkaXN0aW5ndWlzaC4gDQojIEkgYW0gc3VycHJpc2VkIGFib3V0IHRoZSByZXN1bHRzLCBiZWNhdXNlIEkgdGhvdWdodCB0aGUgd2VpZ2h0IGNvdWxkIGJlIG9uZSBvZiB0aGUgbGFyZ2VzdCBkaWZmZXJlbnQgYmV0d2VlbiBtZW4gYW5kIHdvbWVuLiANCmBgYA0KDQpgYGB7cn0NCg0KbWFsZV9oaXBicmVhZHRobGVuZ3RoX3NkIDwtICBzZChhbnN1cl9tZW4kaGlwYnJlYWR0aHNpdHRpbmcpDQpmZW1hbGVfaGlwYnJlYWR0aGxzaXR0aW5nX21lYW4gPC0gbWVhbihhbnN1cl9tZW4kaGlwYnJlYWR0aHNpdHRpbmcpDQpmZW1hbGVfaGlwYnJlYWR0aGxlbmd0aF9zZCA8LSAgc2QoYW5zdXJfbWVuJGhpcGJyZWFkdGhzaXR0aW5nKQ0KbWFsZV9oaXBicmVhZHRoc2l0dGluZ19tZWFuIDwtIG1lYW4oYW5zdXJfbWVuJGhpcGJyZWFkdGhzaXR0aW5nKQ0KYGBgDQoNCg==