Problem 1
For this problem, we are asked to summarize and compare Asymptotic
and Bootstrap Sampling distributions. We are asked to outline the key
assumptions, practical applications, and discuss when and why to use one
over the other.
Asymptotic and Bootstrap Sampling Distributions are both probability
distributions that are used to estimate sample statistics, like means or
standard deviations. They are both used when the distribution of any
given population is unknown, or if you don’t have access to any more
ways to gather data for whatever reason.
Asympotitic
Distributions
Asymptotic Distributions rely on assumptions from the central limit
theorem. The central limit theorem says that if we take a random sample
from any given population, then we can say that as we continually
increase the sample size (gather more data points), any distribution of
a function of said sample should eventually be normally distributed.
Asymptotic Distributions are generally used if a sample size is
“large” or when the sample resembles a distribution we are familiar
with, like a normal, chi-square, etc.
Bootstrapped
Distributions
Bootstrapping is a nonparametric resampling method in which samples
are taken from a sample. In other words, if you have a sample, we treat
that sample as our “population” and we would then randomly sample with
replacement from that “population”. From there, we can take functions of
theses new samples and use those as estimates.
Bootstrapping is generally used when the original sample is small or
when data is more complex. There is one similarity with asymptotic
distributions: as you take more and more samples, the sampling
distribution of a given statistic will eventuall converge to a normal
distribution.
Problem 2
For this problem, we are interested in analyzing sample means and
variances via bootstrapping. To do this, we will use a data set that
consists of the volume of coffee sold daily at two different coffee
shops:
coffee <- c(2850, 3200, 2900, 3100, 2950, 7800, 8100, 7900, 3300, 3050, 4000, 4200, 3150, 3400, 7700, 8200, 3250, 4400, 3100, 4200, 4500, 4800, 4300, 8500, 8200, 8900, 8700, 3250, 3000, 4600, 4100, 8400, 8800, 3350, 4700, 3100, 8100, 3050, 8300, 4100, 3100, 8300, 8900, 8200, 4400, 4500, 3250, 4600, 8400, 3300, 4200, 4500, 4800, 4300, 8500)
Part A
I believe that we can use the central limit theorem to derive the
asymptotic distribution of the sample mean because our sample size is
greater than 30 (n = 55 in our case).
length(coffee)
[1] 55
Part B
For this part, we will do the bootstrap samples and calculate the
sample means for each. They will then be plotted via a histogram.
Afterwards we will generate and plot a kernel density estimate for the
sample means.
Let’s start by generating and plotting the bootstrapped sampling
distribution for the mean. For the sampling distribution, 1000 samples
will be used. We will also plot a kernel density curve on the plot:
original.sample = sample(coffee, # population of all coffee volume sales
55, # sample size = 55
replace = FALSE # sample without replacement
)
### Bootstrap sampling begins
bt.sample.mean.vec = NULL # define an empty vector to hold sample means of repeated samples.
for(i in 1:1000){ # starting for-loop to take bootstrap samples with n = 55
ith.bt.sample = sample(x = original.sample, # Original sample with 55 Daily
size = 55, # sample size = 55 MUST be equal to the sample size!!
replace = TRUE # MUST use WITH REPLACEMENT!!
) # this is the i-th Bootstrap sample
bt.sample.mean.vec[i] = mean(ith.bt.sample) # calculate the mean of i-th bootstrap sample and
# save it in the empty vector: sample.bt.mean.vec
}
###
hist(bt.sample.mean.vec, # data from sample
breaks = 14, # specify number of vertical bars
probability = TRUE,
xlab = "Bootstrapped Sample Means", # change the label of x-axis
# add a title to the histogram
main = "Bootstrap Sampling Distribution of Sample Means",
cex.main = 0.9, col = "lightblue"
)
lines(density(bt.sample.mean.vec, n = 1000), col = "red", lwd = 2)

# overlays the kernel density estimate for the sample mean
The histogram shape looks pretty normal, although slightly skewed.
The kernel density (in red) looks rough, but does resemble a normal
curve. Let’s call the kernel seperately and compare:
density(bt.sample.mean.vec, n = 1000)
Call:
density.default(x = bt.sample.mean.vec, n = 1000)
Data: bt.sample.mean.vec (1000 obs.); Bandwidth 'bw' = 69.4
x y
Min. :4103 Min. :6.470e-08
1st Qu.:4667 1st Qu.:2.124e-05
Median :5231 Median :2.768e-04
Mean :5231 Mean :4.426e-04
3rd Qu.:5796 3rd Qu.:8.520e-04
Max. :6360 Max. :1.268e-03
mean(coffee)
[1] 5250
The actual sample mean is 5250. Even though the estimate for the mean
will change every time you run a sample, it does stay relatively close
to the mean (usually between 5220 and 5280). This seems to do a good job
of estimating the sample mean.
Part C
For this part, we will repeat what we did in parts A and B to
estimate the sample variance.
I still think that the central limit theorem can apply to estimate
the sample variance. Our sample size isn’t changing (n = 55) and the
amount of samples we will take won’t change either (samples = 1000).
Now for the bootstrapped samples and the kernel density estimate:
original.sample = sample(coffee, # population of all daily coffee sales
55, # sample size = 55 values in the sample
replace = FALSE # sample without replacement
)
### Bootstrap sampling begins
bt.sample.var.vec = NULL # define an empty vector to hold sample means of repeated samples.
for(i in 1:1000){ # starting for-loop to take bootstrap samples with n = 55
ith.bt.sample = sample(x = original.sample, # Original sample with 55 WCU students' heights
size = 55, # sample size = 55 MUST be equal to the sample size!!
replace = TRUE # MUST use WITH REPLACEMENT!!
) # this is the i-th Bootstrap sample
bt.sample.var.vec[i] = var(ith.bt.sample) # calculate the variance of i-th bootstrap sample and
# save it in the empty vector: sample.bt.var.vec
}
###
hist(bt.sample.var.vec, # data used for histogram
breaks = 14, # specify number of vertical bars
probability = TRUE,
xlab = "Bootstrap Sample Variance", # change the label of x-axis
# add a title to the histogram
main="Bootstrap Sampling Distribution of Sample Variances",
cex.main = 0.9,
col.main = "navy", col = "lightblue")
lines(density(bt.sample.var.vec), col = "red", lwd = 2)
Although it resembles a normal distribution, there seems to be a lot
more skew compared to the sampling distribution of the mean. I believe
some of the potential skew may be coming from just how the graph looks.
I don’t think the skew is as bad as it looks.
density(bt.sample.var.vec, n = 1000)
Call:
density.default(x = bt.sample.var.vec, n = 1000)
Data: bt.sample.var.vec (1000 obs.); Bandwidth 'bw' = 1.245e+05
x y
Min. :1909410 Min. :3.570e-11
1st Qu.:3075557 1st Qu.:5.538e-09
Median :4241705 Median :7.790e-08
Mean :4241705 Mean :2.142e-07
3rd Qu.:5407852 3rd Qu.:3.824e-07
Max. :6573999 Max. :7.415e-07
var(coffee)
[1] 5030833
The actual sample variance is 5,030,833. The Kernel Density Estimate
usually falls between 4,200,000 and 4,400,000. In rare cases, it may
exceed 4,400,000. However, if we keep running the code, the peak of the
histograms generated usually float around the 5,000,000 mark. So I think
we did a good enough job estimating the sample variance as well.
LS0tDQp0aXRsZTogIlNUQSA1MDYgSG9tZXdvcmsgMzogUmVzYW1wbGluZyBNZXRob2RzIg0KYXV0aG9yOiAiSWFuIFZhbldyaWdodCINCmRhdGU6ICIwMi8xNS8yMDI2Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogMw0KICAgIGZpZ19oZWlnaHQ6IDMNCiAgd29yZF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQojVE9DOjpiZWZvcmUgew0KICBjb250ZW50OiAiVGFibGUgb2YgQ29udGVudHMiOw0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1zaXplOiAxLjJlbTsNCiAgZGlzcGxheTogYmxvY2s7DQogIGNvbG9yOiBuYXZ5Ow0KICBtYXJnaW4tYm90dG9tOiAxMHB4Ow0KfQ0KDQoNCmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8NCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCg0KaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8NCiAgZm9udC1zaXplOiAyMnB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KfQ0KDQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE1cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMSAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTZweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoNCB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovDQouaGVhZGVyLXNlY3Rpb24tbnVtYmVyOjphZnRlciB7DQogIGNvbnRlbnQ6ICIuIjsNCg0KYm9keSB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCg0KcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KfQ0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoInBhbmRlciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJwYW5kZXIiKQ0KICAgbGlicmFyeShwYW5kZXIpDQp9DQppZiAoIXJlcXVpcmUoImdncGxvdDIiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCiAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCg0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KICBsaWJyYXJ5KHBsb3RseSkNCn0NCg0KIyMgbGlicmFyeShsZWFwcykNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgICMgc29tZXRpbWVzLCB5b3UgY29kZSBtYXkgcHJvZHVjZSB3YXJuaW5nIG1lc3NhZ2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdSBjYW4gY2hvb3NlIHRvIGluY2x1ZGUgdGhlIHdhcm5pbmcgbWVzc2FnZXMgaW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgICAjIHlvdSBjYW4gYWxzbyBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiB0aGUgb3V0cHV0IGZpbGUuDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQQ0KICAgICAgICAgICAgICAgICAgICAgICkgIA0KYGBgDQoNClwNCg0KIyBQcm9ibGVtIDENCkZvciB0aGlzIHByb2JsZW0sIHdlIGFyZSBhc2tlZCB0byBzdW1tYXJpemUgYW5kIGNvbXBhcmUgQXN5bXB0b3RpYyBhbmQgQm9vdHN0cmFwIFNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMuIFdlIGFyZSBhc2tlZCB0byBvdXRsaW5lIHRoZSBrZXkgYXNzdW1wdGlvbnMsIHByYWN0aWNhbCBhcHBsaWNhdGlvbnMsIGFuZCBkaXNjdXNzIHdoZW4gYW5kIHdoeSB0byB1c2Ugb25lIG92ZXIgdGhlIG90aGVyLg0KDQpBc3ltcHRvdGljIGFuZCBCb290c3RyYXAgU2FtcGxpbmcgRGlzdHJpYnV0aW9ucyBhcmUgYm90aCBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb25zIHRoYXQgYXJlIHVzZWQgdG8gZXN0aW1hdGUgc2FtcGxlIHN0YXRpc3RpY3MsIGxpa2UgbWVhbnMgb3Igc3RhbmRhcmQgZGV2aWF0aW9ucy4gVGhleSBhcmUgYm90aCB1c2VkIHdoZW4gdGhlIGRpc3RyaWJ1dGlvbiBvZiBhbnkgZ2l2ZW4gcG9wdWxhdGlvbiBpcyB1bmtub3duLCBvciBpZiB5b3UgZG9uJ3QgaGF2ZSBhY2Nlc3MgdG8gYW55IG1vcmUgd2F5cyB0byBnYXRoZXIgZGF0YSBmb3Igd2hhdGV2ZXIgcmVhc29uLg0KDQojIyBBc3ltcG90aXRpYyBEaXN0cmlidXRpb25zDQpBc3ltcHRvdGljIERpc3RyaWJ1dGlvbnMgcmVseSBvbiBhc3N1bXB0aW9ucyBmcm9tIHRoZSBjZW50cmFsIGxpbWl0IHRoZW9yZW0uIFRoZSBjZW50cmFsIGxpbWl0IHRoZW9yZW0gc2F5cyB0aGF0IGlmIHdlIHRha2UgYSByYW5kb20gc2FtcGxlIGZyb20gYW55IGdpdmVuIHBvcHVsYXRpb24sIHRoZW4gd2UgY2FuIHNheSB0aGF0IGFzIHdlIGNvbnRpbnVhbGx5IGluY3JlYXNlIHRoZSBzYW1wbGUgc2l6ZSAoZ2F0aGVyIG1vcmUgZGF0YSBwb2ludHMpLCBhbnkgZGlzdHJpYnV0aW9uIG9mIGEgZnVuY3Rpb24gb2Ygc2FpZCBzYW1wbGUgc2hvdWxkIGV2ZW50dWFsbHkgYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQoNCkFzeW1wdG90aWMgRGlzdHJpYnV0aW9ucyBhcmUgZ2VuZXJhbGx5IHVzZWQgaWYgYSBzYW1wbGUgc2l6ZSBpcyAibGFyZ2UiIG9yIHdoZW4gdGhlIHNhbXBsZSByZXNlbWJsZXMgYSBkaXN0cmlidXRpb24gd2UgYXJlIGZhbWlsaWFyIHdpdGgsIGxpa2UgYSBub3JtYWwsIGNoaS1zcXVhcmUsIGV0Yy4gDQoNCiMjIEJvb3RzdHJhcHBlZCBEaXN0cmlidXRpb25zDQpCb290c3RyYXBwaW5nIGlzIGEgbm9ucGFyYW1ldHJpYyByZXNhbXBsaW5nIG1ldGhvZCBpbiB3aGljaCBzYW1wbGVzIGFyZSB0YWtlbiBmcm9tIGEgc2FtcGxlLiBJbiBvdGhlciB3b3JkcywgaWYgeW91IGhhdmUgYSBzYW1wbGUsIHdlIHRyZWF0IHRoYXQgc2FtcGxlIGFzIG91ciAicG9wdWxhdGlvbiIgYW5kIHdlIHdvdWxkIHRoZW4gcmFuZG9tbHkgc2FtcGxlIHdpdGggcmVwbGFjZW1lbnQgZnJvbSB0aGF0ICJwb3B1bGF0aW9uIi4gRnJvbSB0aGVyZSwgd2UgY2FuIHRha2UgZnVuY3Rpb25zIG9mIHRoZXNlcyBuZXcgc2FtcGxlcyBhbmQgdXNlIHRob3NlIGFzIGVzdGltYXRlcy4NCg0KQm9vdHN0cmFwcGluZyBpcyBnZW5lcmFsbHkgdXNlZCB3aGVuIHRoZSBvcmlnaW5hbCBzYW1wbGUgaXMgc21hbGwgb3Igd2hlbiBkYXRhIGlzIG1vcmUgY29tcGxleC4gVGhlcmUgaXMgb25lIHNpbWlsYXJpdHkgd2l0aCBhc3ltcHRvdGljIGRpc3RyaWJ1dGlvbnM6IGFzIHlvdSB0YWtlIG1vcmUgYW5kIG1vcmUgc2FtcGxlcywgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiBhIGdpdmVuIHN0YXRpc3RpYyB3aWxsIGV2ZW50dWFsbCBjb252ZXJnZSB0byBhIG5vcm1hbCBkaXN0cmlidXRpb24uDQoNCiMgUHJvYmxlbSAyDQpGb3IgdGhpcyBwcm9ibGVtLCB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBhbmFseXppbmcgc2FtcGxlIG1lYW5zIGFuZCB2YXJpYW5jZXMgdmlhIGJvb3RzdHJhcHBpbmcuIFRvIGRvIHRoaXMsIHdlIHdpbGwgdXNlIGEgZGF0YSBzZXQgdGhhdCBjb25zaXN0cyBvZiB0aGUgdm9sdW1lIG9mIGNvZmZlZSBzb2xkIGRhaWx5IGF0IHR3byBkaWZmZXJlbnQgY29mZmVlIHNob3BzOg0KYGBge3J9IA0KY29mZmVlIDwtIGMoMjg1MCwgMzIwMCwgMjkwMCwgMzEwMCwgMjk1MCwgNzgwMCwgODEwMCwgNzkwMCwgMzMwMCwgMzA1MCwgNDAwMCwgNDIwMCwgMzE1MCwgMzQwMCwgNzcwMCwgODIwMCwgMzI1MCwgNDQwMCwgMzEwMCwgNDIwMCwgNDUwMCwgNDgwMCwgNDMwMCwgODUwMCwgODIwMCwgODkwMCwgODcwMCwgMzI1MCwgMzAwMCwgNDYwMCwgNDEwMCwgODQwMCwgODgwMCwgMzM1MCwgNDcwMCwgMzEwMCwgODEwMCwgMzA1MCwgODMwMCwgNDEwMCwgMzEwMCwgODMwMCwgODkwMCwgODIwMCwgNDQwMCwgNDUwMCwgMzI1MCwgNDYwMCwgODQwMCwgMzMwMCwgNDIwMCwgNDUwMCwgNDgwMCwgNDMwMCwgODUwMCkNCmBgYA0KDQojIyBQYXJ0IEENCkkgYmVsaWV2ZSB0aGF0IHdlIGNhbiB1c2UgdGhlIGNlbnRyYWwgbGltaXQgdGhlb3JlbSB0byBkZXJpdmUgdGhlIGFzeW1wdG90aWMgZGlzdHJpYnV0aW9uIG9mIHRoZSBzYW1wbGUgbWVhbiBiZWNhdXNlIG91ciBzYW1wbGUgc2l6ZSBpcyBncmVhdGVyIHRoYW4gMzAgKG4gPSA1NSBpbiBvdXIgY2FzZSkuDQpgYGB7cn0NCmxlbmd0aChjb2ZmZWUpDQpgYGANCg0KIyMgUGFydCBCDQpGb3IgdGhpcyBwYXJ0LCB3ZSB3aWxsIGRvIHRoZSBib290c3RyYXAgc2FtcGxlcyBhbmQgY2FsY3VsYXRlIHRoZSBzYW1wbGUgbWVhbnMgZm9yIGVhY2guIFRoZXkgd2lsbCB0aGVuIGJlIHBsb3R0ZWQgdmlhIGEgaGlzdG9ncmFtLiBBZnRlcndhcmRzIHdlIHdpbGwgZ2VuZXJhdGUgYW5kIHBsb3QgYSBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSBmb3IgdGhlIHNhbXBsZSBtZWFucy4NCg0KTGV0J3Mgc3RhcnQgYnkgZ2VuZXJhdGluZyBhbmQgcGxvdHRpbmcgdGhlIGJvb3RzdHJhcHBlZCBzYW1wbGluZyBkaXN0cmlidXRpb24gZm9yIHRoZSBtZWFuLiBGb3IgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiwgMTAwMCBzYW1wbGVzIHdpbGwgYmUgdXNlZC4gV2Ugd2lsbCBhbHNvIHBsb3QgYSBrZXJuZWwgZGVuc2l0eSBjdXJ2ZSBvbiB0aGUgcGxvdDoNCmBgYHtyfQ0Kb3JpZ2luYWwuc2FtcGxlID0gc2FtcGxlKGNvZmZlZSwgICAgIyBwb3B1bGF0aW9uIG9mIGFsbCBjb2ZmZWUgdm9sdW1lIHNhbGVzDQo1NSwgICAgICAgICAgICAgICAgICAgICAgIyBzYW1wbGUgc2l6ZSA9IDU1IA0KcmVwbGFjZSA9IEZBTFNFICAgICAgICAgICMgc2FtcGxlIHdpdGhvdXQgcmVwbGFjZW1lbnQNCiAgICAgICAgICAgICAgICAgKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KIyMjIEJvb3RzdHJhcCBzYW1wbGluZyBiZWdpbnMgDQpidC5zYW1wbGUubWVhbi52ZWMgPSBOVUxMICAgICAgIyBkZWZpbmUgYW4gZW1wdHkgdmVjdG9yIHRvIGhvbGQgc2FtcGxlIG1lYW5zIG9mIHJlcGVhdGVkIHNhbXBsZXMuDQpmb3IoaSBpbiAxOjEwMDApeyAgICAgICAgICAgICAgIyBzdGFydGluZyBmb3ItbG9vcCB0byB0YWtlIGJvb3RzdHJhcCBzYW1wbGVzIHdpdGggbiA9IDU1DQogIGl0aC5idC5zYW1wbGUgPSBzYW1wbGUoeCA9IG9yaWdpbmFsLnNhbXBsZSwgIyBPcmlnaW5hbCBzYW1wbGUgd2l0aCA1NSBEYWlseQ0KICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gNTUsICAgICAgICAgICAgICMgc2FtcGxlIHNpemUgPSA1NSBNVVNUIGJlIGVxdWFsIHRvIHRoZSBzYW1wbGUgc2l6ZSEhDQogICAgICAgICAgICAgICAgICAgIHJlcGxhY2UgPSBUUlVFICAgICAgICAgICAgIyBNVVNUIHVzZSBXSVRIIFJFUExBQ0VNRU5UISENCiAgICAgICAgICAgICAgICAgICAgICAgKSAgICAgICAgICAgICAgICAgICAgICAjIHRoaXMgaXMgdGhlIGktdGggQm9vdHN0cmFwIHNhbXBsZQ0KICBidC5zYW1wbGUubWVhbi52ZWNbaV0gPSBtZWFuKGl0aC5idC5zYW1wbGUpICMgY2FsY3VsYXRlIHRoZSBtZWFuIG9mIGktdGggYm9vdHN0cmFwIHNhbXBsZSBhbmQgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzYXZlIGl0IGluIHRoZSBlbXB0eSB2ZWN0b3I6IHNhbXBsZS5idC5tZWFuLnZlYyANCn0NCiMjIw0KDQpoaXN0KGJ0LnNhbXBsZS5tZWFuLnZlYywgICAgICAgICAgICAgICAgICAgICAjIGRhdGEgZnJvbSBzYW1wbGUNCiAgICAgYnJlYWtzID0gMTQsICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc3BlY2lmeSBudW1iZXIgb2YgdmVydGljYWwgYmFycw0KICAgICBwcm9iYWJpbGl0eSA9IFRSVUUsDQogICAgICAgeGxhYiA9ICJCb290c3RyYXBwZWQgU2FtcGxlIE1lYW5zIiwgICAgICAjIGNoYW5nZSB0aGUgbGFiZWwgb2YgeC1heGlzDQogICAgICAjIGFkZCBhIHRpdGxlIHRvIHRoZSBoaXN0b2dyYW0NCiAgICAgICAgbWFpbiA9ICJCb290c3RyYXAgU2FtcGxpbmcgRGlzdHJpYnV0aW9uIG9mIFNhbXBsZSBNZWFucyIsDQogICAgICAgICAgY2V4Lm1haW4gPSAwLjksIGNvbCA9ICJsaWdodGJsdWUiDQogICAgICAgKSAgIA0KDQpsaW5lcyhkZW5zaXR5KGJ0LnNhbXBsZS5tZWFuLnZlYywgbiA9IDEwMDApLCBjb2wgPSAicmVkIiwgbHdkID0gMikNCiMgb3ZlcmxheXMgdGhlIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlIGZvciB0aGUgc2FtcGxlIG1lYW4NCmBgYA0KDQpUaGUgaGlzdG9ncmFtIHNoYXBlIGxvb2tzIHByZXR0eSBub3JtYWwsIGFsdGhvdWdoIHNsaWdodGx5IHNrZXdlZC4gVGhlIGtlcm5lbCBkZW5zaXR5IChpbiByZWQpIGxvb2tzIHJvdWdoLCBidXQgZG9lcyByZXNlbWJsZSBhIG5vcm1hbCBjdXJ2ZS4NCkxldCdzIGNhbGwgdGhlIGtlcm5lbCBzZXBlcmF0ZWx5IGFuZCBjb21wYXJlOg0KYGBge3J9DQpkZW5zaXR5KGJ0LnNhbXBsZS5tZWFuLnZlYywgbiA9IDEwMDApDQptZWFuKGNvZmZlZSkNCmBgYA0KVGhlIGFjdHVhbCBzYW1wbGUgbWVhbiBpcyA1MjUwLiBFdmVuIHRob3VnaCB0aGUgZXN0aW1hdGUgZm9yIHRoZSBtZWFuIHdpbGwgY2hhbmdlIGV2ZXJ5IHRpbWUgeW91IHJ1biBhIHNhbXBsZSwgaXQgZG9lcyBzdGF5IHJlbGF0aXZlbHkgY2xvc2UgdG8gdGhlIG1lYW4gKHVzdWFsbHkgYmV0d2VlbiA1MjIwIGFuZCA1MjgwKS4gVGhpcyBzZWVtcyB0byBkbyBhIGdvb2Qgam9iIG9mIGVzdGltYXRpbmcgdGhlIHNhbXBsZSBtZWFuLg0KDQojIyBQYXJ0IEMNCkZvciB0aGlzIHBhcnQsIHdlIHdpbGwgcmVwZWF0IHdoYXQgd2UgZGlkIGluIHBhcnRzIEEgYW5kIEIgdG8gZXN0aW1hdGUgdGhlIHNhbXBsZSB2YXJpYW5jZS4NCg0KSSBzdGlsbCB0aGluayB0aGF0IHRoZSBjZW50cmFsIGxpbWl0IHRoZW9yZW0gY2FuIGFwcGx5IHRvIGVzdGltYXRlIHRoZSBzYW1wbGUgdmFyaWFuY2UuIE91ciBzYW1wbGUgc2l6ZSBpc24ndCBjaGFuZ2luZyAobiA9IDU1KSBhbmQgdGhlIGFtb3VudCBvZiBzYW1wbGVzIHdlIHdpbGwgdGFrZSB3b24ndCBjaGFuZ2UgZWl0aGVyIChzYW1wbGVzID0gMTAwMCkuDQoNCk5vdyBmb3IgdGhlIGJvb3RzdHJhcHBlZCBzYW1wbGVzIGFuZCB0aGUga2VybmVsIGRlbnNpdHkgZXN0aW1hdGU6DQpgYGB7cn0NCm9yaWdpbmFsLnNhbXBsZSA9IHNhbXBsZShjb2ZmZWUsICAgICMgcG9wdWxhdGlvbiBvZiBhbGwgZGFpbHkgY29mZmVlIHNhbGVzDQogICAgICAgICAgICAgICAgICAgICAgIDU1LCAgICAgICAgICAgICAgICAgICAgICAjIHNhbXBsZSBzaXplID0gNTUgdmFsdWVzIGluIHRoZSBzYW1wbGUNCiAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZSA9IEZBTFNFICAgICAgICAgICMgc2FtcGxlIHdpdGhvdXQgcmVwbGFjZW1lbnQNCiAgICAgICAgICAgICAgICAgKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KIyMjIEJvb3RzdHJhcCBzYW1wbGluZyBiZWdpbnMgDQpidC5zYW1wbGUudmFyLnZlYyA9IE5VTEwgICAgICAjIGRlZmluZSBhbiBlbXB0eSB2ZWN0b3IgdG8gaG9sZCBzYW1wbGUgbWVhbnMgb2YgcmVwZWF0ZWQgc2FtcGxlcy4NCmZvcihpIGluIDE6MTAwMCl7ICAgICAgICAgICAgICAjIHN0YXJ0aW5nIGZvci1sb29wIHRvIHRha2UgYm9vdHN0cmFwIHNhbXBsZXMgd2l0aCBuID0gNTUNCiAgaXRoLmJ0LnNhbXBsZSA9IHNhbXBsZSh4ID0gb3JpZ2luYWwuc2FtcGxlLCAjIE9yaWdpbmFsIHNhbXBsZSB3aXRoIDU1IFdDVSBzdHVkZW50cycgaGVpZ2h0cw0KICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gNTUsICAgICAgICAgICAgICMgc2FtcGxlIHNpemUgPSA1NSBNVVNUIGJlIGVxdWFsIHRvIHRoZSBzYW1wbGUgc2l6ZSEhDQogICAgICAgICAgICAgICAgICAgIHJlcGxhY2UgPSBUUlVFICAgICAgICAgICAgIyBNVVNUIHVzZSBXSVRIIFJFUExBQ0VNRU5UISENCiAgICAgICAgICAgICAgICAgICAgICAgKSAgICAgICAgICAgICAgICAgICAgICAjIHRoaXMgaXMgdGhlIGktdGggQm9vdHN0cmFwIHNhbXBsZQ0KICBidC5zYW1wbGUudmFyLnZlY1tpXSA9IHZhcihpdGguYnQuc2FtcGxlKSAjIGNhbGN1bGF0ZSB0aGUgdmFyaWFuY2Ugb2YgaS10aCBib290c3RyYXAgc2FtcGxlIGFuZCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHNhdmUgaXQgaW4gdGhlIGVtcHR5IHZlY3Rvcjogc2FtcGxlLmJ0LnZhci52ZWMgDQp9DQojIyMNCmhpc3QoYnQuc2FtcGxlLnZhci52ZWMsICAgICAgICAgICAgICAgICAgICAgIyBkYXRhIHVzZWQgZm9yIGhpc3RvZ3JhbQ0KICAgICBicmVha3MgPSAxNCwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzcGVjaWZ5IG51bWJlciBvZiB2ZXJ0aWNhbCBiYXJzDQogICAgIHByb2JhYmlsaXR5ID0gVFJVRSwNCiAgICAgICB4bGFiID0gIkJvb3RzdHJhcCBTYW1wbGUgVmFyaWFuY2UiLCAgICAgICMgY2hhbmdlIHRoZSBsYWJlbCBvZiB4LWF4aXMNCiAgICAgICMgYWRkIGEgdGl0bGUgdG8gdGhlIGhpc3RvZ3JhbQ0KICAgICAgICBtYWluPSJCb290c3RyYXAgU2FtcGxpbmcgRGlzdHJpYnV0aW9uIG9mIFNhbXBsZSBWYXJpYW5jZXMiLA0KICAgICAgICAgIGNleC5tYWluID0gMC45LA0KICAgICAgIGNvbC5tYWluID0gIm5hdnkiLCBjb2wgPSAibGlnaHRibHVlIikgICANCmxpbmVzKGRlbnNpdHkoYnQuc2FtcGxlLnZhci52ZWMpLCBjb2wgPSAicmVkIiwgbHdkID0gMikNCmBgYA0KQWx0aG91Z2ggaXQgcmVzZW1ibGVzIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiwgdGhlcmUgc2VlbXMgdG8gYmUgYSBsb3QgbW9yZSBza2V3IGNvbXBhcmVkIHRvIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgdGhlIG1lYW4uIEkgYmVsaWV2ZSBzb21lIG9mIHRoZSBwb3RlbnRpYWwgc2tldyBtYXkgYmUgY29taW5nIGZyb20ganVzdCBob3cgdGhlIGdyYXBoIGxvb2tzLiBJIGRvbid0IHRoaW5rIHRoZSBza2V3IGlzIGFzIGJhZCBhcyBpdCBsb29rcy4gDQoNCmBgYHtyfQ0KZGVuc2l0eShidC5zYW1wbGUudmFyLnZlYywgbiA9IDEwMDApDQp2YXIoY29mZmVlKQ0KDQpgYGANClRoZSBhY3R1YWwgc2FtcGxlIHZhcmlhbmNlIGlzIDUsMDMwLDgzMy4gVGhlIEtlcm5lbCBEZW5zaXR5IEVzdGltYXRlIHVzdWFsbHkgZmFsbHMgYmV0d2VlbiA0LDIwMCwwMDAgYW5kIDQsNDAwLDAwMC4gSW4gcmFyZSBjYXNlcywgaXQgbWF5IGV4Y2VlZCA0LDQwMCwwMDAuIEhvd2V2ZXIsIGlmIHdlIGtlZXAgcnVubmluZyB0aGUgY29kZSwgdGhlIHBlYWsgb2YgdGhlIGhpc3RvZ3JhbXMgZ2VuZXJhdGVkIHVzdWFsbHkgZmxvYXQgYXJvdW5kIHRoZSA1LDAwMCwwMDAgbWFyay4gU28gSSB0aGluayB3ZSBkaWQgYSBnb29kIGVub3VnaCBqb2IgZXN0aW1hdGluZyB0aGUgc2FtcGxlIHZhcmlhbmNlIGFzIHdlbGwu