Question 1: Cumulative Distribution Function (CDF)
Estimation
The following failure times (in hours) were observed for 8 electronic
components:
23, 45, 67, 89, 112, 156, 189, 245
- Write an R function implementing the ECDF \(\hat{F}_n(t)\) according to its
mathematical definition. Validate your implementation using R’s ecdf()
function on the given data, with comparison based on their step
functions.
# Failure times (in hours) were observed for 8 electronic components:
x <- c(23, 45, 67, 89, 112, 156, 189, 245)
n <- length(x)
# Implementation of ECDF
ecdf_manual <- function(t, x) {
mean(x <= t)
}
# Validation of Implementation
ecdf_r <- ecdf(x)
t_vals <- seq(0, 260, by = 1)
plot(t_vals, sapply(t_vals, ecdf_manual, x = x),
type = "s", col = "blue", lwd = 2, main = "Empirical CDF of Failure Times",ylab = "ECDF", xlab = "Failure Time (hours)")
lines(ecdf_r, col = "red", lwd = 2, lty = 2)
legend("bottomright", legend = c("Manual ECDF", "R's ecdf()"),
col = c("blue", "red"), lty = c(1,2))

Both ECDF’s return identical values and is continuous from the right
at every point and increases by 1/n = 0.125 for each observed failure
time
- A colleague claims that the probability of failure before 100 hours
is 0.5 based on these data. Do you agree? Explain your reasoning using
the empirical cumulative distribution function (ECDF).
# Observation of colleague claim using ECDF
ecdf_manual(100, x)
[1] 0.5
The ECDF at 100 hours is 0.5, meaning 50% of observed failures
occurred before 100 hours.
Question 2: Density Function Estimation
Consider the following failure times from a mechanical system:
12.3, 14.7, 15.2, 16.8, 18.1, 19.4, 20.6, 22.3, 23.9, 25.4
- Create a histogram of the data using 3 equally spaced bins. What is
the estimated density in each bin? Describe the shape of the histogram’s
distribution.
# Failure times from a mechanical system
y <- c(12.3, 14.7, 15.2, 16.8, 18.1,
19.4, 20.6, 22.3, 23.9, 25.4)
n <= length(y)
[1] TRUE
# Compute range and bin width
data_range <- range(y)
bin_width <- diff(data_range) / 3
# Define bin boundaries
breaks <- seq(from = data_range[1],
to = data_range[2],
length.out = 4)
breaks
[1] 12.30000 16.66667 21.03333 25.40000
# Count observations in each bin
bin_counts <- table(cut(y, breaks = breaks, include.lowest = TRUE))
bin_counts
[12.3,16.7] (16.7,21] (21,25.4]
3 4 3
# Compute estimated density in each bin
bin_densities <- as.numeric(bin_counts) / (n * bin_width)
bin_densities
[1] 0.08587786 0.11450382 0.08587786
# Present results
density_table <- data.frame(
Bin = levels(cut(y, breaks = breaks, include.lowest = TRUE)),
Count = as.numeric(bin_counts),
Density = bin_densities
)
density_table
Bin Count Density
1 [12.3,16.7] 3 0.08587786
2 (16.7,21] 4 0.11450382
3 (21,25.4] 3 0.08587786
# Visualization
hist(y, breaks = breaks, probability = TRUE,
main = "Histogram with Estimated Bin Densities",
xlab = "Failure Time")

The estimated density in each histogram bin is computed by dividing
the number of observations in that bin by the product of the sample size
and the bin width. The densities sum to 1 when multiplied by band width
with the middle bin having the highest density where failure times are
most concentrated.
The histogram is unimodal and symmetric, having a smooth
distribution
- Write an R function that computes kernel density estimates using a
Gaussian kernel with \(h=2\). Validate
your implementation against R’s built-in density() function.
\[
\hat{f}_h(t) = \frac{1}{nh}\sum_{i=1}^n K\left( \frac{t-t_i}{h}\right),
\ \ \text{ where } \ \ K(u) = \frac{1}{\sqrt{2\pi}} e^{-u^2/2}.
\]
# Gaussian Kernel Density Estimation (h = 2)
kde_gaussian <- function(t, x, h) {
n <- length(x)
sapply(t, function(tt) {
mean(dnorm((tt - x) / h)) / h
})
}
# Validation against density()
t_grid <- seq(min(y) - 2, max(y) + 2, length = 200)
plot(t_grid, kde_gaussian(t_grid, y, h = 2),
type = "l", lwd = 2, col = "blue",
xlab = "t", ylab = "Density",
main = "Gaussian KDE Comparison")
lines(density(y, bw = 2), col = "red", lty = 2)
legend("topright",
legend = c("Manual KDE", "R density()"),
col = c("blue", "red"), lty = c(1, 2))

The curves overlap correctly and confirms the correctness of the
manuel KDE implementation
- Write a custom R function that computes kernel density estimates
using the Epanechnikov kernel with \(h=2\). Validate your implementation by
comparing results with R’s built-in density() function for Gaussian
kernel estimation.
\[
\hat{f}_h(t) = \frac{1}{nh}\sum_{i=1}^n K\left( \frac{t-t_i}{h}\right),
\ \ \text{ where } \ \ K(u) = \frac{3}{4}(1 - u^2) \ \ \text{ for } \ \
|u| \le 1.
\]
# Epanechnikov Kernel Density Estimation (h = 2)
kde_epanechnikov <- function(t, x, h) {
n <- length(x)
sapply(t, function(tt) {
u <- (tt - x) / h
mean(0.75 * (1 - u^2) * (abs(u) <= 1)) / h
})
}
# Visualization
plot(t_grid, kde_epanechnikov(t_grid, y, h = 2),
type = "l", lwd = 2, col = "green",
main = "Epanechnikov KDE (h = 2)",
ylab = "Density", xlab = "Failure Time")
lines(density(y, bw = 2), col = "red", lty = 2)
legend("topright", c("Epanechnikov", "Gaussian"),
col = c("green", "red"), lty = c(1,1))

The Epanechnikov KDE is more compact with limited support
- How does the choice of kernel (Gaussian vs. Epanechnikov) affect the
density estimate? For both kernel estimators applied to this dataset,
what happens when we select \(h=1.5\)
versus \(h=2.5\)?
Kernel choice
- Gaussian: smoother tails, infinite support
- Epanechnikov: compact support, sharper cutoff
- Differences are small
density(y, bw = 1.5)
Call:
density.default(x = y, bw = 1.5)
Data: y (10 obs.); Bandwidth 'bw' = 1.5
x y
Min. : 7.80 Min. :0.000297
1st Qu.:13.32 1st Qu.:0.015141
Median :18.85 Median :0.055866
Mean :18.85 Mean :0.045149
3rd Qu.:24.38 3rd Qu.:0.071778
Max. :29.90 Max. :0.077948
density(y, bw = 2.5)
Call:
density.default(x = y, bw = 2.5)
Data: y (10 obs.); Bandwidth 'bw' = 2.5
x y
Min. : 4.80 Min. :0.0001868
1st Qu.:11.82 1st Qu.:0.0057773
Median :18.85 Median :0.0343512
Mean :18.85 Mean :0.0355077
3rd Qu.:25.88 3rd Qu.:0.0644896
Max. :32.90 Max. :0.0743308
Bandwidth effect
- h = 1.5 → less smoothing, more bumps, higher variance
- h = 2.5 → more smoothing, flatter curve, higher bias
Conclusion
- Bandwidth has a much larger impact on the density estimate than
kernel choice.
LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgMTogRXN0aW1hdGluZyBDREYgYW5kIFBERiINCmF1dGhvcjogIktpZXJhbiBIZWZmZXJhbiAiDQpkYXRlOiAiIER1ZTogMi8zLzI2ICINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogMw0KICAgIGZpZ19oZWlnaHQ6IDMNCiAgd29yZF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQojVE9DOjpiZWZvcmUgew0KICBjb250ZW50OiAiVGFibGUgb2YgQ29udGVudHMiOw0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1zaXplOiAxLjJlbTsNCiAgZGlzcGxheTogYmxvY2s7DQogIGNvbG9yOiBuYXZ5Ow0KICBtYXJnaW4tYm90dG9tOiAxMHB4Ow0KfQ0KDQoNCmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8NCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCg0KaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8NCiAgZm9udC1zaXplOiAyMnB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KfQ0KDQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE1cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMSAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTZweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoNCB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovDQouaGVhZGVyLXNlY3Rpb24tbnVtYmVyOjphZnRlciB7DQogIGNvbnRlbnQ6ICIuIjsNCg0KYm9keSB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCg0KcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KfQ0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoInBhbmRlciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJwYW5kZXIiKQ0KICAgbGlicmFyeShwYW5kZXIpDQp9DQppZiAoIXJlcXVpcmUoImdncGxvdDIiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCiAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCg0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KICBsaWJyYXJ5KHBsb3RseSkNCn0NCiMjIyMNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgICMgc29tZXRpbWVzLCB5b3UgY29kZSBtYXkgcHJvZHVjZSB3YXJuaW5nIG1lc3NhZ2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdSBjYW4gY2hvb3NlIHRvIGluY2x1ZGUgdGhlIHdhcm5pbmcgbWVzc2FnZXMgaW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgICAjIHlvdSBjYW4gYWxzbyBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiB0aGUgb3V0cHV0IGZpbGUuDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQQ0KICAgICAgICAgICAgICAgICAgICAgICkgIA0KYGBgDQogDQogXA0KIA0KIyMgKipBc3NpZ25tZW50IE9iamVjdGl2ZXMqKiANCg0KKiBEZXZlbG9wIGEgY2xlYXIgdGVjaG5pY2FsIHVuZGVyc3RhbmRpbmcgb2Ygbm9ucGFyYW1ldHJpYyBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiAoQ0RGKSBlc3RpbWF0aW9uIGFuZCB2YXJpb3VzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRvcnMuDQoNCiogVHJhbnNsYXRlIG1hdGhlbWF0aWNhbCBmb3JtdWxhcyBpbnRvIFIgZnVuY3Rpb25zIGFuZCBhcHBseSB0aGVtIHRvIHNvbHZlIHJlbGF0ZWQgcHJvYmxlbXMuDQoNCiogQ3JlYXRlIGVmZmVjdGl2ZSB2aXN1YWxpemF0aW9ucyB0byBkZW1vbnN0cmF0ZSB5b3VyIHVuZGVyc3RhbmRpbmcgb2Yga2V5IGNvbmNlcHRzIGluIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zLg0KDQpcDQoNCiMjICoqUXVlc3Rpb24gMTogQ3VtdWxhdGl2ZSBEaXN0cmlidXRpb24gRnVuY3Rpb24gKENERikgRXN0aW1hdGlvbioqDQoNClRoZSBmb2xsb3dpbmcgZmFpbHVyZSB0aW1lcyAoaW4gaG91cnMpIHdlcmUgb2JzZXJ2ZWQgZm9yIDggZWxlY3Ryb25pYyBjb21wb25lbnRzOg0KDQo8Y2VudGVyPiAyMywgNDUsIDY3LCA4OSwgMTEyLCAxNTYsIDE4OSwgMjQ1ICA8L2NlbnRlcj4NCg0KYSkgV3JpdGUgYW4gUiBmdW5jdGlvbiBpbXBsZW1lbnRpbmcgdGhlIEVDREYgJFxoYXR7Rn1fbih0KSQgYWNjb3JkaW5nIHRvIGl0cyBtYXRoZW1hdGljYWwgZGVmaW5pdGlvbi4gVmFsaWRhdGUgeW91ciBpbXBsZW1lbnRhdGlvbiB1c2luZyBSJ3MgZWNkZigpIGZ1bmN0aW9uIG9uIHRoZSBnaXZlbiBkYXRhLCB3aXRoIGNvbXBhcmlzb24gYmFzZWQgb24gdGhlaXIgc3RlcCBmdW5jdGlvbnMuDQpgYGB7cn0NCiMgRmFpbHVyZSB0aW1lcyAoaW4gaG91cnMpIHdlcmUgb2JzZXJ2ZWQgZm9yIDggZWxlY3Ryb25pYyBjb21wb25lbnRzOg0KeCA8LSBjKDIzLCA0NSwgNjcsIDg5LCAxMTIsIDE1NiwgMTg5LCAyNDUpDQpuIDwtIGxlbmd0aCh4KQ0KYGBgDQoNCmBgYHtyfQ0KIyBJbXBsZW1lbnRhdGlvbiBvZiBFQ0RGDQplY2RmX21hbnVhbCA8LSBmdW5jdGlvbih0LCB4KSB7DQogIG1lYW4oeCA8PSB0KQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KIyBWYWxpZGF0aW9uIG9mIEltcGxlbWVudGF0aW9uDQplY2RmX3IgPC0gZWNkZih4KQ0KDQp0X3ZhbHMgPC0gc2VxKDAsIDI2MCwgYnkgPSAxKQ0KDQpwbG90KHRfdmFscywgc2FwcGx5KHRfdmFscywgZWNkZl9tYW51YWwsIHggPSB4KSwNCiAgICAgdHlwZSA9ICJzIiwgY29sID0gImJsdWUiLCBsd2QgPSAyLCBtYWluID0gIkVtcGlyaWNhbCBDREYgb2YgRmFpbHVyZSBUaW1lcyIseWxhYiA9ICJFQ0RGIiwgeGxhYiA9ICJGYWlsdXJlIFRpbWUgKGhvdXJzKSIpDQpsaW5lcyhlY2RmX3IsIGNvbCA9ICJyZWQiLCBsd2QgPSAyLCBsdHkgPSAyKQ0KbGVnZW5kKCJib3R0b21yaWdodCIsIGxlZ2VuZCA9IGMoIk1hbnVhbCBFQ0RGIiwgIlIncyBlY2RmKCkiKSwNCiAgICAgICBjb2wgPSBjKCJibHVlIiwgInJlZCIpLCBsdHkgPSBjKDEsMikpDQoNCmBgYA0KDQpCb3RoIEVDREYncyByZXR1cm4gaWRlbnRpY2FsIHZhbHVlcyBhbmQgaXMgY29udGludW91cyBmcm9tIHRoZSByaWdodCBhdCBldmVyeSBwb2ludCBhbmQgaW5jcmVhc2VzIGJ5IDEvbiA9IDAuMTI1IGZvciBlYWNoIG9ic2VydmVkIGZhaWx1cmUgdGltZQ0KDQoNCmIpIEEgY29sbGVhZ3VlIGNsYWltcyB0aGF0IHRoZSBwcm9iYWJpbGl0eSBvZiBmYWlsdXJlIGJlZm9yZSAxMDAgaG91cnMgaXMgMC41IGJhc2VkIG9uIHRoZXNlIGRhdGEuIERvIHlvdSBhZ3JlZT8gRXhwbGFpbiB5b3VyIHJlYXNvbmluZyB1c2luZyB0aGUgZW1waXJpY2FsIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uIChFQ0RGKS4NCg0KYGBge3J9DQojIE9ic2VydmF0aW9uIG9mIGNvbGxlYWd1ZSBjbGFpbSB1c2luZyBFQ0RGIA0KZWNkZl9tYW51YWwoMTAwLCB4KQ0KYGBgDQoNClRoZSBFQ0RGIGF0IDEwMCBob3VycyBpcyAwLjUsIG1lYW5pbmcgNTAlIG9mIG9ic2VydmVkIGZhaWx1cmVzIG9jY3VycmVkIGJlZm9yZSAxMDAgaG91cnMuDQoNClwNCg0KIyMgKipRdWVzdGlvbiAyOiBEZW5zaXR5IEZ1bmN0aW9uIEVzdGltYXRpb24qKg0KDQpDb25zaWRlciB0aGUgZm9sbG93aW5nIGZhaWx1cmUgdGltZXMgZnJvbSBhIG1lY2hhbmljYWwgc3lzdGVtOg0KDQo8Y2VudGVyPiAxMi4zLCAxNC43LCAxNS4yLCAxNi44LCAxOC4xLCAxOS40LCAyMC42LCAyMi4zLCAyMy45LCAyNS40IDwvY2VudGVyPg0KDQphKSBDcmVhdGUgYSBoaXN0b2dyYW0gb2YgdGhlIGRhdGEgdXNpbmcgMyBlcXVhbGx5IHNwYWNlZCBiaW5zLiBXaGF0IGlzIHRoZSBlc3RpbWF0ZWQgZGVuc2l0eSBpbiBlYWNoIGJpbj8gRGVzY3JpYmUgdGhlIHNoYXBlIG9mIHRoZSBoaXN0b2dyYW0ncyBkaXN0cmlidXRpb24uDQoNCmBgYHtyfQ0KIyBGYWlsdXJlIHRpbWVzIGZyb20gYSBtZWNoYW5pY2FsIHN5c3RlbQ0KeSA8LSBjKDEyLjMsIDE0LjcsIDE1LjIsIDE2LjgsIDE4LjEsDQogICAgICAgMTkuNCwgMjAuNiwgMjIuMywgMjMuOSwgMjUuNCkNCg0KbiA8PSBsZW5ndGgoeSkNCmBgYA0KDQpgYGB7cn0NCiMgQ29tcHV0ZSByYW5nZSBhbmQgYmluIHdpZHRoDQpkYXRhX3JhbmdlIDwtIHJhbmdlKHkpDQpiaW5fd2lkdGggPC0gZGlmZihkYXRhX3JhbmdlKSAvIDMNCg0KIyBEZWZpbmUgYmluIGJvdW5kYXJpZXMNCmJyZWFrcyA8LSBzZXEoZnJvbSA9IGRhdGFfcmFuZ2VbMV0sDQogICAgICAgICAgICAgIHRvICAgPSBkYXRhX3JhbmdlWzJdLA0KICAgICAgICAgICAgICBsZW5ndGgub3V0ID0gNCkNCg0KYnJlYWtzDQpgYGANCg0KYGBge3J9DQojIENvdW50IG9ic2VydmF0aW9ucyBpbiBlYWNoIGJpbg0KYmluX2NvdW50cyA8LSB0YWJsZShjdXQoeSwgYnJlYWtzID0gYnJlYWtzLCBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpKQ0KYmluX2NvdW50cw0KYGBgDQoNCmBgYHtyfQ0KIyBDb21wdXRlIGVzdGltYXRlZCBkZW5zaXR5IGluIGVhY2ggYmluDQpiaW5fZGVuc2l0aWVzIDwtIGFzLm51bWVyaWMoYmluX2NvdW50cykgLyAobiAqIGJpbl93aWR0aCkNCg0KYmluX2RlbnNpdGllcw0KYGBgDQoNCmBgYHtyfQ0KIyBQcmVzZW50IHJlc3VsdHMNCmRlbnNpdHlfdGFibGUgPC0gZGF0YS5mcmFtZSgNCiAgQmluID0gbGV2ZWxzKGN1dCh5LCBicmVha3MgPSBicmVha3MsIGluY2x1ZGUubG93ZXN0ID0gVFJVRSkpLA0KICBDb3VudCA9IGFzLm51bWVyaWMoYmluX2NvdW50cyksDQogIERlbnNpdHkgPSBiaW5fZGVuc2l0aWVzDQopDQoNCmRlbnNpdHlfdGFibGUNCmBgYA0KDQpgYGB7cn0NCiMgVmlzdWFsaXphdGlvbiANCmhpc3QoeSwgYnJlYWtzID0gYnJlYWtzLCBwcm9iYWJpbGl0eSA9IFRSVUUsDQogICAgIG1haW4gPSAiSGlzdG9ncmFtIHdpdGggRXN0aW1hdGVkIEJpbiBEZW5zaXRpZXMiLA0KICAgICB4bGFiID0gIkZhaWx1cmUgVGltZSIpDQpgYGANCg0KVGhlIGVzdGltYXRlZCBkZW5zaXR5IGluIGVhY2ggaGlzdG9ncmFtIGJpbiBpcyBjb21wdXRlZCBieSBkaXZpZGluZyB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBpbiB0aGF0IGJpbiBieSB0aGUgcHJvZHVjdCBvZiB0aGUgc2FtcGxlIHNpemUgYW5kIHRoZSBiaW4gd2lkdGguIFRoZSBkZW5zaXRpZXMgc3VtIHRvIDEgd2hlbiBtdWx0aXBsaWVkIGJ5IGJhbmQgd2lkdGggd2l0aCB0aGUgbWlkZGxlIGJpbiBoYXZpbmcgdGhlIGhpZ2hlc3QgZGVuc2l0eSB3aGVyZSBmYWlsdXJlIHRpbWVzIGFyZSBtb3N0IGNvbmNlbnRyYXRlZC4NCg0KVGhlIGhpc3RvZ3JhbSBpcyB1bmltb2RhbCBhbmQgc3ltbWV0cmljLCBoYXZpbmcgYSBzbW9vdGggZGlzdHJpYnV0aW9uDQoNCmIpIFdyaXRlIGFuIFIgZnVuY3Rpb24gdGhhdCBjb21wdXRlcyBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZXMgdXNpbmcgYSBHYXVzc2lhbiBrZXJuZWwgd2l0aCAkaD0yJC4gVmFsaWRhdGUgeW91ciBpbXBsZW1lbnRhdGlvbiBhZ2FpbnN0IFIncyBidWlsdC1pbiBkZW5zaXR5KCkgZnVuY3Rpb24uDQoNCiQkDQpcaGF0e2Z9X2godCkgPSBcZnJhY3sxfXtuaH1cc3VtX3tpPTF9Xm4gS1xsZWZ0KCBcZnJhY3t0LXRfaX17aH1ccmlnaHQpLCBcIFwgXHRleHR7IHdoZXJlIH0gXCBcIEsodSkgPSBcZnJhY3sxfXtcc3FydHsyXHBpfX0gZV57LXVeMi8yfS4NCiQkDQoNCmBgYHtyfQ0KIyBHYXVzc2lhbiBLZXJuZWwgRGVuc2l0eSBFc3RpbWF0aW9uIChoID0gMikNCmtkZV9nYXVzc2lhbiA8LSBmdW5jdGlvbih0LCB4LCBoKSB7DQogIG4gPC0gbGVuZ3RoKHgpDQogIHNhcHBseSh0LCBmdW5jdGlvbih0dCkgew0KICAgIG1lYW4oZG5vcm0oKHR0IC0geCkgLyBoKSkgLyBoDQogIH0pDQp9DQpgYGANCg0KYGBge3J9DQojIFZhbGlkYXRpb24gYWdhaW5zdCBkZW5zaXR5KCkNCnRfZ3JpZCA8LSBzZXEobWluKHkpIC0gMiwgbWF4KHkpICsgMiwgbGVuZ3RoID0gMjAwKQ0KDQpwbG90KHRfZ3JpZCwga2RlX2dhdXNzaWFuKHRfZ3JpZCwgeSwgaCA9IDIpLA0KICAgICB0eXBlID0gImwiLCBsd2QgPSAyLCBjb2wgPSAiYmx1ZSIsDQogICAgIHhsYWIgPSAidCIsIHlsYWIgPSAiRGVuc2l0eSIsDQogICAgIG1haW4gPSAiR2F1c3NpYW4gS0RFIENvbXBhcmlzb24iKQ0KDQpsaW5lcyhkZW5zaXR5KHksIGJ3ID0gMiksIGNvbCA9ICJyZWQiLCBsdHkgPSAyKQ0KDQpsZWdlbmQoInRvcHJpZ2h0IiwNCiAgICAgICBsZWdlbmQgPSBjKCJNYW51YWwgS0RFIiwgIlIgZGVuc2l0eSgpIiksDQogICAgICAgY29sID0gYygiYmx1ZSIsICJyZWQiKSwgbHR5ID0gYygxLCAyKSkNCmBgYA0KDQpUaGUgY3VydmVzIG92ZXJsYXAgY29ycmVjdGx5IGFuZCBjb25maXJtcyB0aGUgY29ycmVjdG5lc3Mgb2YgdGhlIG1hbnVlbCBLREUgaW1wbGVtZW50YXRpb24NCg0KYykgV3JpdGUgYSBjdXN0b20gUiBmdW5jdGlvbiB0aGF0IGNvbXB1dGVzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlcyB1c2luZyB0aGUgRXBhbmVjaG5pa292IGtlcm5lbCB3aXRoICRoPTIkLiBWYWxpZGF0ZSB5b3VyIGltcGxlbWVudGF0aW9uIGJ5IGNvbXBhcmluZyByZXN1bHRzIHdpdGggUidzIGJ1aWx0LWluIGRlbnNpdHkoKSBmdW5jdGlvbiBmb3IgR2F1c3NpYW4ga2VybmVsIGVzdGltYXRpb24uDQoNCg0KJCQNClxoYXR7Zn1faCh0KSA9IFxmcmFjezF9e25ofVxzdW1fe2k9MX1ebiBLXGxlZnQoIFxmcmFje3QtdF9pfXtofVxyaWdodCksIFwgXCBcdGV4dHsgd2hlcmUgfSBcIFwgSyh1KSA9IFxmcmFjezN9ezR9KDEgLSB1XjIpIFwgXCBcdGV4dHsgZm9yIH0gXCBcIHx1fCBcbGUgMS4NCiQkDQoNCmBgYHtyfQ0KIyBFcGFuZWNobmlrb3YgS2VybmVsIERlbnNpdHkgRXN0aW1hdGlvbiAoaCA9IDIpDQprZGVfZXBhbmVjaG5pa292IDwtIGZ1bmN0aW9uKHQsIHgsIGgpIHsNCiAgbiA8LSBsZW5ndGgoeCkNCiAgc2FwcGx5KHQsIGZ1bmN0aW9uKHR0KSB7DQogICAgdSA8LSAodHQgLSB4KSAvIGgNCiAgICBtZWFuKDAuNzUgKiAoMSAtIHVeMikgKiAoYWJzKHUpIDw9IDEpKSAvIGgNCiAgfSkNCn0NCmBgYA0KDQpgYGB7cn0NCiMgVmlzdWFsaXphdGlvbiANCnBsb3QodF9ncmlkLCBrZGVfZXBhbmVjaG5pa292KHRfZ3JpZCwgeSwgaCA9IDIpLA0KICAgICB0eXBlID0gImwiLCBsd2QgPSAyLCBjb2wgPSAiZ3JlZW4iLA0KICAgICBtYWluID0gIkVwYW5lY2huaWtvdiBLREUgKGggPSAyKSIsDQogICAgIHlsYWIgPSAiRGVuc2l0eSIsIHhsYWIgPSAiRmFpbHVyZSBUaW1lIikNCmxpbmVzKGRlbnNpdHkoeSwgYncgPSAyKSwgY29sID0gInJlZCIsIGx0eSA9IDIpDQpsZWdlbmQoInRvcHJpZ2h0IiwgYygiRXBhbmVjaG5pa292IiwgIkdhdXNzaWFuIiksDQogICAgICAgY29sID0gYygiZ3JlZW4iLCAicmVkIiksIGx0eSA9IGMoMSwxKSkNCmBgYA0KDQpUaGUgRXBhbmVjaG5pa292IEtERSBpcyBtb3JlIGNvbXBhY3Qgd2l0aCBsaW1pdGVkIHN1cHBvcnQNCg0KZCkgSG93IGRvZXMgdGhlIGNob2ljZSBvZiBrZXJuZWwgKEdhdXNzaWFuIHZzLiBFcGFuZWNobmlrb3YpIGFmZmVjdCB0aGUgZGVuc2l0eSBlc3RpbWF0ZT8gRm9yIGJvdGgga2VybmVsIGVzdGltYXRvcnMgYXBwbGllZCB0byB0aGlzIGRhdGFzZXQsIHdoYXQgaGFwcGVucyB3aGVuIHdlIHNlbGVjdCAkaD0xLjUkIHZlcnN1cyAkaD0yLjUkPw0KDQpLZXJuZWwgY2hvaWNlDQoNCi0gICBHYXVzc2lhbjogc21vb3RoZXIgdGFpbHMsIGluZmluaXRlIHN1cHBvcnQNCi0gICBFcGFuZWNobmlrb3Y6IGNvbXBhY3Qgc3VwcG9ydCwgc2hhcnBlciBjdXRvZmYNCi0gICBEaWZmZXJlbmNlcyBhcmUgc21hbGwNCg0KYGBge3J9DQpkZW5zaXR5KHksIGJ3ID0gMS41KQ0KZGVuc2l0eSh5LCBidyA9IDIuNSkNCmBgYA0KDQpCYW5kd2lkdGggZWZmZWN0DQoNCi0gICBoID0gMS41IOKGkiBsZXNzIHNtb290aGluZywgbW9yZSBidW1wcywgaGlnaGVyIHZhcmlhbmNlDQotICAgaCA9IDIuNSDihpIgbW9yZSBzbW9vdGhpbmcsIGZsYXR0ZXIgY3VydmUsIGhpZ2hlciBiaWFzDQoNCg0KQ29uY2x1c2lvbg0KDQotICAgQmFuZHdpZHRoIGhhcyBhIG11Y2ggbGFyZ2VyIGltcGFjdCBvbiB0aGUgZGVuc2l0eSBlc3RpbWF0ZSB0aGFuIGtlcm5lbCBjaG9pY2UuDQoNCg0KDQoNCg==