Question 1: Cumulative Distribution Function (CDF) Estimation

Part A

Since we are estimating an empirical distribution, we can apply the formula here: \[ F_n(x) =\frac{1}{n}\sum_{i=1}^n I(X_i \le x) = \frac{[\ \text{Number of } X_i \le x]}{n} \]

In our case, n = 8. So, for every point, we should get an increase of our cumuluative probability to be 1/8.

x = c(23, 45, 67, 89, 112, 156, 189, 245)
unique.x <- sort(unique(x)) # sort unique values of x

myECDF <- function(indat, outx){
  # outx - a vector of given values
  freq.table <- table(indat)                          # frequency table
  uniq <- as.numeric(names(freq.table))          # unique data values
  rep.x <- as.vector(freq.table)                   # frequencies of the unique data values
  cum.rel.feq <- cumsum(rep.x)/sum(rep.x)       # cumulative relative frequencies: CDF
  cum.prob <- NULL
  for (i in 1:length(outx)){
    intvl.id <- which(uniq <= outx[i])      # identify the index meeting the condition
    cum.prob[i] <- cum.rel.feq[max(intvl.id)] # extract the cumulative prob according to CDF 
  }
  cum.prob          
}

myECDF(x, unique.x)
[1] 0.125 0.250 0.375 0.500 0.625 0.750 0.875 1.000

We can also verify our estimates via the ecdf() function:

empirical_cdfx <- ecdf(x)
empirical_cdfx(x)
[1] 0.125 0.250 0.375 0.500 0.625 0.750 0.875 1.000

The results seem to match, so our estimate seems to be correct.

Part B

Yes, I agree with the colleague. 4 data points are less than or equal to 100. Referencing the formula from Part A, we can say the numerator is 4, and our n is still 8, so our cumulative probability should be 4/8, or 1/2. To verify, we can use the ecdf() function from Part A:

empirical_cdfx(100)
[1] 0.5

And we get an output of 0.5. So the colleague is correct.

Question 2: Density Function Estimation

Part A

y <- c(12.3, 14.7, 15.2, 16.8, 18.1, 19.4, 20.6, 22.3, 23.9, 25.4)

hist.y <-hist(y, breaks = seq(12, 26, length.out = 4), freq = FALSE, main = "Histogram of Failure Times")

hist.y$density
[1] 0.06428571 0.08571429 0.06428571
#seq function taken as suggestion to force 3 bins from stackoverflow.com

According to our graph, the estimates are 0.0643, 0.0857, and 0.0643. The histogram looks symmetrical about the second bin, but we need more bins/data to be sure of the distribution’s true shape.

Part B

Function used to estimate the densities:

mykerf <- function(in.data, h, out.x){
  n <- length(in.data)     # sample size
  den <- NULL              # density vector to store output values
  for (i in 1:length(out.x)){
    den[i] <- sum(dnorm(out.x[i], mean=in.data, sd = h))/n  # kernel density formula
  }
  den  # return density values based on the out.x values
}

These are the values of the gaussian kernel estimates with h = 2:

d1 <- mykerf(y, 2, y)
d1
 [1] 0.03855284 0.06671954 0.07046656 0.07600381 0.07587074 0.07360217
 [7] 0.06993562 0.06400803 0.05652506 0.04237326

To verify, these are the kernel estimates using the density() function:

d2 <- density(y, bw = 2, n = 10)
d2$x #the estimated values of the distribution
 [1]  6.300000  9.088889 11.877778 14.666667 17.455556 20.244444 23.033333
 [8] 25.822222 28.611111 31.400000
d2$y #the values of the corresponding density estimates
 [1] 0.0002260196 0.0060884538 0.0330404547 0.0664300753 0.0762536983
 [6] 0.0711297655 0.0611758565 0.0370947939 0.0068889038 0.0002403998

Part C

d4 <- density(y, bw = 2, kernel = "epanechnikov")

Part D

The different methods use different weighting functions. So different values aren’t weighted the same.

d5 <- density(y, bw = 1.5, kernel = "gaussian", n = 10)
d6 <- density(y, bw = 2.5, kernel = "gaussian", n = 10)
d7 <- density(y, bw = 1.5, kernel = "epanechnikov", n = 10)
d8 <- density(y, bw = 2.5, kernel = "epanechnikov", n = 10)

It seems that the estimated values of the distributions didn’t change, but their density estimates changed.

d5

Call:
    density.default(x = y, bw = 1.5, kernel = "gaussian", n = 10)

Data: y (10 obs.);  Bandwidth 'bw' = 1.5

       x               y           
 Min.   : 7.80   Min.   :0.000297  
 1st Qu.:13.32   1st Qu.:0.011274  
 Median :18.85   Median :0.047917  
 Mean   :18.85   Mean   :0.040735  
 3rd Qu.:24.38   3rd Qu.:0.070350  
 Max.   :29.90   Max.   :0.076519  
d6

Call:
    density.default(x = y, bw = 2.5, kernel = "gaussian", n = 10)

Data: y (10 obs.);  Bandwidth 'bw' = 2.5

       x               y            
 Min.   : 4.80   Min.   :0.0001868  
 1st Qu.:11.82   1st Qu.:0.0042516  
 Median :18.85   Median :0.0262266  
 Mean   :18.85   Mean   :0.0320283  
 3rd Qu.:25.88   3rd Qu.:0.0579508  
 Max.   :32.90   Max.   :0.0740767  
d7

Call:
    density.default(x = y, bw = 1.5, kernel = "epanechnikov", n = 10)

Data: y (10 obs.);  Bandwidth 'bw' = 1.5

       x               y          
 Min.   : 7.80   Min.   :0.00000  
 1st Qu.:13.32   1st Qu.:0.01405  
 Median :18.85   Median :0.04828  
 Mean   :18.85   Mean   :0.04132  
 3rd Qu.:24.38   3rd Qu.:0.06972  
 Max.   :29.90   Max.   :0.07981  
d8

Call:
    density.default(x = y, bw = 2.5, kernel = "epanechnikov", n = 10)

Data: y (10 obs.);  Bandwidth 'bw' = 2.5

       x               y           
 Min.   : 4.80   Min.   :0.000000  
 1st Qu.:11.82   1st Qu.:0.005187  
 Median :18.85   Median :0.027290  
 Mean   :18.85   Mean   :0.032055  
 3rd Qu.:25.88   3rd Qu.:0.056422  
 Max.   :32.90   Max.   :0.074101  
LS0tDQp0aXRsZTogIlNUQTUwNl9Bc3NpZ25tZW50IDE6IEVzdGltYXRpbmcgQ0RGIGFuZCBQREYiDQphdXRob3I6ICJJYW4gVmFuV3JpZ2h0ICINCmRhdGU6ICIwMS8yOS8yMDI2Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIHRoZW1lOiBsdW1lbg0KICBwZGZfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiAzDQogICAgZmlnX2hlaWdodDogMw0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCiNUT0M6OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICJUYWJsZSBvZiBDb250ZW50cyI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuMmVtOw0KICBkaXNwbGF5OiBibG9jazsNCiAgY29sb3I6IG5hdnk7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCg0KZGl2I1RPQyBsaSB7ICAgICAvKiB0YWJsZSBvZiBjb250ZW50ICAqLw0KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLw0KICBmb250LXNpemU6IDIycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMTVweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KDQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQp9DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpDQogICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICBsaWJyYXJ5KGdncGxvdDIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KDQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogIGxpYnJhcnkocGxvdGx5KQ0KfQ0KIyMjIw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICAjIGluY2x1ZGUgY29kZSBjaHVuayBpbiB0aGUgb3V0cHV0IGZpbGUNCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91IGNhbiBjaG9vc2UgdG8gaW5jbHVkZSB0aGUgd2FybmluZyBtZXNzYWdlcyBpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBvdXRwdXQgZmlsZS4gDQogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICAgICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGluIHRoZSBvdXRwdXQgZmlsZS4NCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BDQogICAgICAgICAgICAgICAgICAgICAgKSAgDQpgYGANCiANCiBcDQogDQoNCiMgKipRdWVzdGlvbiAxOiBDdW11bGF0aXZlIERpc3RyaWJ1dGlvbiBGdW5jdGlvbiAoQ0RGKSBFc3RpbWF0aW9uKioNCg0KIyMgUGFydCBBDQpTaW5jZSB3ZSBhcmUgZXN0aW1hdGluZyBhbiBlbXBpcmljYWwgZGlzdHJpYnV0aW9uLCB3ZSBjYW4gYXBwbHkgdGhlIGZvcm11bGEgaGVyZToNCiQkDQpGX24oeCkgPVxmcmFjezF9e259XHN1bV97aT0xfV5uIEkoWF9pIFxsZSB4KSA9IFxmcmFje1tcIFx0ZXh0e051bWJlciBvZiAgfSBYX2kgXGxlIHhdfXtufQ0KJCQNCg0KSW4gb3VyIGNhc2UsIG4gPSA4LiBTbywgZm9yIGV2ZXJ5IHBvaW50LCB3ZSBzaG91bGQgZ2V0IGFuIGluY3JlYXNlIG9mIG91ciBjdW11bHVhdGl2ZSBwcm9iYWJpbGl0eSB0byBiZSAxLzguDQpgYGB7cn0NCnggPSBjKDIzLCA0NSwgNjcsIDg5LCAxMTIsIDE1NiwgMTg5LCAyNDUpDQp1bmlxdWUueCA8LSBzb3J0KHVuaXF1ZSh4KSkgIyBzb3J0IHVuaXF1ZSB2YWx1ZXMgb2YgeA0KDQpteUVDREYgPC0gZnVuY3Rpb24oaW5kYXQsIG91dHgpew0KICAjIG91dHggLSBhIHZlY3RvciBvZiBnaXZlbiB2YWx1ZXMNCiAgZnJlcS50YWJsZSA8LSB0YWJsZShpbmRhdCkgICAgICAgICAgICAgICAgICAgICAgICAgICMgZnJlcXVlbmN5IHRhYmxlDQogIHVuaXEgPC0gYXMubnVtZXJpYyhuYW1lcyhmcmVxLnRhYmxlKSkgICAgICAgICAgIyB1bmlxdWUgZGF0YSB2YWx1ZXMNCiAgcmVwLnggPC0gYXMudmVjdG9yKGZyZXEudGFibGUpICAgICAgICAgICAgICAgICAgICMgZnJlcXVlbmNpZXMgb2YgdGhlIHVuaXF1ZSBkYXRhIHZhbHVlcw0KICBjdW0ucmVsLmZlcSA8LSBjdW1zdW0ocmVwLngpL3N1bShyZXAueCkgICAgICAgIyBjdW11bGF0aXZlIHJlbGF0aXZlIGZyZXF1ZW5jaWVzOiBDREYNCiAgY3VtLnByb2IgPC0gTlVMTA0KICBmb3IgKGkgaW4gMTpsZW5ndGgob3V0eCkpew0KICAgIGludHZsLmlkIDwtIHdoaWNoKHVuaXEgPD0gb3V0eFtpXSkgICAgICAjIGlkZW50aWZ5IHRoZSBpbmRleCBtZWV0aW5nIHRoZSBjb25kaXRpb24NCiAgICBjdW0ucHJvYltpXSA8LSBjdW0ucmVsLmZlcVttYXgoaW50dmwuaWQpXSAjIGV4dHJhY3QgdGhlIGN1bXVsYXRpdmUgcHJvYiBhY2NvcmRpbmcgdG8gQ0RGIA0KICB9DQogIGN1bS5wcm9iICAgICAgICAgIA0KfQ0KDQpteUVDREYoeCwgdW5pcXVlLngpDQpgYGANCg0KV2UgY2FuIGFsc28gdmVyaWZ5IG91ciBlc3RpbWF0ZXMgdmlhIHRoZSBlY2RmKCkgZnVuY3Rpb246DQpgYGB7cn0NCmVtcGlyaWNhbF9jZGZ4IDwtIGVjZGYoeCkNCmVtcGlyaWNhbF9jZGZ4KHgpDQpgYGANCg0KVGhlIHJlc3VsdHMgc2VlbSB0byBtYXRjaCwgc28gb3VyIGVzdGltYXRlIHNlZW1zIHRvIGJlIGNvcnJlY3QuDQoNCg0KIyMgUGFydCBCDQpZZXMsIEkgYWdyZWUgd2l0aCB0aGUgY29sbGVhZ3VlLiA0IGRhdGEgcG9pbnRzIGFyZSBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gMTAwLiBSZWZlcmVuY2luZyB0aGUgZm9ybXVsYSBmcm9tIFBhcnQgQSwgd2UgY2FuIHNheSB0aGUgbnVtZXJhdG9yIGlzIDQsIGFuZCBvdXIgbiBpcyBzdGlsbCA4LCBzbyBvdXIgY3VtdWxhdGl2ZSBwcm9iYWJpbGl0eSBzaG91bGQgYmUgNC84LCBvciAxLzIuIFRvIHZlcmlmeSwgd2UgY2FuIHVzZSB0aGUgZWNkZigpIGZ1bmN0aW9uIGZyb20gUGFydCBBOg0KYGBge3J9DQplbXBpcmljYWxfY2RmeCgxMDApDQpgYGANCkFuZCB3ZSBnZXQgYW4gb3V0cHV0IG9mIDAuNS4gU28gdGhlIGNvbGxlYWd1ZSBpcyBjb3JyZWN0Lg0KDQoNCiMgKipRdWVzdGlvbiAyOiBEZW5zaXR5IEZ1bmN0aW9uIEVzdGltYXRpb24qKg0KIyMgUGFydCBBDQpgYGB7cn0NCnkgPC0gYygxMi4zLCAxNC43LCAxNS4yLCAxNi44LCAxOC4xLCAxOS40LCAyMC42LCAyMi4zLCAyMy45LCAyNS40KQ0KDQpoaXN0LnkgPC1oaXN0KHksIGJyZWFrcyA9IHNlcSgxMiwgMjYsIGxlbmd0aC5vdXQgPSA0KSwgZnJlcSA9IEZBTFNFLCBtYWluID0gIkhpc3RvZ3JhbSBvZiBGYWlsdXJlIFRpbWVzIikNCmhpc3QueSRkZW5zaXR5DQoNCiNzZXEgZnVuY3Rpb24gdGFrZW4gYXMgc3VnZ2VzdGlvbiB0byBmb3JjZSAzIGJpbnMgZnJvbSBzdGFja292ZXJmbG93LmNvbQ0KYGBgDQpBY2NvcmRpbmcgdG8gb3VyIGdyYXBoLCB0aGUgZXN0aW1hdGVzIGFyZSAwLjA2NDMsIDAuMDg1NywgYW5kIDAuMDY0My4NClRoZSBoaXN0b2dyYW0gbG9va3Mgc3ltbWV0cmljYWwgYWJvdXQgdGhlIHNlY29uZCBiaW4sIGJ1dCB3ZSBuZWVkIG1vcmUgYmlucy9kYXRhIHRvIGJlIHN1cmUgb2YgdGhlIGRpc3RyaWJ1dGlvbidzIHRydWUgc2hhcGUuDQoNCiMjIFBhcnQgQg0KRnVuY3Rpb24gdXNlZCB0byBlc3RpbWF0ZSB0aGUgZGVuc2l0aWVzOg0KYGBge3J9DQpteWtlcmYgPC0gZnVuY3Rpb24oaW4uZGF0YSwgaCwgb3V0Lngpew0KICBuIDwtIGxlbmd0aChpbi5kYXRhKSAgICAgIyBzYW1wbGUgc2l6ZQ0KICBkZW4gPC0gTlVMTCAgICAgICAgICAgICAgIyBkZW5zaXR5IHZlY3RvciB0byBzdG9yZSBvdXRwdXQgdmFsdWVzDQogIGZvciAoaSBpbiAxOmxlbmd0aChvdXQueCkpew0KICAgIGRlbltpXSA8LSBzdW0oZG5vcm0ob3V0LnhbaV0sIG1lYW49aW4uZGF0YSwgc2QgPSBoKSkvbiAgIyBrZXJuZWwgZGVuc2l0eSBmb3JtdWxhDQogIH0NCiAgZGVuICAjIHJldHVybiBkZW5zaXR5IHZhbHVlcyBiYXNlZCBvbiB0aGUgb3V0LnggdmFsdWVzDQp9DQpgYGANCg0KVGhlc2UgYXJlIHRoZSB2YWx1ZXMgb2YgdGhlIGdhdXNzaWFuIGtlcm5lbCBlc3RpbWF0ZXMgd2l0aCBoID0gMjoNCmBgYHtyfQ0KZDEgPC0gbXlrZXJmKHksIDIsIHkpDQpkMQ0KYGBgDQoNClRvIHZlcmlmeSwgdGhlc2UgYXJlIHRoZSBrZXJuZWwgZXN0aW1hdGVzIHVzaW5nIHRoZSBkZW5zaXR5KCkgZnVuY3Rpb246DQpgYGB7cn0NCmQyIDwtIGRlbnNpdHkoeSwgYncgPSAyLCBuID0gMTApDQpkMiR4ICN0aGUgZXN0aW1hdGVkIHZhbHVlcyBvZiB0aGUgZGlzdHJpYnV0aW9uDQpkMiR5ICN0aGUgdmFsdWVzIG9mIHRoZSBjb3JyZXNwb25kaW5nIGRlbnNpdHkgZXN0aW1hdGVzDQpgYGANCiMjIFBhcnQgQw0KYGBge3J9DQpkNCA8LSBkZW5zaXR5KHksIGJ3ID0gMiwga2VybmVsID0gImVwYW5lY2huaWtvdiIpDQpgYGANCg0KIyMgUGFydCBEDQpUaGUgZGlmZmVyZW50IG1ldGhvZHMgdXNlIGRpZmZlcmVudCB3ZWlnaHRpbmcgZnVuY3Rpb25zLiBTbyBkaWZmZXJlbnQgdmFsdWVzIGFyZW4ndCB3ZWlnaHRlZCB0aGUgc2FtZS4NCmBgYHtyfQ0KZDUgPC0gZGVuc2l0eSh5LCBidyA9IDEuNSwga2VybmVsID0gImdhdXNzaWFuIiwgbiA9IDEwKQ0KZDYgPC0gZGVuc2l0eSh5LCBidyA9IDIuNSwga2VybmVsID0gImdhdXNzaWFuIiwgbiA9IDEwKQ0KZDcgPC0gZGVuc2l0eSh5LCBidyA9IDEuNSwga2VybmVsID0gImVwYW5lY2huaWtvdiIsIG4gPSAxMCkNCmQ4IDwtIGRlbnNpdHkoeSwgYncgPSAyLjUsIGtlcm5lbCA9ICJlcGFuZWNobmlrb3YiLCBuID0gMTApDQpgYGANCg0KSXQgc2VlbXMgdGhhdCB0aGUgZXN0aW1hdGVkIHZhbHVlcyBvZiB0aGUgZGlzdHJpYnV0aW9ucyBkaWRuJ3QgY2hhbmdlLCBidXQgdGhlaXIgZGVuc2l0eSBlc3RpbWF0ZXMgY2hhbmdlZC4NCmBgYHtyfQ0KZDUNCmQ2DQpkNw0KZDgNCmBgYA0KDQoNCg0K