Uniform and Poisson distribution
Let’s generate 200 samples from uniform distribution in the interval \([0,10]\).
set.seed(2017)
n <- 1000
sample <- runif(n, min = 0, max = 10)
hist(sample, breaks = 100, probability = TRUE, col = 3, main = "Uniform distribution samples")
lines(density(sample, adjust = 2), col = 2)
If we divide the interval \([0,10]\) into \(k\) sub-intervals and count how many data points are inside each of them, say \(n_1, \cdots, n_k\). Then these counts will follow Poisson distribution. That is, \[ \mathbb{P} (m \text{ points in a unit interval}) = \frac{\lambda^m}{m!}e^{-\lambda}, m=0,1,\cdots\]
Therefore, we expect \(\{n_1, \cdots, n_k\}\) to follow a Poisson. Let’s verify it by simulation. We divide the interval into 100 sub-intervals, i.e. \(k = 100\).
k <- 100
tab <- table(cut(sample, breaks = seq(0, 10, length.out = k+1), include.lowest = TRUE))
head(tab, 10)
[0,0.1] (0.1,0.2] (0.2,0.3] (0.3,0.4] (0.4,0.5] (0.5,0.6] (0.6,0.7] (0.7,0.8] (0.8,0.9] (0.9,1]
13 10 13 8 11 5 11 7 6 7
counts <- as.vector(tab)
head(counts, 10)
[1] 13 10 13 8 11 5 11 7 6 7
So by theory, the counts should follow a Poisson process. Let’s compare it with a generated Poisson sequence. We know \(\lambda\) equals to the expected number of points in an interval, so here, we set \(\lambda = k^{-1}\sum_{i=1}^k n_i\).
hist(counts, breaks = 15, col = rgb(1,0,0,0.5), probability = TRUE, xlab = "number of points inside an interval", ylim = c(0,0.2))
lines(density(counts, adjust = 2), col = rgb(1,0,0,0.5))
Pois <- rpois(1000, lambda = mean(counts))
hist(Pois, breaks = 15, col = rgb(0,0,1,0.5), probability = TRUE, add = TRUE)
lines(density(Pois, adjust = 2), col = rgb(0,0,1,0.5))
legend(x = 14, y = 0.15, legend = c("sample", "Poisson"), lty = c(1,1), col = c(rgb(1,0,0,0.5), rgb(0,0,1,0.5)))
We can see our counts variable is indeed very close to Poisson distribution.
Pearson’s \(\chi^2\) Test (goodness of fit)
A test of goodness of fit establishes whether an observed frequency distribution differs from a theoretical distribution.
Test procedure
Let’s now use the Peason’s \(\chi^2\) test to check whether the sample does follow Uniform distribution (because we know we generated the sample from Uniform, so of course we should expect a good result).
Step 1. Calculate the chi-squared test statistic, \(\chi^2\), which resembles a normalized sum of squared deviations between observed and theoretical frequencies, \(O_i\) and \(E_i\). The formula is \[ \chi^2 = \sum_{i=1}^k \frac{(O_i - E_i)^2}{E_i} = n \sum_{i=1}^k \frac{(O_i/n - p_i)^2}{p_i}, \] where \(k\) is the number of cells or intervals in which you calculated frequencies, \(n\) is the total number of samples, and \(p_i = E_i/n\) is the expected probability in the \(i\)-th interval.
Let’s calculate the observed and theoretical frequencies for our sample and Uniform distribution. We already have our \(O_i\)’s, for Uniform distribution, we know \(E_i = n/k = 1000/100\) in this case. We have \(\chi^2 = 82.2\).
E_i <- n/k
chi_2 <- sum((counts - E_i)^2/E_i)
chi_2
Step 2. Determine the degrees of freedom, df, of that statistic. In the test of goodness of fit, the degree of freedom equals to \(k - p\), where \(k\) is the number of cells or intervals, and \(p = s+1\) is the contraint in that distribution, here, \(s\) is the number of parameters for the distribution we want to test against. For example, a Normal distribution \(\mathcal{N}(\mu, \sigma^2)\) has two parameters, \(\mu\) and \(\sigma\), thus \(s = 2\). In our discrete Uniform case, we have \(p = 1\). So df will be \(100-1=99\).
Step 3. Select a desired level of confidence. We will select \(\alpha = 0.05\).
- Step 4.
- Compare the test statistic \(\chi^2\) to the value from the chi-squared distribution with df degrees of freedom and the selected confidence level, \(1 - \alpha\).
- Or we can calculate the \(p\)-value, \(\mathbb{P}(X > \chi^2)\), where \(X\) is a chi-square random variable with df degree of freedoms.
- Note that the test is one-sided.
chi2_compare <- qchisq(p = 0.95, df = 99)
chi2_compare
p_value <- 1 - pchisq(chi_2, df = 99)
p_value
Built-in R function
We can also use the built-in function chisq.test()
.
p_i <- rep(E_i/n, k)
chisq.test(counts, p = p_i)
Standardized residual plot
We can also plot the standardized residuals, which are defined to be \[ R_i = \frac{|O_i - E_i|}{\sqrt{E_i}}\] in each interval. So recall the definition of \(\chi^2\) statistic, we actually have \[\chi^2 = \sum_{i=1}^k R_i^2.\]
Residuals <- (counts - E_i) / sqrt(E_i)
plot(Residuals, type = 'h', ylab = "standardized residuals", xlab = "interval index")
Two Sample t-test
- Two sample t-test can be used to determine if the means of two sets of data are significantly different. But one of the underlying assumptions is that both group of data follow Normal distribution. So we should first check if Normality assumption is satisfied (Q-Q plot, ecdf, Shapiro–Wilk, Kolmogorov–Smirnov) before we apply this test.
- We should first check if two samples have the same variance. This can be done using Fisher’s F-test (it counts in the effect of different sample sizes).
- Details of two sample t-test are postponed to MATH 181 if you have not touched it before.
set.seed(2017)
sample1 <- rnorm(200, mean = 0, sd = 1)
sample2 <- rnorm(300, mean = 2, sd = 1)
sample3 <- rnorm(250, mean = 0, sd = 10)
Check if two samples have the same variance.
var.test(sample1, sample2)
F test to compare two variances
data: sample1 and sample2
F = 0.96949, num df = 199, denom df = 299, p-value = 0.8179
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
0.7543491 1.2542128
sample estimates:
ratio of variances
0.9694931
var.test(sample1, sample3)
F test to compare two variances
data: sample1 and sample3
F = 0.0096017, num df = 199, denom df = 249, p-value < 2.2e-16
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
0.007386628 0.012530430
sample estimates:
ratio of variances
0.009601719
At level \(\alpha = 0.05\), we accept sample1 and sample2 have the same variance, and reject the hypothesis that sample1 and sample3 have the same variance.
t.test(sample1, sample2, paired = FALSE, var.equal = TRUE)
Two Sample t-test
data: sample1 and sample2
t = -22.493, df = 498, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-2.160604 -1.813477
sample estimates:
mean of x mean of y
0.02008153 2.00712204
t.test(sample1, sample3, paired = FALSE, var.equal = FALSE)
Welch Two Sample t-test
data: sample1 and sample3
t = -1.2912, df = 254.97, p-value = 0.1978
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-2.0295776 0.4221389
sample estimates:
mean of x mean of y
0.02008153 0.82380085
At level \(\alpha = 0.05\), we can conclude that sample1 and sample2 have different means, while sample1 and sample3 have the same mean.
- So what if the Normality assumption is not valid. Well, when sample size is large enough, by the central limit theorem, the two sample t-test is still a decent way to achieve our goal. In another word, when the sample size is moderate or large, the two sample t-test is robust to non-Normality.
LS0tCnRpdGxlOiAiTWF0aCAxODkvMjg5IExhYiAzIgphdXRob3I6ICJBbGV4IEhhbmJvIExpIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIFVuaWZvcm0gYW5kIFBvaXNzb24gZGlzdHJpYnV0aW9uCkxldCdzIGdlbmVyYXRlIDIwMCBzYW1wbGVzIGZyb20gdW5pZm9ybSBkaXN0cmlidXRpb24gaW4gdGhlIGludGVydmFsICRbMCwxMF0kLgpgYGB7cn0Kc2V0LnNlZWQoMjAxNykKbiA8LSAxMDAwCnNhbXBsZSA8LSBydW5pZihuLCBtaW4gPSAwLCBtYXggPSAxMCkKaGlzdChzYW1wbGUsIGJyZWFrcyA9IDEwMCwgcHJvYmFiaWxpdHkgPSBUUlVFLCBjb2wgPSAzLCBtYWluID0gIlVuaWZvcm0gZGlzdHJpYnV0aW9uIHNhbXBsZXMiKQpsaW5lcyhkZW5zaXR5KHNhbXBsZSwgYWRqdXN0ID0gMiksIGNvbCA9IDIpCmBgYAoKSWYgd2UgZGl2aWRlIHRoZSBpbnRlcnZhbCAkWzAsMTBdJCBpbnRvICRrJCBzdWItaW50ZXJ2YWxzIGFuZCBjb3VudCBob3cgbWFueSBkYXRhIHBvaW50cyBhcmUgaW5zaWRlIGVhY2ggb2YgdGhlbSwgc2F5ICRuXzEsIFxjZG90cywgbl9rJC4gVGhlbiB0aGVzZSBjb3VudHMgd2lsbCBmb2xsb3cgUG9pc3NvbiBkaXN0cmlidXRpb24uIFRoYXQgaXMsCiQkIFxtYXRoYmJ7UH0gKG0gXHRleHR7IHBvaW50cyBpbiBhIHVuaXQgaW50ZXJ2YWx9KSA9IFxmcmFje1xsYW1iZGFebX17bSF9ZV57LVxsYW1iZGF9LCBtPTAsMSxcY2RvdHMkJAoKVGhlcmVmb3JlLCB3ZSBleHBlY3QgJFx7bl8xLCBcY2RvdHMsIG5fa1x9JCB0byBmb2xsb3cgYSBQb2lzc29uLiBMZXQncyB2ZXJpZnkgaXQgYnkgc2ltdWxhdGlvbi4gV2UgZGl2aWRlIHRoZSBpbnRlcnZhbCBpbnRvIDEwMCBzdWItaW50ZXJ2YWxzLCBpLmUuICRrID0gMTAwJC4KYGBge3J9CmsgPC0gMTAwCnRhYiA8LSB0YWJsZShjdXQoc2FtcGxlLCBicmVha3MgPSBzZXEoMCwgMTAsIGxlbmd0aC5vdXQgPSBrKzEpLCBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpKQpoZWFkKHRhYiwgMTApCmNvdW50cyA8LSBhcy52ZWN0b3IodGFiKQpoZWFkKGNvdW50cywgMTApCmBgYAoKU28gYnkgdGhlb3J5LCB0aGUgKipjb3VudHMqKiBzaG91bGQgZm9sbG93IGEgUG9pc3NvbiBwcm9jZXNzLiBMZXQncyBjb21wYXJlIGl0IHdpdGggYSBnZW5lcmF0ZWQgUG9pc3NvbiBzZXF1ZW5jZS4gV2Uga25vdyAkXGxhbWJkYSQgZXF1YWxzIHRvIHRoZSBleHBlY3RlZCBudW1iZXIgb2YgcG9pbnRzIGluIGFuIGludGVydmFsLCBzbyBoZXJlLCB3ZSBzZXQgJFxsYW1iZGEgPSBrXnstMX1cc3VtX3tpPTF9Xmsgbl9pJC4KYGBge3J9Cmhpc3QoY291bnRzLCBicmVha3MgPSAxNSwgY29sID0gcmdiKDEsMCwwLDAuNSksIHByb2JhYmlsaXR5ID0gVFJVRSwgeGxhYiA9ICJudW1iZXIgb2YgcG9pbnRzIGluc2lkZSBhbiBpbnRlcnZhbCIsIHlsaW0gPSBjKDAsMC4yKSkKbGluZXMoZGVuc2l0eShjb3VudHMsIGFkanVzdCA9IDIpLCBjb2wgPSByZ2IoMSwwLDAsMC41KSkKUG9pcyA8LSBycG9pcygxMDAwLCBsYW1iZGEgPSBtZWFuKGNvdW50cykpCmhpc3QoUG9pcywgYnJlYWtzID0gMTUsIGNvbCA9IHJnYigwLDAsMSwwLjUpLCBwcm9iYWJpbGl0eSA9IFRSVUUsIGFkZCA9IFRSVUUpCmxpbmVzKGRlbnNpdHkoUG9pcywgYWRqdXN0ID0gMiksIGNvbCA9IHJnYigwLDAsMSwwLjUpKQpsZWdlbmQoeCA9IDE0LCB5ID0gMC4xNSwgbGVnZW5kID0gYygic2FtcGxlIiwgIlBvaXNzb24iKSwgbHR5ID0gYygxLDEpLCBjb2wgPSBjKHJnYigxLDAsMCwwLjUpLCByZ2IoMCwwLDEsMC41KSkpCmBgYAoKV2UgY2FuIHNlZSBvdXIgKipjb3VudHMqKiB2YXJpYWJsZSBpcyBpbmRlZWQgdmVyeSBjbG9zZSB0byBQb2lzc29uIGRpc3RyaWJ1dGlvbi4KCgoKIyBQZWFyc29uJ3MgJFxjaGleMiQgVGVzdCAoZ29vZG5lc3Mgb2YgZml0KQoKQSB0ZXN0IG9mIGdvb2RuZXNzIG9mIGZpdCBlc3RhYmxpc2hlcyB3aGV0aGVyIGFuIG9ic2VydmVkICoqZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbioqIGRpZmZlcnMgZnJvbSBhICoqdGhlb3JldGljYWwgZGlzdHJpYnV0aW9uKiouCgojIyMgVGVzdCBwcm9jZWR1cmUKTGV0J3Mgbm93IHVzZSB0aGUgUGVhc29uJ3MgJFxjaGleMiQgdGVzdCB0byBjaGVjayB3aGV0aGVyIHRoZSAqKnNhbXBsZSoqIGRvZXMgZm9sbG93IFVuaWZvcm0gZGlzdHJpYnV0aW9uIChiZWNhdXNlIHdlIGtub3cgd2UgZ2VuZXJhdGVkIHRoZSBzYW1wbGUgZnJvbSBVbmlmb3JtLCBzbyBvZiBjb3Vyc2Ugd2Ugc2hvdWxkIGV4cGVjdCBhIGdvb2QgcmVzdWx0KS4KCiogU3RlcCAxLiAKQ2FsY3VsYXRlIHRoZSBjaGktc3F1YXJlZCB0ZXN0IHN0YXRpc3RpYywgJFxjaGleMiQsIHdoaWNoIHJlc2VtYmxlcyBhIG5vcm1hbGl6ZWQgc3VtIG9mIHNxdWFyZWQgZGV2aWF0aW9ucyBiZXR3ZWVuIG9ic2VydmVkIGFuZCB0aGVvcmV0aWNhbCBmcmVxdWVuY2llcywgJE9faSQgYW5kICRFX2kkLiBUaGUgZm9ybXVsYSBpcyAKJCQgXGNoaV4yID0gXHN1bV97aT0xfV5rIFxmcmFjeyhPX2kgLSBFX2kpXjJ9e0VfaX0gPSBuIFxzdW1fe2k9MX1eayBcZnJhY3soT19pL24gLSBwX2kpXjJ9e3BfaX0sICQkCndoZXJlICRrJCBpcyB0aGUgbnVtYmVyIG9mIGNlbGxzIG9yIGludGVydmFscyBpbiB3aGljaCB5b3UgY2FsY3VsYXRlZCBmcmVxdWVuY2llcywgJG4kIGlzIHRoZSB0b3RhbCBudW1iZXIgb2Ygc2FtcGxlcywgYW5kICRwX2kgPSBFX2kvbiQgaXMgdGhlIGV4cGVjdGVkIHByb2JhYmlsaXR5IGluIHRoZSAkaSQtdGggaW50ZXJ2YWwuCgogICAgTGV0J3MgY2FsY3VsYXRlIHRoZSBvYnNlcnZlZCBhbmQgdGhlb3JldGljYWwgZnJlcXVlbmNpZXMgZm9yIG91ciBzYW1wbGUgYW5kIFVuaWZvcm0gZGlzdHJpYnV0aW9uLiAKICAgIFdlIGFscmVhZHkgaGF2ZSBvdXIgJE9faSQncywgZm9yIFVuaWZvcm0gZGlzdHJpYnV0aW9uLCB3ZSBrbm93ICRFX2kgPSBuL2sgPSAxMDAwLzEwMCQgaW4gdGhpcyBjYXNlLiBXZSBoYXZlICRcY2hpXjIgPSA4Mi4yJC4KICAgIAoKYGBge3J9CkVfaSA8LSBuL2sKY2hpXzIgPC0gc3VtKChjb3VudHMgLSBFX2kpXjIvRV9pKQpjaGlfMgpgYGAKCiogU3RlcCAyLgpEZXRlcm1pbmUgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSwgKmRmKiwgb2YgdGhhdCBzdGF0aXN0aWMuIEluIHRoZSB0ZXN0IG9mIGdvb2RuZXNzIG9mIGZpdCwgdGhlIGRlZ3JlZSBvZiBmcmVlZG9tIGVxdWFscyB0byAkayAtIHAkLCB3aGVyZSAkayQgaXMgdGhlIG51bWJlciBvZiBjZWxscyBvciBpbnRlcnZhbHMsIGFuZCAkcCA9IHMrMSQgaXMgdGhlIGNvbnRyYWludCBpbiB0aGF0IGRpc3RyaWJ1dGlvbiwgaGVyZSwgJHMkIGlzIHRoZSBudW1iZXIgb2YgcGFyYW1ldGVycyBmb3IgdGhlIGRpc3RyaWJ1dGlvbiB3ZSB3YW50IHRvIHRlc3QgYWdhaW5zdC4gRm9yIGV4YW1wbGUsIGEgTm9ybWFsIGRpc3RyaWJ1dGlvbiAkXG1hdGhjYWx7Tn0oXG11LCBcc2lnbWFeMikkIGhhcyB0d28gcGFyYW1ldGVycywgJFxtdSQgYW5kICRcc2lnbWEkLCB0aHVzICRzID0gMiQuIEluIG91ciBkaXNjcmV0ZSBVbmlmb3JtIGNhc2UsIHdlIGhhdmUgJHAgPSAxJC4gU28gKmRmKiB3aWxsIGJlICQxMDAtMT05OSQuCgoqIFN0ZXAgMy4KU2VsZWN0IGEgZGVzaXJlZCBsZXZlbCBvZiBjb25maWRlbmNlLiBXZSB3aWxsIHNlbGVjdCAkXGFscGhhID0gMC4wNSQuCgoqIFN0ZXAgNC4KICAgICsgQ29tcGFyZSB0aGUgdGVzdCBzdGF0aXN0aWMgJFxjaGleMiQgdG8gdGhlIHZhbHVlIGZyb20gdGhlIGNoaS1zcXVhcmVkIGRpc3RyaWJ1dGlvbiB3aXRoICpkZiogZGVncmVlcyBvZiBmcmVlZG9tIGFuZCB0aGUgc2VsZWN0ZWQgY29uZmlkZW5jZSBsZXZlbCwgJDEgLSBcYWxwaGEkLgogICAgKyBPciB3ZSBjYW4gY2FsY3VsYXRlIHRoZSAkcCQtdmFsdWUsICRcbWF0aGJie1B9KFggPiBcY2hpXjIpJCwgd2hlcmUgJFgkIGlzIGEgY2hpLXNxdWFyZSByYW5kb20gdmFyaWFibGUgd2l0aCAqZGYqIGRlZ3JlZSBvZiBmcmVlZG9tcy4KICAgICsgTm90ZSB0aGF0IHRoZSB0ZXN0IGlzIG9uZS1zaWRlZC4KYGBge3J9CmNoaTJfY29tcGFyZSA8LSBxY2hpc3EocCA9IDAuOTUsIGRmID0gOTkpCmNoaTJfY29tcGFyZQpwX3ZhbHVlIDwtIDEgLSBwY2hpc3EoY2hpXzIsIGRmID0gOTkpCnBfdmFsdWUKYGBgCgojIyMgQnVpbHQtaW4gUiBmdW5jdGlvbgpXZSBjYW4gYWxzbyB1c2UgdGhlIGJ1aWx0LWluIGZ1bmN0aW9uIGBjaGlzcS50ZXN0KClgLgpgYGB7cn0KcF9pIDwtIHJlcChFX2kvbiwgaykKY2hpc3EudGVzdChjb3VudHMsIHAgPSBwX2kpCmBgYAoKIyMjIFN0YW5kYXJkaXplZCByZXNpZHVhbCBwbG90CldlIGNhbiBhbHNvIHBsb3QgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbHMsIHdoaWNoIGFyZSBkZWZpbmVkIHRvIGJlCiQkIFJfaSA9IFxmcmFje3xPX2kgLSBFX2l8fXtcc3FydHtFX2l9fSQkCmluIGVhY2ggaW50ZXJ2YWwuClNvIHJlY2FsbCB0aGUgZGVmaW5pdGlvbiBvZiAkXGNoaV4yJCBzdGF0aXN0aWMsIHdlIGFjdHVhbGx5IGhhdmUgCiQkXGNoaV4yID0gXHN1bV97aT0xfV5rIFJfaV4yLiQkCmBgYHtyfQpSZXNpZHVhbHMgPC0gKGNvdW50cyAtIEVfaSkgLyBzcXJ0KEVfaSkKcGxvdChSZXNpZHVhbHMsIHR5cGUgPSAnaCcsIHlsYWIgPSAic3RhbmRhcmRpemVkIHJlc2lkdWFscyIsIHhsYWIgPSAiaW50ZXJ2YWwgaW5kZXgiKQpgYGAKCiMgVHdvIFNhbXBsZSB0LXRlc3QKKiBUd28gc2FtcGxlIHQtdGVzdCBjYW4gYmUgdXNlZCB0byBkZXRlcm1pbmUgaWYgdGhlIG1lYW5zIG9mIHR3byBzZXRzIG9mIGRhdGEgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50LiBCdXQgb25lIG9mIHRoZSB1bmRlcmx5aW5nIGFzc3VtcHRpb25zIGlzIHRoYXQgYm90aCBncm91cCBvZiBkYXRhIGZvbGxvdyBOb3JtYWwgZGlzdHJpYnV0aW9uLiBTbyB3ZSBzaG91bGQgZmlyc3QgY2hlY2sgaWYgTm9ybWFsaXR5IGFzc3VtcHRpb24gaXMgc2F0aXNmaWVkIChRLVEgcGxvdCwgZWNkZiwgU2hhcGlyb+KAk1dpbGssIEtvbG1vZ29yb3bigJNTbWlybm92KSBiZWZvcmUgd2UgYXBwbHkgdGhpcyB0ZXN0LgoqIFdlIHNob3VsZCBmaXJzdCBjaGVjayBpZiB0d28gc2FtcGxlcyBoYXZlIHRoZSBzYW1lIHZhcmlhbmNlLiBUaGlzIGNhbiBiZSBkb25lIHVzaW5nIEZpc2hlcidzIEYtdGVzdCAoaXQgY291bnRzIGluIHRoZSBlZmZlY3Qgb2YgZGlmZmVyZW50IHNhbXBsZSBzaXplcykuCiogRGV0YWlscyBvZiB0d28gc2FtcGxlIHQtdGVzdCBhcmUgcG9zdHBvbmVkIHRvIE1BVEggMTgxIGlmIHlvdSBoYXZlIG5vdCB0b3VjaGVkIGl0IGJlZm9yZS4KYGBge3J9CnNldC5zZWVkKDIwMTcpCnNhbXBsZTEgPC0gcm5vcm0oMjAwLCBtZWFuID0gMCwgc2QgPSAxKQpzYW1wbGUyIDwtIHJub3JtKDMwMCwgbWVhbiA9IDIsIHNkID0gMSkKc2FtcGxlMyA8LSBybm9ybSgyNTAsIG1lYW4gPSAwLCBzZCA9IDEwKQpgYGAKCkNoZWNrIGlmIHR3byBzYW1wbGVzIGhhdmUgdGhlIHNhbWUgdmFyaWFuY2UuCmBgYHtyfQp2YXIudGVzdChzYW1wbGUxLCBzYW1wbGUyKQp2YXIudGVzdChzYW1wbGUxLCBzYW1wbGUzKQpgYGAKCkF0IGxldmVsICRcYWxwaGEgPSAwLjA1JCwgd2UgYWNjZXB0ICpzYW1wbGUxKiBhbmQgKnNhbXBsZTIqIGhhdmUgdGhlIHNhbWUgdmFyaWFuY2UsIGFuZCByZWplY3QgdGhlIGh5cG90aGVzaXMgdGhhdCAqc2FtcGxlMSogYW5kICpzYW1wbGUzKiBoYXZlIHRoZSBzYW1lIHZhcmlhbmNlLgoKYGBge3J9CnQudGVzdChzYW1wbGUxLCBzYW1wbGUyLCBwYWlyZWQgPSBGQUxTRSwgdmFyLmVxdWFsID0gVFJVRSkKdC50ZXN0KHNhbXBsZTEsIHNhbXBsZTMsIHBhaXJlZCA9IEZBTFNFLCB2YXIuZXF1YWwgPSBGQUxTRSkKYGBgCkF0IGxldmVsICRcYWxwaGEgPSAwLjA1JCwgd2UgY2FuIGNvbmNsdWRlIHRoYXQgKnNhbXBsZTEqIGFuZCAqc2FtcGxlMiogaGF2ZSBkaWZmZXJlbnQgbWVhbnMsIHdoaWxlICpzYW1wbGUxKiBhbmQgKnNhbXBsZTMqIGhhdmUgdGhlIHNhbWUgbWVhbi4KCiogU28gd2hhdCBpZiB0aGUgTm9ybWFsaXR5IGFzc3VtcHRpb24gaXMgbm90IHZhbGlkLiBXZWxsLCB3aGVuIHNhbXBsZSBzaXplIGlzIGxhcmdlIGVub3VnaCwgYnkgdGhlIGNlbnRyYWwgbGltaXQgdGhlb3JlbSwgdGhlIHR3byBzYW1wbGUgdC10ZXN0IGlzIHN0aWxsIGEgZGVjZW50IHdheSB0byBhY2hpZXZlIG91ciBnb2FsLiBJbiBhbm90aGVyIHdvcmQsIHdoZW4gdGhlIHNhbXBsZSBzaXplIGlzIG1vZGVyYXRlIG9yIGxhcmdlLCB0aGUgdHdvIHNhbXBsZSB0LXRlc3QgaXMgcm9idXN0IHRvIG5vbi1Ob3JtYWxpdHkuCgo=