Week2 HW

Libraries

library(tidyverse)
library(GGally)
library(ISLR)
library(boot)

R for Data Science Problems

7.3.4.2 Explore the distribution of price. Do you discover anything unusual or surprising? (Hint: Carefully think about the binwidth and make sure you try a wide range of values.)

ggplot(data = diamonds)+
  geom_histogram((aes(price)))

Right tailed.

ggplot(data = diamonds)+
  geom_histogram((aes(price)), binwidth = 100)

Why is there a huge gap? What is the cheapest value of diamonds and why are so few made? (326)

7.4.1.1 What happens to missing values in a histogram? What happens to missing values in a bar chart? Why is there a difference?

Bar counts missing values while histogram removes them.In histogram, x value needs to be numeric, this is not the case for Bar as it takes on catagorical values and just treats NA as another value.

7.4.1.2 What does na.rm = TRUE do in mean() and sum()? Calculate the mean and sum without the missing values.

7.5.1.5 Compare and contrast geom_violin() with a facetted geom_histogram(), or a coloured geom_freqpoly(). What are the pros and cons of each method?

ggplot(data = diamonds, mapping = aes(x = price)) + 
  geom_freqpoly(mapping = aes(colour = cut), binwidth = 500)

ggplot(data = diamonds, mapping = aes(x = price)) + 
  geom_histogram(mapping = aes(x = price), binwidth = 100)+
  facet_wrap(~ cut, nrow = 2)

ggplot(data = diamonds, mapping = aes(x = price)) + 
  geom_violin(mapping = aes(x = cut, y = price))

Geom Pros Cons
geom_violin() Easy to compare and no transformation needed Don’t really see any
facetted geom_histogram() Easier to see individual distributions Hard to compare different distributions
colored geom_freqpoly() Easy to compare if we change y to density Hard to see differences when just looking at count

ISLR Problems

4.7.5

We now examine the differences between LDA and QDA.

(a) If the Bayes decision boundary is linear, do we expect LDA or QDA to perform better on the training set? On the test set? LDA on test, QDA on training (b) If the Bayes decision boundary is non-linear, do we expect LDA or QDA to perform better on the training set? On the test set? QDA on both

(c) In general, as the sample size n increases, do we expect the test prediction accuracy of QDA relative to LDA to improve, decline, or be unchanged? Why?

Unchaged, it will depend on the underlying decision boundary.

4.7.6

6. Suppose we collect data for a group of students in a statistics class with variables X1 = hours studied, X2 = undergrad GPA, and Y = receive an A. We fit a logistic regression and produce estimated coefficient

(a) Estimate the probability that a student who studies for 40 h and has an undergrad GPA of 3.5 gets an A in the class.

exp(-6 +40*.05+3.5*1)/(1+exp(-6 +40*.05+3.5*1))
[1] 0.3775407

(b) How many hours would the student in part (a) need to study to have a 50 % chance of getting an A in the class?

exp(-6 +50*.05+3.5*1)/(1+exp(-6 +50*.05+3.5*1))
[1] 0.5

5.4.2 We will now derive the probability that a given observation is part of a bootstrap sample. Suppose that we obtain a bootstrap sample from a set of n observations.

(a) What is the probability that the first bootstrap observation is not the jth observation from the original sample? Justify your answer. 1 - 1/n, there is a 1/n chance of choosing a given observation. (b) What is the probability that the second bootstrap observation is not the jth observation from the original sample? 1 - 1/n (c) Argue that the probability that the jth observation is not in the bootstrap sample is (1 − 1/n)^n. there is a 1-1/n probability of a given sample not being a specific bootstap sample, since there are n bootstrap observations, we can easily find the probability of a given observation not being in the bootstrap sample.

(d) When n = 5, what is the probability that the jth observation is in the bootstrap sample? (1-1/5)^5 is the probability it isn’t in the bootstrap sample, so

1-(1-1/5)^5
[1] 0.67232

(e) When n = 100, what is the probability that the jth observation is in the bootstrap sample?

1-(1-1/100)^100
[1] 0.6339677

5.4.5 5. In Chapter 4, we used logistic regression to predict the probability of default using income and balance on the Default data set. We will now estimate the test error of this logistic regression model using the validation set approach. Do not forget to set a random seed before beginning your analysis.

(a) Fit a logistic regression model that uses income and balance to predict default.

logit = glm(default~income+balance, data = Default, family = binomial)
logit

Call:  glm(formula = default ~ income + balance, family = binomial, 
    data = Default)

Coefficients:
(Intercept)       income      balance  
 -1.154e+01    2.081e-05    5.647e-03  

Degrees of Freedom: 9999 Total (i.e. Null);  9997 Residual
Null Deviance:      2921 
Residual Deviance: 1579     AIC: 1585

(b) Using the validation set approach, estimate the test error of this model. In order to do this, you must perform the following steps: i. Split the sample set into a training set and a validation set.

(c) Repeat the process in (b) three times, using three different splits of the observations into a training set and a validation set. Comment on the results obtained.

(d) Now consider a logistic regression model that predicts the probability of default using income, balance, and a dummy variable for student. Estimate the test error for this model using the validation set approach. Comment on whether or not including a dummy variable for student leads to a reduction in the test error rate.

5.4.6 We continue to consider the use of a logistic regression model to predict the probability of default using income and balance on the Default data set. In particular, we will now compute estimates for the standard errors of the income and balance logistic regression coefficients in two different ways: (1) using the bootstrap, and (2) using the standard formula for computing the standard errors in the glm() function. Do not forget to set a random seed before beginning your analysis.

Default

(a) Using the summary() and glm() functions, determine the estimated standard errors for the coefficients associated with income and balance in a multiple logistic regression model that uses both predictors.

model1 = glm(default~income + balance,data = Default, family = "binomial")
summary(model1)$coefficients[,2]
 (Intercept)       income      balance 
4.347564e-01 4.985167e-06 2.273731e-04 

(b) Write a function, boot.fn(), that takes as input the Default data set as well as an index of the observations, and that outputs the coefficient estimates for income and balance in the multiple logistic regression model.

boot.fn = function(data, index){
  model = glm(default~income + balance,data = data[index,], family = "binomial",subset=index)
  return(summary(model)$coefficients[-1,2])
}

boot.fn(Default, 1:10000)
      income      balance 
4.985167e-06 2.273731e-04 

(c) Use the boot() function together with your boot.fn() function to estimate the standard errors of the logistic regression coefficients for income and balance.

set.seed(1)
boot(data = Default, statistic = boot.fn, R = 100) #I'm I reading this correctly?

ORDINARY NONPARAMETRIC BOOTSTRAP


Call:
boot(data = Default, statistic = boot.fn, R = 100)


Bootstrap Statistics :
        original       bias     std. error
t1* 4.985167e-06 3.745402e-08 1.972904e-07
t2* 2.273731e-04 1.662875e-06 1.602112e-05

(d) Comment on the estimated standard errors obtained using the glm() function and using your bootstrap function. Extremely similar. Income is the same up to eight decimal places and balance is the same up to 6 decimal places

LS0tDQp0aXRsZTogIldlZWsyIEhXIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCioqTGlicmFyaWVzKioNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KEdHYWxseSkNCmxpYnJhcnkoSVNMUikNCmxpYnJhcnkoYm9vdCkNCmBgYA0KIyBSIGZvciBEYXRhIFNjaWVuY2UgUHJvYmxlbXMNCg0KKio3LjMuNC4yIEV4cGxvcmUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBwcmljZS4gRG8geW91IGRpc2NvdmVyIGFueXRoaW5nIHVudXN1YWwgb3Igc3VycHJpc2luZz8gKEhpbnQ6IENhcmVmdWxseSB0aGluayBhYm91dCB0aGUgYmlud2lkdGggYW5kIG1ha2Ugc3VyZSB5b3UgdHJ5IGEgd2lkZSByYW5nZSBvZiB2YWx1ZXMuKSoqDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBkaWFtb25kcykrDQogIGdlb21faGlzdG9ncmFtKChhZXMocHJpY2UpKSkNCmBgYA0KDQpSaWdodCB0YWlsZWQuDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBkaWFtb25kcykrDQogIGdlb21faGlzdG9ncmFtKChhZXMocHJpY2UpKSwgYmlud2lkdGggPSAxMDApDQpgYGANCldoeSBpcyB0aGVyZSBhIGh1Z2UgZ2FwPyBXaGF0IGlzIHRoZSBjaGVhcGVzdCB2YWx1ZSBvZiBkaWFtb25kcyBhbmQgd2h5IGFyZSBzbyBmZXcgbWFkZT8gKDMyNikNCg0KKio3LjQuMS4xIFdoYXQgaGFwcGVucyB0byBtaXNzaW5nIHZhbHVlcyBpbiBhIGhpc3RvZ3JhbT8gV2hhdCBoYXBwZW5zIHRvIG1pc3NpbmcgdmFsdWVzIGluIGEgYmFyIGNoYXJ0PyBXaHkgaXMgdGhlcmUgYSBkaWZmZXJlbmNlPyoqDQoNCkJhciBjb3VudHMgbWlzc2luZyB2YWx1ZXMgd2hpbGUgaGlzdG9ncmFtIHJlbW92ZXMgdGhlbS5JbiBoaXN0b2dyYW0sIHggdmFsdWUgbmVlZHMgdG8gYmUgbnVtZXJpYywgdGhpcyBpcyBub3QgdGhlIGNhc2UgZm9yIEJhciBhcyBpdCB0YWtlcyBvbiBjYXRhZ29yaWNhbCB2YWx1ZXMgYW5kIGp1c3QgdHJlYXRzIE5BIGFzIGFub3RoZXIgdmFsdWUuDQoNCioqNy40LjEuMiBXaGF0IGRvZXMgbmEucm0gPSBUUlVFIGRvIGluIG1lYW4oKSBhbmQgc3VtKCk/KioNCkNhbGN1bGF0ZSB0aGUgbWVhbiBhbmQgc3VtIHdpdGhvdXQgdGhlIG1pc3NpbmcgdmFsdWVzLg0KDQoqKjcuNS4xLjUgQ29tcGFyZSBhbmQgY29udHJhc3QgZ2VvbV92aW9saW4oKSB3aXRoIGEgZmFjZXR0ZWQgZ2VvbV9oaXN0b2dyYW0oKSwgb3IgYSBjb2xvdXJlZCBnZW9tX2ZyZXFwb2x5KCkuIFdoYXQgYXJlIHRoZSBwcm9zIGFuZCBjb25zIG9mIGVhY2ggbWV0aG9kPyoqDQoNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzLCBtYXBwaW5nID0gYWVzKHggPSBwcmljZSkpICsgDQogIGdlb21fZnJlcXBvbHkobWFwcGluZyA9IGFlcyhjb2xvdXIgPSBjdXQpLCBiaW53aWR0aCA9IDUwMCkNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzLCBtYXBwaW5nID0gYWVzKHggPSBwcmljZSkpICsgDQogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IHByaWNlKSwgYmlud2lkdGggPSAxMDApKw0KICBmYWNldF93cmFwKH4gY3V0LCBucm93ID0gMikNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzLCBtYXBwaW5nID0gYWVzKHggPSBwcmljZSkpICsgDQogIGdlb21fdmlvbGluKG1hcHBpbmcgPSBhZXMoeCA9IGN1dCwgeSA9IHByaWNlKSkNCmBgYA0KDQp8IEdlb20gICAgICAgICAgICAgICAgICAgICAgfCBQcm9zICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBDb25zICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18DQp8IGdlb21fdmlvbGluKCkgICAgICAgICAgICAgfCBFYXN5IHRvIGNvbXBhcmUgYW5kIG5vIHRyYW5zZm9ybWF0aW9uIG5lZWRlZCAgfCBEb24ndCByZWFsbHkgc2VlIGFueSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8IGZhY2V0dGVkIGdlb21faGlzdG9ncmFtKCkgfCBFYXNpZXIgdG8gc2VlIGluZGl2aWR1YWwgZGlzdHJpYnV0aW9ucyAgICAgICAgfCBIYXJkIHRvIGNvbXBhcmUgZGlmZmVyZW50IGRpc3RyaWJ1dGlvbnMgICAgICAgICAgICB8DQp8IGNvbG9yZWQgZ2VvbV9mcmVxcG9seSgpICAgfCBFYXN5IHRvIGNvbXBhcmUgaWYgd2UgY2hhbmdlIHkgdG8gZGVuc2l0eSAgICAgfCBIYXJkIHRvIHNlZSBkaWZmZXJlbmNlcyB3aGVuIGp1c3QgbG9va2luZyBhdCBjb3VudCB8ICAgICAgICAgICAgICAgICAgICAgICANCg0KIyBJU0xSIFByb2JsZW1zDQoNCioqNC43LjUgKioNCg0KKipXZSBub3cgZXhhbWluZSB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBMREEgYW5kIFFEQS4qKg0KDQoqKihhKSBJZiB0aGUgQmF5ZXMgZGVjaXNpb24gYm91bmRhcnkgaXMgbGluZWFyLCBkbyB3ZSBleHBlY3QgTERBIG9yIFFEQSB0byBwZXJmb3JtIGJldHRlciBvbiB0aGUgdHJhaW5pbmcgc2V0PyBPbiB0aGUgdGVzdCBzZXQ/KioNCiBMREEgb24gdGVzdCwgUURBIG9uIHRyYWluaW5nDQoqKihiKSBJZiB0aGUgQmF5ZXMgZGVjaXNpb24gYm91bmRhcnkgaXMgbm9uLWxpbmVhciwgZG8gd2UgZXhwZWN0IExEQSBvciBRREEgdG8gcGVyZm9ybSBiZXR0ZXIgb24gdGhlIHRyYWluaW5nIHNldD8gT24gdGhlIHRlc3Qgc2V0PyoqDQogIFFEQSBvbiBib3RoDQoNCioqKGMpIEluIGdlbmVyYWwsIGFzIHRoZSBzYW1wbGUgc2l6ZSBuIGluY3JlYXNlcywgZG8gd2UgZXhwZWN0IHRoZSB0ZXN0IHByZWRpY3Rpb24gYWNjdXJhY3kgb2YgUURBIHJlbGF0aXZlIHRvIExEQSB0byBpbXByb3ZlLCBkZWNsaW5lLCBvciBiZSB1bmNoYW5nZWQ/IFdoeT8qKiANCg0KVW5jaGFnZWQsIGl0IHdpbGwgZGVwZW5kIG9uIHRoZSB1bmRlcmx5aW5nIGRlY2lzaW9uIGJvdW5kYXJ5Lg0KDQoqKjQuNy42KioNCg0KKio2LiBTdXBwb3NlIHdlIGNvbGxlY3QgZGF0YSBmb3IgYSBncm91cCBvZiBzdHVkZW50cyBpbiBhIHN0YXRpc3RpY3MgY2xhc3Mgd2l0aCB2YXJpYWJsZXMgWDEgPSBob3VycyBzdHVkaWVkLCBYMiA9IHVuZGVyZ3JhZCBHUEEsIGFuZCBZID0gcmVjZWl2ZSBhbiBBLiBXZSBmaXQgYSBsb2dpc3RpYyByZWdyZXNzaW9uIGFuZCBwcm9kdWNlIGVzdGltYXRlZCBjb2VmZmljaWVudCoqDQoNCioqKGEpIEVzdGltYXRlIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGEgc3R1ZGVudCB3aG8gc3R1ZGllcyBmb3IgNDAgaCBhbmQgaGFzIGFuIHVuZGVyZ3JhZCBHUEEgb2YgMy41IGdldHMgYW4gQSBpbiB0aGUgY2xhc3MuKioNCmBgYHtyfQ0KZXhwKC02ICs0MCouMDUrMy41KjEpLygxK2V4cCgtNiArNDAqLjA1KzMuNSoxKSkNCmBgYA0KDQoqKihiKSBIb3cgbWFueSBob3VycyB3b3VsZCB0aGUgc3R1ZGVudCBpbiBwYXJ0IChhKSBuZWVkIHRvIHN0dWR5IHRvIGhhdmUgYSA1MCAlIGNoYW5jZSBvZiBnZXR0aW5nIGFuIEEgaW4gdGhlIGNsYXNzPyoqDQpgYGB7cn0NCmV4cCgtNiArNTAqLjA1KzMuNSoxKS8oMStleHAoLTYgKzUwKi4wNSszLjUqMSkpDQpgYGANCg0KDQoqKjUuNC4yIFdlIHdpbGwgbm93IGRlcml2ZSB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhIGdpdmVuIG9ic2VydmF0aW9uIGlzIHBhcnQgb2YgYSBib290c3RyYXAgc2FtcGxlLiBTdXBwb3NlIHRoYXQgd2Ugb2J0YWluIGEgYm9vdHN0cmFwIHNhbXBsZSBmcm9tIGEgc2V0IG9mIG4gb2JzZXJ2YXRpb25zLiAqKg0KDQoqKihhKSBXaGF0IGlzIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBmaXJzdCBib290c3RyYXAgb2JzZXJ2YXRpb24gaXMgbm90IHRoZSBqdGggb2JzZXJ2YXRpb24gZnJvbSB0aGUgb3JpZ2luYWwgc2FtcGxlPyBKdXN0aWZ5IHlvdXIgYW5zd2VyLioqDQoxIC0gMS9uLCB0aGVyZSBpcyBhIDEvbiBjaGFuY2Ugb2YgY2hvb3NpbmcgYSBnaXZlbiBvYnNlcnZhdGlvbi4NCioqKGIpIFdoYXQgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIHNlY29uZCBib290c3RyYXAgb2JzZXJ2YXRpb24gaXMgbm90IHRoZSBqdGggb2JzZXJ2YXRpb24gZnJvbSB0aGUgb3JpZ2luYWwgc2FtcGxlPyoqDQoxIC0gMS9uDQoqKihjKSBBcmd1ZSB0aGF0IHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBqdGggb2JzZXJ2YXRpb24gaXMgbm90IGluIHRoZSBib290c3RyYXAgc2FtcGxlIGlzICgxIOKIkiAxL24pXm4uKioNCnRoZXJlIGlzIGEgMS0xL24gcHJvYmFiaWxpdHkgb2YgYSBnaXZlbiBzYW1wbGUgbm90IGJlaW5nIGEgc3BlY2lmaWMgYm9vdHN0YXAgc2FtcGxlLCBzaW5jZSB0aGVyZSBhcmUgbiBib290c3RyYXAgb2JzZXJ2YXRpb25zLCB3ZSBjYW4gZWFzaWx5IGZpbmQgdGhlIHByb2JhYmlsaXR5IG9mIGEgZ2l2ZW4gb2JzZXJ2YXRpb24gbm90IGJlaW5nIGluIHRoZSBib290c3RyYXAgc2FtcGxlLg0KDQoqKihkKSBXaGVuIG4gPSA1LCB3aGF0IGlzIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBqdGggb2JzZXJ2YXRpb24gaXMgaW4gdGhlIGJvb3RzdHJhcCBzYW1wbGU/KioNCigxLTEvNSleNSBpcyB0aGUgcHJvYmFiaWxpdHkgaXQgaXNuJ3QgaW4gdGhlIGJvb3RzdHJhcCBzYW1wbGUsIHNvDQoNCmBgYHtyfQ0KMS0oMS0xLzUpXjUNCmBgYA0KDQoqKihlKSBXaGVuIG4gPSAxMDAsIHdoYXQgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIGp0aCBvYnNlcnZhdGlvbiBpcyBpbiB0aGUgYm9vdHN0cmFwIHNhbXBsZT8qKg0KYGBge3J9DQoxLSgxLTEvMTAwKV4xMDANCmBgYA0KDQoNCioqNS40LjUgNS4gSW4gQ2hhcHRlciA0LCB3ZSB1c2VkIGxvZ2lzdGljIHJlZ3Jlc3Npb24gdG8gcHJlZGljdCB0aGUgcHJvYmFiaWxpdHkgb2YgZGVmYXVsdCB1c2luZyBpbmNvbWUgYW5kIGJhbGFuY2Ugb24gdGhlIERlZmF1bHQgZGF0YSBzZXQuIFdlIHdpbGwgbm93IGVzdGltYXRlIHRoZSB0ZXN0IGVycm9yIG9mIHRoaXMgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCB1c2luZyB0aGUgdmFsaWRhdGlvbiBzZXQgYXBwcm9hY2guIERvIG5vdCBmb3JnZXQgdG8gc2V0IGEgcmFuZG9tIHNlZWQgYmVmb3JlIGJlZ2lubmluZyB5b3VyIGFuYWx5c2lzLioqDQoNCioqKGEpIEZpdCBhIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgdGhhdCB1c2VzIGluY29tZSBhbmQgYmFsYW5jZSB0byBwcmVkaWN0IGRlZmF1bHQuKioNCg0KYGBge3J9DQpsb2dpdCA9IGdsbShkZWZhdWx0fmluY29tZStiYWxhbmNlLCBkYXRhID0gRGVmYXVsdCwgZmFtaWx5ID0gYmlub21pYWwpDQpsb2dpdA0KYGBgDQoNCg0KKiooYikgVXNpbmcgdGhlIHZhbGlkYXRpb24gc2V0IGFwcHJvYWNoLCBlc3RpbWF0ZSB0aGUgdGVzdCBlcnJvciBvZiB0aGlzIG1vZGVsLiBJbiBvcmRlciB0byBkbyB0aGlzLCB5b3UgbXVzdCBwZXJmb3JtIHRoZSBmb2xsb3dpbmcgc3RlcHM6IGkuIFNwbGl0IHRoZSBzYW1wbGUgc2V0IGludG8gYSB0cmFpbmluZyBzZXQgYW5kIGEgdmFsaWRhdGlvbiBzZXQuKioNCg0KKiooYykgUmVwZWF0IHRoZSBwcm9jZXNzIGluIChiKSB0aHJlZSB0aW1lcywgdXNpbmcgdGhyZWUgZGlmZmVyZW50IHNwbGl0cyBvZiB0aGUgb2JzZXJ2YXRpb25zIGludG8gYSB0cmFpbmluZyBzZXQgYW5kIGEgdmFsaWRhdGlvbiBzZXQuIENvbW1lbnQgb24gdGhlIHJlc3VsdHMgb2J0YWluZWQuKioNCg0KKiooZCkgTm93IGNvbnNpZGVyIGEgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCB0aGF0IHByZWRpY3RzIHRoZSBwcm9iYWJpbGl0eSBvZiBkZWZhdWx0IHVzaW5nIGluY29tZSwgYmFsYW5jZSwgYW5kIGEgZHVtbXkgdmFyaWFibGUgZm9yIHN0dWRlbnQuIEVzdGltYXRlIHRoZSB0ZXN0IGVycm9yIGZvciB0aGlzIG1vZGVsIHVzaW5nIHRoZSB2YWxpZGF0aW9uIHNldCBhcHByb2FjaC4gQ29tbWVudCBvbiB3aGV0aGVyIG9yIG5vdCBpbmNsdWRpbmcgYSBkdW1teSB2YXJpYWJsZSBmb3Igc3R1ZGVudCBsZWFkcyB0byBhIHJlZHVjdGlvbiBpbiB0aGUgdGVzdCBlcnJvciByYXRlLioqDQoNCioqNS40LjYgV2UgY29udGludWUgdG8gY29uc2lkZXIgdGhlIHVzZSBvZiBhIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgdG8gcHJlZGljdCB0aGUgcHJvYmFiaWxpdHkgb2YgZGVmYXVsdCB1c2luZyBpbmNvbWUgYW5kIGJhbGFuY2Ugb24gdGhlIERlZmF1bHQgZGF0YSBzZXQuIEluIHBhcnRpY3VsYXIsIHdlIHdpbGwgbm93IGNvbXB1dGUgZXN0aW1hdGVzIGZvciB0aGUgc3RhbmRhcmQgZXJyb3JzIG9mIHRoZSBpbmNvbWUgYW5kIGJhbGFuY2UgbG9naXN0aWMgcmVncmVzc2lvbiBjb2VmZmljaWVudHMgaW4gdHdvIGRpZmZlcmVudCB3YXlzOiAoMSkgdXNpbmcgdGhlIGJvb3RzdHJhcCwgYW5kICgyKSB1c2luZyB0aGUgc3RhbmRhcmQgZm9ybXVsYSBmb3IgY29tcHV0aW5nIHRoZSBzdGFuZGFyZCBlcnJvcnMgaW4gdGhlIGdsbSgpIGZ1bmN0aW9uLiBEbyBub3QgZm9yZ2V0IHRvIHNldCBhIHJhbmRvbSBzZWVkIGJlZm9yZSBiZWdpbm5pbmcgeW91ciBhbmFseXNpcy4qKg0KDQpgYGB7cn0NCkRlZmF1bHQNCmBgYA0KDQoNCioqKGEpIFVzaW5nIHRoZSBzdW1tYXJ5KCkgYW5kIGdsbSgpIGZ1bmN0aW9ucywgZGV0ZXJtaW5lIHRoZSBlc3RpbWF0ZWQgc3RhbmRhcmQgZXJyb3JzIGZvciB0aGUgY29lZmZpY2llbnRzIGFzc29jaWF0ZWQgd2l0aCBpbmNvbWUgYW5kIGJhbGFuY2UgaW4gYSBtdWx0aXBsZSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsIHRoYXQgdXNlcyBib3RoIHByZWRpY3RvcnMuKioNCg0KYGBge3J9DQptb2RlbDEgPSBnbG0oZGVmYXVsdH5pbmNvbWUgKyBiYWxhbmNlLGRhdGEgPSBEZWZhdWx0LCBmYW1pbHkgPSAiYmlub21pYWwiKQ0Kc3VtbWFyeShtb2RlbDEpJGNvZWZmaWNpZW50c1ssMl0NCmBgYA0KDQoNCioqKGIpIFdyaXRlIGEgZnVuY3Rpb24sIGJvb3QuZm4oKSwgdGhhdCB0YWtlcyBhcyBpbnB1dCB0aGUgRGVmYXVsdCBkYXRhIHNldCBhcyB3ZWxsIGFzIGFuIGluZGV4IG9mIHRoZSBvYnNlcnZhdGlvbnMsIGFuZCB0aGF0IG91dHB1dHMgdGhlIGNvZWZmaWNpZW50IGVzdGltYXRlcyBmb3IgaW5jb21lIGFuZCBiYWxhbmNlIGluIHRoZSBtdWx0aXBsZSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsLioqDQoNCmBgYHtyfQ0KYm9vdC5mbiA9IGZ1bmN0aW9uKGRhdGEsIGluZGV4KXsNCiAgbW9kZWwgPSBnbG0oZGVmYXVsdH5pbmNvbWUgKyBiYWxhbmNlLGRhdGEgPSBkYXRhW2luZGV4LF0sIGZhbWlseSA9ICJiaW5vbWlhbCIsc3Vic2V0PWluZGV4KQ0KICByZXR1cm4oc3VtbWFyeShtb2RlbCkkY29lZmZpY2llbnRzWy0xLDJdKQ0KfQ0KDQpib290LmZuKERlZmF1bHQsIDE6MTAwMDApDQpgYGANCg0KKiooYykgVXNlIHRoZSBib290KCkgZnVuY3Rpb24gdG9nZXRoZXIgd2l0aCB5b3VyIGJvb3QuZm4oKSBmdW5jdGlvbiB0byBlc3RpbWF0ZSB0aGUgc3RhbmRhcmQgZXJyb3JzIG9mIHRoZSBsb2dpc3RpYyByZWdyZXNzaW9uIGNvZWZmaWNpZW50cyBmb3IgaW5jb21lIGFuZCBiYWxhbmNlLioqDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMSkNCmJvb3QoZGF0YSA9IERlZmF1bHQsIHN0YXRpc3RpYyA9IGJvb3QuZm4sIFIgPSAxMDApICNJJ20gSSByZWFkaW5nIHRoaXMgY29ycmVjdGx5Pw0KYGBgDQoNCg0KKiooZCkgQ29tbWVudCBvbiB0aGUgZXN0aW1hdGVkIHN0YW5kYXJkIGVycm9ycyBvYnRhaW5lZCB1c2luZyB0aGUgZ2xtKCkgZnVuY3Rpb24gYW5kIHVzaW5nIHlvdXIgYm9vdHN0cmFwIGZ1bmN0aW9uLioqDQpFeHRyZW1lbHkgc2ltaWxhci4gSW5jb21lIGlzIHRoZSBzYW1lIHVwIHRvIGVpZ2h0IGRlY2ltYWwgcGxhY2VzIGFuZCBiYWxhbmNlIGlzIHRoZSBzYW1lIHVwIHRvIDYgZGVjaW1hbCBwbGFjZXM=