Exercise:
# This is a small demonstartion of the command replicate(). It replicates drawing a sample of size 15, 10 times
# from a normal distribution with mean 10 and variance 1. As you can see from the output, the samples appear along
# the columns as the repetitions appear along the columns.
#set.seed(1)
#samples <- replicate(10, rnorm(15, 10, 1))
#samples
# We can cycle through the columns and calculate the average of each column as follows by looping through
# with a for loop.
#for(i in 1:10) {
# cat(mean(samples[,i]), "is the average for column", i, "\n")
#}
# As an exercise read the documentation for the functions apply, sapply etc and see if you can rewrite
# the code to avoid the use of the for loop.
set.seed(98)
samples <- replicate(1000, rnorm(40, 10, 1)) # simulating our experiment.
sample_mean <- 1:1000
for(i in 1:1000) { # This part of the code computes the sample mean for all samples via a for loop.
sample_mean[i] <- mean(samples[,i])
}
#Empirical verification of unbiasedness
mean(sample_mean) # printing the sample mean.
#Normality plot
library(ggplot2)
# Create the normal probability plot (with the help of the inbuilt qq-plot package features).
ggplot(data.frame(sample_mean), aes(sample = sample_mean)) +
stat_qq() +
stat_qq_line() +
labs(title = "Normal Probability Plot")
Question 1:
# This is a small demonstartion of the command replicate(). It replicates drawing a sample of size 15, 10 times
# from a normal distribution with mean 10 and variance 1. As you can see from the output, the samples appear along
# the columns as the repetitions appear along the columns.
set.seed(98)
uniform_samples <- replicate(1000, runif(40, 0, 1))
uniform_samples_mean <- 1:1000
for(i in 1:1000) {
uniform_samples_mean[i] <- mean(uniform_samples[,i])
}
library(ggplot2)
ggplot(data.frame(uniform_samples_mean), aes(sample = uniform_samples_mean)) +
stat_qq() +
stat_qq_line() +
labs(title = "Normality Plot")

# We can cycle through the columns and calculate the average of each column as follows by looping through
# with a for loop.
Based on the normality plot generated according to the sample
averages, the points closely align with the line and there are no
significant deviations. Therefore, it is reasonable to say that the
averages are (approximately) normally distributed.
We will repeat this experiment now setting the sample size to 2 for
the uniform distrubution
set.seed(98)
uniform_samples <- replicate(1000, runif(2, 0, 1))
uniform_samples_mean <- 1:1000
for(i in 1:1000) {
uniform_samples_mean[i] <- mean(uniform_samples[,i])
}
library(ggplot2)
ggplot(data.frame(uniform_samples_mean), aes(sample = uniform_samples_mean)) +
stat_qq() +
stat_qq_line() +
labs(title = "Normality Plot")

This time, based on the normality plot generated according to the
sample averages, the points are highly deviated from the line.
Therefore, it is not reasonable to conclude that the sample averages
here are normally distributed.
Both the first experiment and the second experiment are also
supported with the Central Limit Theorem (ie. first experiment sample
size greater than 30, second experiment sample size less than 30),
therefore our conclusions empirically verify the Central Limit Theorem
for Uniform Distributions.
Question 2:
The code below repeats the outcome/purpose of exercise 1 but does not
use a built-in function that directly draws a normality plot and instead
uses a function that I have written.
set.seed(98)
samples <- replicate(1000, rnorm(40, 10, 1))
sample_mean <- 1:1000
for (i in 1:1000) {
sample_mean[i] <- mean(samples[, i])
}
mean_sample_mean <- mean(sample_mean)
# Calculate observed and theoretical values via textbook method:
calculate_normality_values <- function(sample_mean) {
n <- length(sample_mean)
p <- (1:n - 0.5) / n
theoretical_quantiles <- qnorm(p)
return(theoretical_quantiles)
}
sorted_sample_mean <- sort(sample_mean) # Using order instead of sort
theoretical_quantiles <- calculate_normality_values(sample_mean)
# Plotting the normality distribution from scratch:
plot(theoretical_quantiles, sorted_sample_mean,
xlab = "Theoretical",
ylab = "Observed",
main = "Normality Plot",
pch = 16, col = "blue")
# For reference purposes:
abline(a = mean_sample_mean, b = sd(sample_mean), col = "orange")

Question 3:
Part I:


Part II:
The following code calculates the appropriate Maximum Likelihood
Estimators for μ and σ^2:
set.seed(123) # Setting seed for reproducibility
# Generate a sample of size 3000 from a normal distribution
sample_data <- rnorm(3000, mean = 2, sd = sqrt(3))
# Compute maximum likelihood estimates
mle_mean <- mean(sample_data)
mle_variance <- var(sample_data)
# Print the results
cat("Maximum Likelihood Estimate for μ:", mle_mean, "\n")
Maximum Likelihood Estimate for μ: 2.022217
cat("Maximum Likelihood Estimate for σ^2:", mle_variance, "\n")
Maximum Likelihood Estimate for σ^2: 2.960085
Question 4:
set.seed(98)
lambda <- 4
sample_size <- 40
num_samples <- 10000
confidence_level <- 0.95
# Function used to calculate the confidence interval for the mean:
calculate_confidence_interval <- function(sample, confidence_level) {
sample_mean <- mean(sample)
standard_error <- sd(sample) / sqrt(length(sample))
z_value <- qnorm((confidence_level + 1) / 2)
margin_of_error <- z_value * standard_error
lower_bound <- sample_mean - margin_of_error
upper_bound <- sample_mean + margin_of_error
return(c(lower_bound, upper_bound))
}
# Simulate drawing 10000 samples and check inclusion of theoretical mean
proportion_containing_theoretical_mean <- 0
for (i in 1:num_samples) {
# Drawing sample for Distribution
sample_data <- rexp(sample_size, rate = lambda)
# Calculating confidence interval for the mean
confidence_interval <- calculate_confidence_interval(sample_data, confidence_level)
# Checking if the theoretical mean is in the confidence interval
theoretical_mean <- 1/lambda
if (theoretical_mean >= confidence_interval[1] && theoretical_mean <= confidence_interval[2]) {
proportion_containing_theoretical_mean <- proportion_containing_theoretical_mean + 1
}
}
# Calculating the proportion
proportion_containing_theoretical_mean <- proportion_containing_theoretical_mean / num_samples
cat("Proportion of Confidence Intervals containing theoretical mean:", proportion_containing_theoretical_mean, "\n")
Proportion of Confidence Intervals containing theoretical mean: 0.9267
We can see that this proportion of Confidence Intervals containing
the theoretical mean is roughly 0.93. This aligns with my understand of
what a Confidence Interval is because a 95% confidence interval means
that if we conduct the same sampling procedure many times and construct
confidence intervals from those samples, we would expect about 95% of
those intervals to contain the true population parameter (theoretical
mean in this case). The value we obtained is very close to this, and
with more samples it could only get closer.
Question 5:
To see if we can use the Central Limit Theorem, we must verify the
respective three specicies’ sample size is large enough (greater than
30):
cat("Sample Size (setosa):", length(setosa_data), "\n")
Sample Size (setosa): 50
cat("Sample Size (versicolor):", length(versicolor_data), "\n")
Sample Size (versicolor): 50
cat("Sample Size (virginica):", length(virginica_data), "\n")
Sample Size (virginica): 50
Yes, we can use the Central Limit Theorem since the sample sizes are
large enough and proceed:
# Load the iris dataset
data(iris)
# Split the data based on Species
setosa_data <- iris$Petal.Length[iris$Species == "setosa"]
versicolor_data <- iris$Petal.Length[iris$Species == "versicolor"]
virginica_data <- iris$Petal.Length[iris$Species == "virginica"]
# Confidence interval function using zconfint
calculate_confidence_interval <- function(data, confidence_level = 0.95) {
mean_val <- mean(data)
standard_error <- sd(data) / sqrt(length(data))
z_value <- qnorm((confidence_level + 1) / 2)
margin_of_error <- z_value * standard_error
lower_bound <- mean_val - margin_of_error
upper_bound <- mean_val + margin_of_error
return(c(lower_bound, upper_bound))
}
# Calculate confidence intervals for Petal.Length for each species
confidence_interval_setosa <- calculate_confidence_interval(setosa_data)
confidence_interval_versicolor <- calculate_confidence_interval(versicolor_data)
confidence_interval_virginica <- calculate_confidence_interval(virginica_data)
# Print the confidence intervals
cat("Confidence Interval (setosa):", confidence_interval_setosa, "\n")
Confidence Interval (setosa): 1.413864 1.510136
cat("Confidence Interval (versicolor):", confidence_interval_versicolor, "\n")
Confidence Interval (versicolor): 4.12975 4.39025
cat("Confidence Interval (virginica):", confidence_interval_virginica, "\n")
Confidence Interval (virginica): 5.399025 5.704975
LS0tCnRpdGxlOiAiUHJvamVjdCAjMyAtIEZhaXogU2hhaWtoIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIEV4ZXJjaXNlOgoKYGBge3J9CgojIFRoaXMgaXMgYSBzbWFsbCBkZW1vbnN0YXJ0aW9uIG9mIHRoZSBjb21tYW5kIHJlcGxpY2F0ZSgpLiBJdCByZXBsaWNhdGVzIGRyYXdpbmcgYSBzYW1wbGUgb2Ygc2l6ZSAxNSwgMTAgdGltZXMKIyBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiB3aXRoIG1lYW4gMTAgYW5kIHZhcmlhbmNlIDEuIEFzIHlvdSBjYW4gc2VlIGZyb20gdGhlIG91dHB1dCwgdGhlIHNhbXBsZXMgYXBwZWFyIGFsb25nCiMgdGhlIGNvbHVtbnMgYXMgdGhlIHJlcGV0aXRpb25zIGFwcGVhciBhbG9uZyB0aGUgY29sdW1ucy4KCiNzZXQuc2VlZCgxKQojc2FtcGxlcyA8LSByZXBsaWNhdGUoMTAsIHJub3JtKDE1LCAxMCwgMSkpCiNzYW1wbGVzCgkKIyBXZSBjYW4gY3ljbGUgdGhyb3VnaCB0aGUgY29sdW1ucyBhbmQgY2FsY3VsYXRlIHRoZSBhdmVyYWdlIG9mIGVhY2ggY29sdW1uIGFzIGZvbGxvd3MgYnkgbG9vcGluZyB0aHJvdWdoIAojIHdpdGggYSBmb3IgbG9vcC4gCgoKI2ZvcihpIGluIDE6MTApIHsgIAojICAgIGNhdChtZWFuKHNhbXBsZXNbLGldKSwgImlzIHRoZSBhdmVyYWdlIGZvciBjb2x1bW4iLCBpLCAiXG4iKQojfQoKIyBBcyBhbiBleGVyY2lzZSByZWFkIHRoZSBkb2N1bWVudGF0aW9uIGZvciB0aGUgZnVuY3Rpb25zIGFwcGx5LCBzYXBwbHkgZXRjIGFuZCBzZWUgaWYgeW91IGNhbiByZXdyaXRlIAojIHRoZSBjb2RlIHRvIGF2b2lkIHRoZSB1c2Ugb2YgdGhlIGZvciBsb29wLgoKc2V0LnNlZWQoOTgpCnNhbXBsZXMgPC0gcmVwbGljYXRlKDEwMDAsIHJub3JtKDQwLCAxMCwgMSkpICMgc2ltdWxhdGluZyBvdXIgZXhwZXJpbWVudC4Kc2FtcGxlX21lYW4gPC0gMToxMDAwCgoKZm9yKGkgaW4gMToxMDAwKSB7ICAjIFRoaXMgcGFydCBvZiB0aGUgY29kZSBjb21wdXRlcyB0aGUgc2FtcGxlIG1lYW4gZm9yIGFsbCBzYW1wbGVzIHZpYSBhIGZvciBsb29wLgogICAgc2FtcGxlX21lYW5baV0gPC0gbWVhbihzYW1wbGVzWyxpXSkKfQoKI0VtcGlyaWNhbCB2ZXJpZmljYXRpb24gb2YgdW5iaWFzZWRuZXNzCm1lYW4oc2FtcGxlX21lYW4pICMgcHJpbnRpbmcgdGhlIHNhbXBsZSBtZWFuLgoKI05vcm1hbGl0eSBwbG90CgpsaWJyYXJ5KGdncGxvdDIpCgojIENyZWF0ZSB0aGUgbm9ybWFsIHByb2JhYmlsaXR5IHBsb3QgKHdpdGggdGhlIGhlbHAgb2YgdGhlIGluYnVpbHQgcXEtcGxvdCBwYWNrYWdlIGZlYXR1cmVzKS4KZ2dwbG90KGRhdGEuZnJhbWUoc2FtcGxlX21lYW4pLCBhZXMoc2FtcGxlID0gc2FtcGxlX21lYW4pKSArCnN0YXRfcXEoKSArCnN0YXRfcXFfbGluZSgpICsKbGFicyh0aXRsZSA9ICJOb3JtYWwgUHJvYmFiaWxpdHkgUGxvdCIpCmBgYAoKCgojIFF1ZXN0aW9uIDE6CgpgYGB7cn0Kc2V0LnNlZWQoOTgpCnVuaWZvcm1fc2FtcGxlcyA8LSByZXBsaWNhdGUoMTAwMCwgcnVuaWYoNDAsIDAsIDEpKQoKdW5pZm9ybV9zYW1wbGVzX21lYW4gPC0gMToxMDAwCmZvcihpIGluIDE6MTAwMCkgeyAgCiAgICB1bmlmb3JtX3NhbXBsZXNfbWVhbltpXSA8LSBtZWFuKHVuaWZvcm1fc2FtcGxlc1ssaV0pCn0KCmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KGRhdGEuZnJhbWUodW5pZm9ybV9zYW1wbGVzX21lYW4pLCBhZXMoc2FtcGxlID0gdW5pZm9ybV9zYW1wbGVzX21lYW4pKSArCiAgc3RhdF9xcSgpICsKICBzdGF0X3FxX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9ICJOb3JtYWxpdHkgUGxvdCIpCmBgYApCYXNlZCBvbiB0aGUgbm9ybWFsaXR5IHBsb3QgZ2VuZXJhdGVkIGFjY29yZGluZyB0byB0aGUgc2FtcGxlIGF2ZXJhZ2VzLCB0aGUgcG9pbnRzIGNsb3NlbHkgYWxpZ24gd2l0aCB0aGUgbGluZSBhbmQgdGhlcmUgYXJlIG5vIHNpZ25pZmljYW50IGRldmlhdGlvbnMuIFRoZXJlZm9yZSwgaXQgaXMgcmVhc29uYWJsZSB0byBzYXkgdGhhdCB0aGUgYXZlcmFnZXMgYXJlIChhcHByb3hpbWF0ZWx5KSBub3JtYWxseSBkaXN0cmlidXRlZC4KCldlIHdpbGwgcmVwZWF0IHRoaXMgZXhwZXJpbWVudCBub3cgc2V0dGluZyB0aGUgc2FtcGxlIHNpemUgdG8gMiBmb3IgdGhlIHVuaWZvcm0gZGlzdHJ1YnV0aW9uCmBgYHtyfQpzZXQuc2VlZCg5OCkKdW5pZm9ybV9zYW1wbGVzIDwtIHJlcGxpY2F0ZSgxMDAwLCBydW5pZigyLCAwLCAxKSkKCnVuaWZvcm1fc2FtcGxlc19tZWFuIDwtIDE6MTAwMApmb3IoaSBpbiAxOjEwMDApIHsgIAogICAgdW5pZm9ybV9zYW1wbGVzX21lYW5baV0gPC0gbWVhbih1bmlmb3JtX3NhbXBsZXNbLGldKQp9CgpsaWJyYXJ5KGdncGxvdDIpCmdncGxvdChkYXRhLmZyYW1lKHVuaWZvcm1fc2FtcGxlc19tZWFuKSwgYWVzKHNhbXBsZSA9IHVuaWZvcm1fc2FtcGxlc19tZWFuKSkgKwogIHN0YXRfcXEoKSArCiAgc3RhdF9xcV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiTm9ybWFsaXR5IFBsb3QiKQpgYGAKVGhpcyB0aW1lLCBiYXNlZCBvbiB0aGUgbm9ybWFsaXR5IHBsb3QgZ2VuZXJhdGVkIGFjY29yZGluZyB0byB0aGUgc2FtcGxlIGF2ZXJhZ2VzLCB0aGUgcG9pbnRzIGFyZSBoaWdobHkgZGV2aWF0ZWQgZnJvbSB0aGUgbGluZS4gVGhlcmVmb3JlLCBpdCBpcyBub3QgcmVhc29uYWJsZSB0byBjb25jbHVkZSB0aGF0IHRoZSBzYW1wbGUgYXZlcmFnZXMgaGVyZSBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuCgpCb3RoIHRoZSBmaXJzdCBleHBlcmltZW50IGFuZCB0aGUgc2Vjb25kIGV4cGVyaW1lbnQgYXJlIGFsc28gc3VwcG9ydGVkIHdpdGggdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSAoaWUuIGZpcnN0IGV4cGVyaW1lbnQgc2FtcGxlIHNpemUgZ3JlYXRlciB0aGFuIDMwLCBzZWNvbmQgZXhwZXJpbWVudCBzYW1wbGUgc2l6ZSBsZXNzIHRoYW4gMzApLCB0aGVyZWZvcmUgb3VyIGNvbmNsdXNpb25zIGVtcGlyaWNhbGx5IHZlcmlmeSB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtIGZvciBVbmlmb3JtIERpc3RyaWJ1dGlvbnMuCgoKCiMgUXVlc3Rpb24gMjoKClRoZSBjb2RlIGJlbG93IHJlcGVhdHMgdGhlIG91dGNvbWUvcHVycG9zZSBvZiBleGVyY2lzZSAxIGJ1dCBkb2VzIG5vdCB1c2UgYSBidWlsdC1pbiBmdW5jdGlvbiB0aGF0IGRpcmVjdGx5IGRyYXdzIGEgbm9ybWFsaXR5IHBsb3QgYW5kIGluc3RlYWQgdXNlcyBhIGZ1bmN0aW9uIHRoYXQgSSBoYXZlIHdyaXR0ZW4uCgpgYGB7cn0Kc2V0LnNlZWQoOTgpCnNhbXBsZXMgPC0gcmVwbGljYXRlKDEwMDAsIHJub3JtKDQwLCAxMCwgMSkpCnNhbXBsZV9tZWFuIDwtIDE6MTAwMAoKZm9yIChpIGluIDE6MTAwMCkgewogIHNhbXBsZV9tZWFuW2ldIDwtIG1lYW4oc2FtcGxlc1ssIGldKQp9CgptZWFuX3NhbXBsZV9tZWFuIDwtIG1lYW4oc2FtcGxlX21lYW4pCgojIENhbGN1bGF0ZSBvYnNlcnZlZCBhbmQgdGhlb3JldGljYWwgdmFsdWVzIHZpYSB0ZXh0Ym9vayBtZXRob2Q6CiAgY2FsY3VsYXRlX25vcm1hbGl0eV92YWx1ZXMgPC0gZnVuY3Rpb24oc2FtcGxlX21lYW4pIHsKICAgIG4gPC0gbGVuZ3RoKHNhbXBsZV9tZWFuKQogICAgcCA8LSAoMTpuIC0gMC41KSAvIG4KICAgIHRoZW9yZXRpY2FsX3F1YW50aWxlcyA8LSBxbm9ybShwKQogICAgcmV0dXJuKHRoZW9yZXRpY2FsX3F1YW50aWxlcykKICB9CgogIHNvcnRlZF9zYW1wbGVfbWVhbiA8LSBzb3J0KHNhbXBsZV9tZWFuKSAgIyBVc2luZyBvcmRlciBpbnN0ZWFkIG9mIHNvcnQKICB0aGVvcmV0aWNhbF9xdWFudGlsZXMgPC0gY2FsY3VsYXRlX25vcm1hbGl0eV92YWx1ZXMoc2FtcGxlX21lYW4pCiAgCiAgIyBQbG90dGluZyB0aGUgbm9ybWFsaXR5IGRpc3RyaWJ1dGlvbiBmcm9tIHNjcmF0Y2g6CiAgcGxvdCh0aGVvcmV0aWNhbF9xdWFudGlsZXMsIHNvcnRlZF9zYW1wbGVfbWVhbiwKICAgICAgIHhsYWIgPSAiVGhlb3JldGljYWwiLAogICAgICAgeWxhYiA9ICJPYnNlcnZlZCIsCiAgICAgICBtYWluID0gIk5vcm1hbGl0eSBQbG90IiwKICAgICAgIHBjaCA9IDE2LCBjb2wgPSAiYmx1ZSIpCiAgCiAgIyBGb3IgcmVmZXJlbmNlIHB1cnBvc2VzOgogIGFibGluZShhID0gbWVhbl9zYW1wbGVfbWVhbiwgYiA9IHNkKHNhbXBsZV9tZWFuKSwgY29sID0gIm9yYW5nZSIpCmBgYAoKIyBRdWVzdGlvbiAzOgoKIyBQYXJ0IEk6CgogICFbXSgvVXNlcnMvZmFpenNoYWlraC9Eb3dubG9hZHMvSU1HXzAyMzQuanBnKQoKICAhW10oL1VzZXJzL2ZhaXpzaGFpa2gvRG93bmxvYWRzL0lNR18wMjM1LmpwZykKCgojIFBhcnQgSUk6CgpUaGUgZm9sbG93aW5nIGNvZGUgY2FsY3VsYXRlcyB0aGUgYXBwcm9wcmlhdGUgTWF4aW11bSBMaWtlbGlob29kIEVzdGltYXRvcnMgZm9yIM68IGFuZCDPg14yOgpgYGB7cn0Kc2V0LnNlZWQoOTgpICAjIFNldHRpbmcgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5CgojIEdlbmVyYXRlIGEgc2FtcGxlIG9mIHNpemUgMzAwMCBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbgpzYW1wbGVfZGF0YSA8LSBybm9ybSgzMDAwLCBtZWFuID0gMiwgc2QgPSBzcXJ0KDMpKQoKIyBDb21wdXRlIG1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0ZXMKbWxlX21lYW4gPC0gbWVhbihzYW1wbGVfZGF0YSkKbWxlX3ZhcmlhbmNlIDwtIHZhcihzYW1wbGVfZGF0YSkKCiMgUHJpbnQgdGhlIHJlc3VsdHMKY2F0KCJNYXhpbXVtIExpa2VsaWhvb2QgRXN0aW1hdGUgZm9yIM68OiIsIG1sZV9tZWFuLCAiXG4iKQpjYXQoIk1heGltdW0gTGlrZWxpaG9vZCBFc3RpbWF0ZSBmb3Igz4NeMjoiLCBtbGVfdmFyaWFuY2UsICJcbiIpCmBgYAoKCiMgUXVlc3Rpb24gNDoKCmBgYHtyfQpzZXQuc2VlZCg5OCkKCmxhbWJkYSA8LSA0CnNhbXBsZV9zaXplIDwtIDQwCm51bV9zYW1wbGVzIDwtIDEwMDAwCmNvbmZpZGVuY2VfbGV2ZWwgPC0gMC45NQoKIyBGdW5jdGlvbiB1c2VkIHRvIGNhbGN1bGF0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgdGhlIG1lYW46CmNhbGN1bGF0ZV9jb25maWRlbmNlX2ludGVydmFsIDwtIGZ1bmN0aW9uKHNhbXBsZSwgY29uZmlkZW5jZV9sZXZlbCkgewogIHNhbXBsZV9tZWFuIDwtIG1lYW4oc2FtcGxlKQogIHN0YW5kYXJkX2Vycm9yIDwtIHNkKHNhbXBsZSkgLyBzcXJ0KGxlbmd0aChzYW1wbGUpKQogIHpfdmFsdWUgPC0gcW5vcm0oKGNvbmZpZGVuY2VfbGV2ZWwgKyAxKSAvIDIpICMgVXNpbmcgdGhlIGxldmVyYWdlIG9mIHRoZSBRLU5vcm0gZnVuY3Rpb24uCiAgCiAgbWFyZ2luX29mX2Vycm9yIDwtIHpfdmFsdWUgKiBzdGFuZGFyZF9lcnJvcgogIAogIGxvd2VyX2JvdW5kIDwtIHNhbXBsZV9tZWFuIC0gbWFyZ2luX29mX2Vycm9yCiAgdXBwZXJfYm91bmQgPC0gc2FtcGxlX21lYW4gKyBtYXJnaW5fb2ZfZXJyb3IKICAKICByZXR1cm4oYyhsb3dlcl9ib3VuZCwgdXBwZXJfYm91bmQpKQp9CgojIFNpbXVsYXRlIGRyYXdpbmcgMTAwMDAgc2FtcGxlcyBhbmQgY2hlY2sgaW5jbHVzaW9uIG9mIHRoZW9yZXRpY2FsIG1lYW4KcHJvcG9ydGlvbl9jb250YWluaW5nX3RoZW9yZXRpY2FsX21lYW4gPC0gMAoKZm9yIChpIGluIDE6bnVtX3NhbXBsZXMpIHsKICAjIERyYXdpbmcgc2FtcGxlIGZvciBEaXN0cmlidXRpb24KICBzYW1wbGVfZGF0YSA8LSByZXhwKHNhbXBsZV9zaXplLCByYXRlID0gbGFtYmRhKQogIAogICMgQ2FsY3VsYXRpbmcgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgdGhlIG1lYW4KICBjb25maWRlbmNlX2ludGVydmFsIDwtIGNhbGN1bGF0ZV9jb25maWRlbmNlX2ludGVydmFsKHNhbXBsZV9kYXRhLCBjb25maWRlbmNlX2xldmVsKQogIAogICMgQ2hlY2tpbmcgaWYgdGhlIHRoZW9yZXRpY2FsIG1lYW4gaXMgaW4gdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwKICB0aGVvcmV0aWNhbF9tZWFuIDwtIDEvbGFtYmRhCiAgaWYgKHRoZW9yZXRpY2FsX21lYW4gPj0gY29uZmlkZW5jZV9pbnRlcnZhbFsxXSAmJiB0aGVvcmV0aWNhbF9tZWFuIDw9IGNvbmZpZGVuY2VfaW50ZXJ2YWxbMl0pIHsKICAgIHByb3BvcnRpb25fY29udGFpbmluZ190aGVvcmV0aWNhbF9tZWFuIDwtIHByb3BvcnRpb25fY29udGFpbmluZ190aGVvcmV0aWNhbF9tZWFuICsgMQogIH0KfQoKIyBDYWxjdWxhdGluZyB0aGUgcHJvcG9ydGlvbgpwcm9wb3J0aW9uX2NvbnRhaW5pbmdfdGhlb3JldGljYWxfbWVhbiA8LSBwcm9wb3J0aW9uX2NvbnRhaW5pbmdfdGhlb3JldGljYWxfbWVhbiAvIG51bV9zYW1wbGVzCmNhdCgiUHJvcG9ydGlvbiBvZiBDb25maWRlbmNlIEludGVydmFscyBjb250YWluaW5nIFRoZW9yZXRpY2FsIE1lYW46IiwgcHJvcG9ydGlvbl9jb250YWluaW5nX3RoZW9yZXRpY2FsX21lYW4sICJcbiIpCmBgYApXZSBjYW4gc2VlIHRoYXQgdGhpcyBwcm9wb3J0aW9uIG9mIENvbmZpZGVuY2UgSW50ZXJ2YWxzIGNvbnRhaW5pbmcgdGhlIHRoZW9yZXRpY2FsIG1lYW4gaXMgcm91Z2hseSAwLjkzLiBUaGlzIGFsaWducyB3aXRoIG15IHVuZGVyc3RhbmQgb2Ygd2hhdCBhIENvbmZpZGVuY2UgSW50ZXJ2YWwgaXMgYmVjYXVzZSBhIDk1JSBjb25maWRlbmNlIGludGVydmFsIG1lYW5zIHRoYXQgaWYgd2UgY29uZHVjdCB0aGUgc2FtZSBzYW1wbGluZyBwcm9jZWR1cmUgbWFueSB0aW1lcyBhbmQgY29uc3RydWN0IGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZyb20gdGhvc2Ugc2FtcGxlcywgd2Ugd291bGQgZXhwZWN0IGFib3V0IDk1JSBvZiB0aG9zZSBpbnRlcnZhbHMgdG8gY29udGFpbiB0aGUgdHJ1ZSBwb3B1bGF0aW9uIHBhcmFtZXRlciAodGhlb3JldGljYWwgbWVhbiBpbiB0aGlzIGNhc2UpLiBUaGUgdmFsdWUgd2Ugb2J0YWluZWQgaXMgdmVyeSBjbG9zZSB0byB0aGlzLCBhbmQgd2l0aCBtb3JlIHNhbXBsZXMgaXQgY291bGQgb25seSBnZXQgY2xvc2VyLgoKCgojIFF1ZXN0aW9uIDU6CgpUbyBzZWUgaWYgd2UgY2FuIHVzZSB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtLCB3ZSBtdXN0IHZlcmlmeSB0aGUgcmVzcGVjdGl2ZSB0aHJlZSBzcGVjaWNpZXMnIHNhbXBsZSBzaXplIGlzIGxhcmdlIGVub3VnaCAoZ3JlYXRlciB0aGFuIDMwKToKYGBge3J9CmNhdCgiU2FtcGxlIFNpemUgKHNldG9zYSk6IiwgbGVuZ3RoKHNldG9zYV9kYXRhKSwgIlxuIikKY2F0KCJTYW1wbGUgU2l6ZSAodmVyc2ljb2xvcik6IiwgbGVuZ3RoKHZlcnNpY29sb3JfZGF0YSksICJcbiIpCmNhdCgiU2FtcGxlIFNpemUgKHZpcmdpbmljYSk6IiwgbGVuZ3RoKHZpcmdpbmljYV9kYXRhKSwgIlxuIikKYGBgCgpZZXMsIHdlIGNhbiB1c2UgdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSBzaW5jZSB0aGUgc2FtcGxlIHNpemVzIGFyZSBsYXJnZSBlbm91Z2ggYW5kIHByb2NlZWQ6CmBgYHtyfQoKc2V0LnNlZWQoOTgpCgojIExvYWRpbmcgdGhlIGlyaXMgZGF0YSBzZXQKZGF0YShpcmlzKQoKIyBTcGxpdHRpbmcgdGhlIGRhdGEgYmFzZWQgb24gU3BlY2llcwpzZXRvc2FfZGF0YSA8LSBpcmlzJFBldGFsLkxlbmd0aFtpcmlzJFNwZWNpZXMgPT0gInNldG9zYSJdCnZlcnNpY29sb3JfZGF0YSA8LSBpcmlzJFBldGFsLkxlbmd0aFtpcmlzJFNwZWNpZXMgPT0gInZlcnNpY29sb3IiXQp2aXJnaW5pY2FfZGF0YSA8LSBpcmlzJFBldGFsLkxlbmd0aFtpcmlzJFNwZWNpZXMgPT0gInZpcmdpbmljYSJdCgojIENvbmZpZGVuY2UgaW50ZXJ2YWwgZnVuY3Rpb24KY2FsY3VsYXRlX2NvbmZpZGVuY2VfaW50ZXJ2YWwgPC0gZnVuY3Rpb24oZGF0YSwgY29uZmlkZW5jZV9sZXZlbCA9IDAuOTUpIHsKICBtZWFuX3ZhbCA8LSBtZWFuKGRhdGEpCiAgc3RhbmRhcmRfZXJyb3IgPC0gc2QoZGF0YSkgLyBzcXJ0KGxlbmd0aChkYXRhKSkKICB6X3ZhbHVlIDwtIHFub3JtKChjb25maWRlbmNlX2xldmVsICsgMSkgLyAyKSAjIFVzaW5nIHRoZSBRLU5vcm0gZnVuY3Rpb24gYWdhaW4KICAKICBtYXJnaW5fb2ZfZXJyb3IgPC0gel92YWx1ZSAqIHN0YW5kYXJkX2Vycm9yCiAgCiAgbG93ZXJfYm91bmQgPC0gbWVhbl92YWwgLSBtYXJnaW5fb2ZfZXJyb3IKICB1cHBlcl9ib3VuZCA8LSBtZWFuX3ZhbCArIG1hcmdpbl9vZl9lcnJvcgogIAogIHJldHVybihjKGxvd2VyX2JvdW5kLCB1cHBlcl9ib3VuZCkpCn0KCiMgQ2FsY3VsYXRpbmcgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciBQZXRhbC5MZW5ndGggZm9yIGVhY2ggc3BlY2llcwpjb25maWRlbmNlX2ludGVydmFsX3NldG9zYSA8LSBjYWxjdWxhdGVfY29uZmlkZW5jZV9pbnRlcnZhbChzZXRvc2FfZGF0YSkKY29uZmlkZW5jZV9pbnRlcnZhbF92ZXJzaWNvbG9yIDwtIGNhbGN1bGF0ZV9jb25maWRlbmNlX2ludGVydmFsKHZlcnNpY29sb3JfZGF0YSkKY29uZmlkZW5jZV9pbnRlcnZhbF92aXJnaW5pY2EgPC0gY2FsY3VsYXRlX2NvbmZpZGVuY2VfaW50ZXJ2YWwodmlyZ2luaWNhX2RhdGEpCgojIFByaW50aW5nIHRoZSByZXNwZWN0aXZlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCmNhdCgiQ29uZmlkZW5jZSBJbnRlcnZhbCAoc2V0b3NhKToiLCBjb25maWRlbmNlX2ludGVydmFsX3NldG9zYSwgIlxuIikKY2F0KCJDb25maWRlbmNlIEludGVydmFsICh2ZXJzaWNvbG9yKToiLCBjb25maWRlbmNlX2ludGVydmFsX3ZlcnNpY29sb3IsICJcbiIpCmNhdCgiQ29uZmlkZW5jZSBJbnRlcnZhbCAodmlyZ2luaWNhKToiLCBjb25maWRlbmNlX2ludGVydmFsX3ZpcmdpbmljYSwgIlxuIikKYGBg