getwd() launch <- read.csv(“challenger.csv”)

estimate beta manually

b <- cov(launch\(temperature, launch\)distress_ct) / var(launch$temperature) b

estimate alpha manually

a <- mean(launch\(distress_ct) - b * mean(launch\)temperature) a

r <- cov(launch\(temperature, launch\)distress_ct) / (sd(launch\(temperature) * sd(launch\)distress_ct)) r

cor(launch\(temperature, launch\)distress_ct)

computing the slope using correlation

r * (sd(launch\(distress_ct) / sd(launch\)temperature))

confirming the regression line using the lm function (not in text)

model <- lm(distress_ct ~ temperature, data = launch) model

Call:

lm(formula = distress_ct ~ temperature, data = launch)

Coefficients:

(Intercept) temperature

2.81458 -0.03365

summary(model)

creating a simple multiple regression function

reg <- function(y, x) { x <- as.matrix(x) x <- cbind(Intercept = 1, x) b <- solve(t(x) %% x) %% t(x) %*% y colnames(b) <- “estimate” print(b) }

examine the launch data

str(launch)

test regression model with simple linear regression

reg(y = launch$distress_ct, x = launch[2])

use regression model with multiple regression

reg(y = launch$distress_ct, x = launch[2:4])

confirming the multiple regression result using the lm function (not in text)

model <- lm(distress_ct ~ temperature + field_check_pressure + flight_num, data = launch) model

Call:

lm(formula = distress_ct ~ temperature + field_check_pressure +

flight_num, data = launch)

Coefficients:

(Intercept) temperature field_check_pressure

2.240e+00 -3.124e-02 -2.587e-05

flight_num

2.762e-02

summary(model)

Step 2: Exploring and preparing the data —-

insurance <- read.csv(“insurance.csv”, stringsAsFactors = TRUE) str(insurance)

summarize the charges variable

summary(insurance$expenses)

histogram of insurance charges

hist(insurance$expenses)

table of region

table(insurance$region)

exploring relationships among features: correlation matrix

cor(insurance[c(“age”, “bmi”, “children”, “expenses”)])

visualing relationships among features: scatterplot matrix

pairs(insurance[c(“age”, “bmi”, “children”, “expenses”)])

Step 3: Training a model on the data —-

ins_model <- lm(expenses ~ age + children + bmi + sex + smoker + region, data = insurance) ins_model <- lm(expenses ~ ., data = insurance) # this is equivalent to above

see the estimated beta coefficients

ins_model

see more detail about the estimated beta coefficients

summary(ins_model)

Call:

lm(formula = expenses ~ ., data = insurance)

Residuals:

Min 1Q Median 3Q Max

-11302.7 -2850.9 -979.6 1383.9 29981.7

Coefficients:

Estimate Std. Error t value Pr(>|t|)

(Intercept) -11941.6 987.8 -12.089 < 2e-16 ***

age 256.8 11.9 21.586 < 2e-16 ***

sexmale -131.3 332.9 -0.395 0.693255

bmi 339.3 28.6 11.864 < 2e-16 ***

children 475.7 137.8 3.452 0.000574 ***

smokeryes 23847.5 413.1 57.723 < 2e-16 ***

regionnorthwest -352.8 476.3 -0.741 0.458976

regionsoutheast -1035.6 478.7 -2.163 0.030685 *

regionsouthwest -959.3 477.9 -2.007 0.044921 *

Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1

Residual standard error: 6062 on 1329 degrees of freedom

Multiple R-squared: 0.7509, Adjusted R-squared: 0.7494

F-statistic: 500.9 on 8 and 1329 DF, p-value: < 2.2e-16

add a higher-order “age” term

insurance\(age2 <- insurance\)age^2

add an indicator for BMI >= 30

insurance\(bmi30 <- ifelse(insurance\)bmi >= 30, 1, 0)

create final model

ins_model2 <- lm(expenses ~ age + age2 + children + bmi + sex + bmi30*smoker + region, data = insurance)

summary(ins_model2)

Call:

lm(formula = expenses ~ age + age2 + children + bmi + sex + bmi30 *

smoker + region, data = insurance)

Residuals:

Min 1Q Median 3Q Max

-17297.1 -1656.0 -1262.7 -727.8 24161.6

Coefficients:

Estimate Std. Error t value Pr(>|t|)

(Intercept) 139.0053 1363.1359 0.102 0.918792

age -32.6181 59.8250 -0.545 0.585690

age2 3.7307 0.7463 4.999 6.54e-07 ***

children 678.6017 105.8855 6.409 2.03e-10 ***

bmi 119.7715 34.2796 3.494 0.000492 ***

sexmale -496.7690 244.3713 -2.033 0.042267 *

bmi30 -997.9355 422.9607 -2.359 0.018449 *

smokeryes 13404.5952 439.9591 30.468 < 2e-16 ***

regionnorthwest -279.1661 349.2826 -0.799 0.424285

regionsoutheast -828.0345 351.6484 -2.355 0.018682 *

regionsouthwest -1222.1619 350.5314 -3.487 0.000505 ***

bmi30:smokeryes 19810.1534 604.6769 32.762 < 2e-16 ***

Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1

Residual standard error: 4445 on 1326 degrees of freedom

Multiple R-squared: 0.8664, Adjusted R-squared: 0.8653

F-statistic: 781.7 on 11 and 1326 DF, p-value: < 2.2e-16

making predictions with the regression model

insurance\(pred <- predict(ins_model2, insurance) cor(insurance\)pred, insurance$expenses)

plot(insurance\(pred, insurance\)expenses) abline(a = 0, b = 1, col = “red”, lwd = 3, lty = 2)

predict(ins_model2, data.frame(age = 30, age2 = 30^2, children = 2, bmi = 30, sex = “male”, bmi30 = 1, smoker = “no”, region = “northeast”)) predict(ins_model2, data.frame(age = 30, age2 = 30^2, children = 2, bmi = 30, sex = “female”, bmi30 = 1, smoker = “no”, region = “northeast”))

set up the data

tee <- c(1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7) at1 <- c(1, 1, 1, 2, 2, 3, 4, 5, 5) at2 <- c(6, 6, 7, 7, 7, 7) bt1 <- c(1, 1, 1, 2, 2, 3, 4) bt2 <- c(5, 5, 6, 6, 7, 7, 7, 7)

compute the SDR

sdr_a <- sd(tee) - (length(at1) / length(tee) * sd(at1) + length(at2) / length(tee) * sd(at2)) sdr_b <- sd(tee) - (length(bt1) / length(tee) * sd(bt1) + length(bt2) / length(tee) * sd(bt2))

compare the SDR for each split

sdr_a

sdr_b

wine <- read.csv(“whitewines.csv”)

examine the wine data

str(wine) # the distribution of quality ratings hist(wine$quality) # summary statistics of the wine data summary(wine)

wine_train <- wine[1:3750, ] wine_test <- wine[3751:4898, ]

regression tree using rpart

library(rpart) m.rpart <- rpart(quality ~ ., data = wine_train) # get basic information about the tree m.rpart # get more detailed information about the tree summary(m.rpart)

install.packages(“rpart.plot”)

use the rpart.plot package to create a visualization

library(rpart.plot) # a basic decision tree diagram rpart.plot(m.rpart, digits = 3) # a few adjustments to the diagram rpart.plot(m.rpart, digits = 4, fallen.leaves = TRUE, type = 3, extra = 101)

generate predictions for the testing dataset

p.rpart <- predict(m.rpart, wine_test)

compare the distribution of predicted values vs. actual values

summary(p.rpart) summary(wine_test\(quality) # compare the correlation cor(p.rpart, wine_test\)quality)

function to calculate the mean absolute error

MAE <- function(actual, predicted) { mean(abs(actual - predicted))
}

MAE(p.rpart, wine_test\(quality) # mean absolute error between actual values and mean value mean(wine_train\)quality) # result = 5.87

MAE(5.87, wine_test$quality)

install.packages(“plyr”) install.packages(“Cubist”) # train a Cubist Model Tree library(Cubist) m.cubist <- cubist(x = wine_train[-12], y = wine_train$quality) # display basic information about the model tree m.cubist

display the tree itself

summary(m.cubist)

generate predictions for the model

p.cubist <- predict(m.cubist, wine_test)

summary statistics about the predictions

summary(p.cubist)

correlation between the predicted and true values

cor(p.cubist, wine_test$quality)

mean absolute error of predicted and true values

(uses a custom function defined above)

MAE(wine_test$quality, p.cubist)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKZ2V0d2QoKQpsYXVuY2ggPC0gcmVhZC5jc3YoImNoYWxsZW5nZXIuY3N2IikKCiMgZXN0aW1hdGUgYmV0YSBtYW51YWxseQpiIDwtIGNvdihsYXVuY2gkdGVtcGVyYXR1cmUsIGxhdW5jaCRkaXN0cmVzc19jdCkgLyB2YXIobGF1bmNoJHRlbXBlcmF0dXJlKQpiCgojIGVzdGltYXRlIGFscGhhIG1hbnVhbGx5CmEgPC0gbWVhbihsYXVuY2gkZGlzdHJlc3NfY3QpIC0gYiAqIG1lYW4obGF1bmNoJHRlbXBlcmF0dXJlKQphCgpyIDwtIGNvdihsYXVuY2gkdGVtcGVyYXR1cmUsIGxhdW5jaCRkaXN0cmVzc19jdCkgLwogICAgICAgKHNkKGxhdW5jaCR0ZW1wZXJhdHVyZSkgKiBzZChsYXVuY2gkZGlzdHJlc3NfY3QpKQpyCgpjb3IobGF1bmNoJHRlbXBlcmF0dXJlLCBsYXVuY2gkZGlzdHJlc3NfY3QpCgojIGNvbXB1dGluZyB0aGUgc2xvcGUgdXNpbmcgY29ycmVsYXRpb24KciAqIChzZChsYXVuY2gkZGlzdHJlc3NfY3QpIC8gc2QobGF1bmNoJHRlbXBlcmF0dXJlKSkKCiMgY29uZmlybWluZyB0aGUgcmVncmVzc2lvbiBsaW5lIHVzaW5nIHRoZSBsbSBmdW5jdGlvbiAobm90IGluIHRleHQpCm1vZGVsIDwtIGxtKGRpc3RyZXNzX2N0IH4gdGVtcGVyYXR1cmUsIGRhdGEgPSBsYXVuY2gpCm1vZGVsCgojIyAKIyMgQ2FsbDoKIyMgbG0oZm9ybXVsYSA9IGRpc3RyZXNzX2N0IH4gdGVtcGVyYXR1cmUsIGRhdGEgPSBsYXVuY2gpCiMjIAojIyBDb2VmZmljaWVudHM6CiMjIChJbnRlcmNlcHQpICB0ZW1wZXJhdHVyZSAgCiMjICAgICAyLjgxNDU4ICAgICAtMC4wMzM2NQpzdW1tYXJ5KG1vZGVsKQoKCiMgY3JlYXRpbmcgYSBzaW1wbGUgbXVsdGlwbGUgcmVncmVzc2lvbiBmdW5jdGlvbgpyZWcgPC0gZnVuY3Rpb24oeSwgeCkgewogIHggPC0gYXMubWF0cml4KHgpCiAgeCA8LSBjYmluZChJbnRlcmNlcHQgPSAxLCB4KQogIGIgPC0gc29sdmUodCh4KSAlKiUgeCkgJSolIHQoeCkgJSolIHkKICBjb2xuYW1lcyhiKSA8LSAiZXN0aW1hdGUiCiAgcHJpbnQoYikKfQoKIyBleGFtaW5lIHRoZSBsYXVuY2ggZGF0YQpzdHIobGF1bmNoKQoKIyB0ZXN0IHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24KcmVnKHkgPSBsYXVuY2gkZGlzdHJlc3NfY3QsIHggPSBsYXVuY2hbMl0pCgojIHVzZSByZWdyZXNzaW9uIG1vZGVsIHdpdGggbXVsdGlwbGUgcmVncmVzc2lvbgpyZWcoeSA9IGxhdW5jaCRkaXN0cmVzc19jdCwgeCA9IGxhdW5jaFsyOjRdKQoKIyBjb25maXJtaW5nIHRoZSBtdWx0aXBsZSByZWdyZXNzaW9uIHJlc3VsdCB1c2luZyB0aGUgbG0gZnVuY3Rpb24gKG5vdCBpbiB0ZXh0KQptb2RlbCA8LSBsbShkaXN0cmVzc19jdCB+IHRlbXBlcmF0dXJlICsgZmllbGRfY2hlY2tfcHJlc3N1cmUgKyBmbGlnaHRfbnVtLCBkYXRhID0gbGF1bmNoKQptb2RlbAoKIyMgCiMjIENhbGw6CiMjIGxtKGZvcm11bGEgPSBkaXN0cmVzc19jdCB+IHRlbXBlcmF0dXJlICsgZmllbGRfY2hlY2tfcHJlc3N1cmUgKyAKIyMgICAgIGZsaWdodF9udW0sIGRhdGEgPSBsYXVuY2gpCiMjIAojIyBDb2VmZmljaWVudHM6CiMjICAgICAgICAgIChJbnRlcmNlcHQpICAgICAgICAgICB0ZW1wZXJhdHVyZSAgZmllbGRfY2hlY2tfcHJlc3N1cmUgIAojIyAgICAgICAgICAgIDIuMjQwZSswMCAgICAgICAgICAgIC0zLjEyNGUtMDIgICAgICAgICAgICAtMi41ODdlLTA1ICAKIyMgICAgICAgICAgIGZsaWdodF9udW0gIAojIyAgICAgICAgICAgIDIuNzYyZS0wMgoKc3VtbWFyeShtb2RlbCkKCiMjIFN0ZXAgMjogRXhwbG9yaW5nIGFuZCBwcmVwYXJpbmcgdGhlIGRhdGEgLS0tLQppbnN1cmFuY2UgPC0gcmVhZC5jc3YoImluc3VyYW5jZS5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkKc3RyKGluc3VyYW5jZSkKCgojIHN1bW1hcml6ZSB0aGUgY2hhcmdlcyB2YXJpYWJsZQpzdW1tYXJ5KGluc3VyYW5jZSRleHBlbnNlcykKCiMgaGlzdG9ncmFtIG9mIGluc3VyYW5jZSBjaGFyZ2VzCmhpc3QoaW5zdXJhbmNlJGV4cGVuc2VzKQoKIyB0YWJsZSBvZiByZWdpb24KdGFibGUoaW5zdXJhbmNlJHJlZ2lvbikKCiMgZXhwbG9yaW5nIHJlbGF0aW9uc2hpcHMgYW1vbmcgZmVhdHVyZXM6IGNvcnJlbGF0aW9uIG1hdHJpeApjb3IoaW5zdXJhbmNlW2MoImFnZSIsICJibWkiLCAiY2hpbGRyZW4iLCAiZXhwZW5zZXMiKV0pCgojIHZpc3VhbGluZyByZWxhdGlvbnNoaXBzIGFtb25nIGZlYXR1cmVzOiBzY2F0dGVycGxvdCBtYXRyaXgKcGFpcnMoaW5zdXJhbmNlW2MoImFnZSIsICJibWkiLCAiY2hpbGRyZW4iLCAiZXhwZW5zZXMiKV0pCgojIyBTdGVwIDM6IFRyYWluaW5nIGEgbW9kZWwgb24gdGhlIGRhdGEgLS0tLQppbnNfbW9kZWwgPC0gbG0oZXhwZW5zZXMgfiBhZ2UgKyBjaGlsZHJlbiArIGJtaSArIHNleCArIHNtb2tlciArIHJlZ2lvbiwKICAgICAgICAgICAgICAgIGRhdGEgPSBpbnN1cmFuY2UpCmluc19tb2RlbCA8LSBsbShleHBlbnNlcyB+IC4sIGRhdGEgPSBpbnN1cmFuY2UpICMgdGhpcyBpcyBlcXVpdmFsZW50IHRvIGFib3ZlCgojIHNlZSB0aGUgZXN0aW1hdGVkIGJldGEgY29lZmZpY2llbnRzCmluc19tb2RlbAoKIyBzZWUgbW9yZSBkZXRhaWwgYWJvdXQgdGhlIGVzdGltYXRlZCBiZXRhIGNvZWZmaWNpZW50cwpzdW1tYXJ5KGluc19tb2RlbCkKCiMjIAojIyBDYWxsOgojIyBsbShmb3JtdWxhID0gZXhwZW5zZXMgfiAuLCBkYXRhID0gaW5zdXJhbmNlKQojIyAKIyMgUmVzaWR1YWxzOgojIyAgICAgIE1pbiAgICAgICAxUSAgIE1lZGlhbiAgICAgICAzUSAgICAgIE1heCAKIyMgLTExMzAyLjcgIC0yODUwLjkgICAtOTc5LjYgICAxMzgzLjkgIDI5OTgxLjcgCiMjIAojIyBDb2VmZmljaWVudHM6CiMjICAgICAgICAgICAgICAgICBFc3RpbWF0ZSBTdGQuIEVycm9yIHQgdmFsdWUgUHIoPnx0fCkgICAgCiMjIChJbnRlcmNlcHQpICAgICAtMTE5NDEuNiAgICAgIDk4Ny44IC0xMi4wODkgIDwgMmUtMTYgKioqCiMjIGFnZSAgICAgICAgICAgICAgICAyNTYuOCAgICAgICAxMS45ICAyMS41ODYgIDwgMmUtMTYgKioqCiMjIHNleG1hbGUgICAgICAgICAgIC0xMzEuMyAgICAgIDMzMi45ICAtMC4zOTUgMC42OTMyNTUgICAgCiMjIGJtaSAgICAgICAgICAgICAgICAzMzkuMyAgICAgICAyOC42ICAxMS44NjQgIDwgMmUtMTYgKioqCiMjIGNoaWxkcmVuICAgICAgICAgICA0NzUuNyAgICAgIDEzNy44ICAgMy40NTIgMC4wMDA1NzQgKioqCiMjIHNtb2tlcnllcyAgICAgICAgMjM4NDcuNSAgICAgIDQxMy4xICA1Ny43MjMgIDwgMmUtMTYgKioqCiMjIHJlZ2lvbm5vcnRod2VzdCAgIC0zNTIuOCAgICAgIDQ3Ni4zICAtMC43NDEgMC40NTg5NzYgICAgCiMjIHJlZ2lvbnNvdXRoZWFzdCAgLTEwMzUuNiAgICAgIDQ3OC43ICAtMi4xNjMgMC4wMzA2ODUgKiAgCiMjIHJlZ2lvbnNvdXRod2VzdCAgIC05NTkuMyAgICAgIDQ3Ny45ICAtMi4wMDcgMC4wNDQ5MjEgKiAgCiMjIC0tLQojIyBTaWduaWYuIGNvZGVzOiAgMCAnKioqJyAwLjAwMSAnKionIDAuMDEgJyonIDAuMDUgJy4nIDAuMSAnICcgMQojIyAKIyMgUmVzaWR1YWwgc3RhbmRhcmQgZXJyb3I6IDYwNjIgb24gMTMyOSBkZWdyZWVzIG9mIGZyZWVkb20KIyMgTXVsdGlwbGUgUi1zcXVhcmVkOiAgMC43NTA5LCBBZGp1c3RlZCBSLXNxdWFyZWQ6ICAwLjc0OTQgCiMjIEYtc3RhdGlzdGljOiA1MDAuOSBvbiA4IGFuZCAxMzI5IERGLCAgcC12YWx1ZTogPCAyLjJlLTE2CgojIGFkZCBhIGhpZ2hlci1vcmRlciAiYWdlIiB0ZXJtCmluc3VyYW5jZSRhZ2UyIDwtIGluc3VyYW5jZSRhZ2VeMgoKIyBhZGQgYW4gaW5kaWNhdG9yIGZvciBCTUkgPj0gMzAKaW5zdXJhbmNlJGJtaTMwIDwtIGlmZWxzZShpbnN1cmFuY2UkYm1pID49IDMwLCAxLCAwKQoKIyBjcmVhdGUgZmluYWwgbW9kZWwKaW5zX21vZGVsMiA8LSBsbShleHBlbnNlcyB+IGFnZSArIGFnZTIgKyBjaGlsZHJlbiArIGJtaSArIHNleCArCiAgICAgICAgICAgICAgICAgICBibWkzMCpzbW9rZXIgKyByZWdpb24sIGRhdGEgPSBpbnN1cmFuY2UpCiAgICAgICAgICAgICAgICAgICAKc3VtbWFyeShpbnNfbW9kZWwyKSAgICAgICAgICAgICAgICAgICAKCiMjIAojIyBDYWxsOgojIyBsbShmb3JtdWxhID0gZXhwZW5zZXMgfiBhZ2UgKyBhZ2UyICsgY2hpbGRyZW4gKyBibWkgKyBzZXggKyBibWkzMCAqIAojIyAgICAgc21va2VyICsgcmVnaW9uLCBkYXRhID0gaW5zdXJhbmNlKQojIyAKIyMgUmVzaWR1YWxzOgojIyAgICAgIE1pbiAgICAgICAxUSAgIE1lZGlhbiAgICAgICAzUSAgICAgIE1heCAKIyMgLTE3Mjk3LjEgIC0xNjU2LjAgIC0xMjYyLjcgICAtNzI3LjggIDI0MTYxLjYgCiMjIAojIyBDb2VmZmljaWVudHM6CiMjICAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKIyMgKEludGVyY2VwdCkgICAgICAgMTM5LjAwNTMgIDEzNjMuMTM1OSAgIDAuMTAyIDAuOTE4NzkyICAgIAojIyBhZ2UgICAgICAgICAgICAgICAtMzIuNjE4MSAgICA1OS44MjUwICAtMC41NDUgMC41ODU2OTAgICAgCiMjIGFnZTIgICAgICAgICAgICAgICAgMy43MzA3ICAgICAwLjc0NjMgICA0Ljk5OSA2LjU0ZS0wNyAqKioKIyMgY2hpbGRyZW4gICAgICAgICAgNjc4LjYwMTcgICAxMDUuODg1NSAgIDYuNDA5IDIuMDNlLTEwICoqKgojIyBibWkgICAgICAgICAgICAgICAxMTkuNzcxNSAgICAzNC4yNzk2ICAgMy40OTQgMC4wMDA0OTIgKioqCiMjIHNleG1hbGUgICAgICAgICAgLTQ5Ni43NjkwICAgMjQ0LjM3MTMgIC0yLjAzMyAwLjA0MjI2NyAqICAKIyMgYm1pMzAgICAgICAgICAgICAtOTk3LjkzNTUgICA0MjIuOTYwNyAgLTIuMzU5IDAuMDE4NDQ5ICogIAojIyBzbW9rZXJ5ZXMgICAgICAgMTM0MDQuNTk1MiAgIDQzOS45NTkxICAzMC40NjggIDwgMmUtMTYgKioqCiMjIHJlZ2lvbm5vcnRod2VzdCAgLTI3OS4xNjYxICAgMzQ5LjI4MjYgIC0wLjc5OSAwLjQyNDI4NSAgICAKIyMgcmVnaW9uc291dGhlYXN0ICAtODI4LjAzNDUgICAzNTEuNjQ4NCAgLTIuMzU1IDAuMDE4NjgyICogIAojIyByZWdpb25zb3V0aHdlc3QgLTEyMjIuMTYxOSAgIDM1MC41MzE0ICAtMy40ODcgMC4wMDA1MDUgKioqCiMjIGJtaTMwOnNtb2tlcnllcyAxOTgxMC4xNTM0ICAgNjA0LjY3NjkgIDMyLjc2MiAgPCAyZS0xNiAqKioKIyMgLS0tCiMjIFNpZ25pZi4gY29kZXM6ICAwICcqKionIDAuMDAxICcqKicgMC4wMSAnKicgMC4wNSAnLicgMC4xICcgJyAxCiMjIAojIyBSZXNpZHVhbCBzdGFuZGFyZCBlcnJvcjogNDQ0NSBvbiAxMzI2IGRlZ3JlZXMgb2YgZnJlZWRvbQojIyBNdWx0aXBsZSBSLXNxdWFyZWQ6ICAwLjg2NjQsIEFkanVzdGVkIFItc3F1YXJlZDogIDAuODY1MyAKIyMgRi1zdGF0aXN0aWM6IDc4MS43IG9uIDExIGFuZCAxMzI2IERGLCAgcC12YWx1ZTogPCAyLjJlLTE2CgojIG1ha2luZyBwcmVkaWN0aW9ucyB3aXRoIHRoZSByZWdyZXNzaW9uIG1vZGVsCmluc3VyYW5jZSRwcmVkIDwtIHByZWRpY3QoaW5zX21vZGVsMiwgaW5zdXJhbmNlKQpjb3IoaW5zdXJhbmNlJHByZWQsIGluc3VyYW5jZSRleHBlbnNlcykKCnBsb3QoaW5zdXJhbmNlJHByZWQsIGluc3VyYW5jZSRleHBlbnNlcykKYWJsaW5lKGEgPSAwLCBiID0gMSwgY29sID0gInJlZCIsIGx3ZCA9IDMsIGx0eSA9IDIpCgpwcmVkaWN0KGluc19tb2RlbDIsCiAgICAgICAgZGF0YS5mcmFtZShhZ2UgPSAzMCwgYWdlMiA9IDMwXjIsIGNoaWxkcmVuID0gMiwKICAgICAgICAgICAgICAgICAgIGJtaSA9IDMwLCBzZXggPSAibWFsZSIsIGJtaTMwID0gMSwKICAgICAgICAgICAgICAgICAgIHNtb2tlciA9ICJubyIsIHJlZ2lvbiA9ICJub3J0aGVhc3QiKSkKcHJlZGljdChpbnNfbW9kZWwyLAogICAgICAgIGRhdGEuZnJhbWUoYWdlID0gMzAsIGFnZTIgPSAzMF4yLCBjaGlsZHJlbiA9IDIsCiAgICAgICAgICAgICAgICAgICBibWkgPSAzMCwgc2V4ID0gImZlbWFsZSIsIGJtaTMwID0gMSwKICAgICAgICAgICAgICAgICAgIHNtb2tlciA9ICJubyIsIHJlZ2lvbiA9ICJub3J0aGVhc3QiKSkKICAgICAgICAgICAgICAgICAgIAojIHNldCB1cCB0aGUgZGF0YQp0ZWUgPC0gYygxLCAxLCAxLCAyLCAyLCAzLCA0LCA1LCA1LCA2LCA2LCA3LCA3LCA3LCA3KQphdDEgPC0gYygxLCAxLCAxLCAyLCAyLCAzLCA0LCA1LCA1KQphdDIgPC0gYyg2LCA2LCA3LCA3LCA3LCA3KQpidDEgPC0gYygxLCAxLCAxLCAyLCAyLCAzLCA0KQpidDIgPC0gYyg1LCA1LCA2LCA2LCA3LCA3LCA3LCA3KQoKIyBjb21wdXRlIHRoZSBTRFIKc2RyX2EgPC0gc2QodGVlKSAtIChsZW5ndGgoYXQxKSAvIGxlbmd0aCh0ZWUpICogc2QoYXQxKSArIGxlbmd0aChhdDIpIC8gbGVuZ3RoKHRlZSkgKiBzZChhdDIpKQpzZHJfYiA8LSBzZCh0ZWUpIC0gKGxlbmd0aChidDEpIC8gbGVuZ3RoKHRlZSkgKiBzZChidDEpICsgbGVuZ3RoKGJ0MikgLyBsZW5ndGgodGVlKSAqIHNkKGJ0MikpCgojIGNvbXBhcmUgdGhlIFNEUiBmb3IgZWFjaCBzcGxpdApzZHJfYQoKc2RyX2IKCndpbmUgPC0gcmVhZC5jc3YoIndoaXRld2luZXMuY3N2IikKCiMgZXhhbWluZSB0aGUgd2luZSBkYXRhCnN0cih3aW5lKQojIHRoZSBkaXN0cmlidXRpb24gb2YgcXVhbGl0eSByYXRpbmdzCmhpc3Qod2luZSRxdWFsaXR5KQojIHN1bW1hcnkgc3RhdGlzdGljcyBvZiB0aGUgd2luZSBkYXRhCnN1bW1hcnkod2luZSkKCndpbmVfdHJhaW4gPC0gd2luZVsxOjM3NTAsIF0Kd2luZV90ZXN0IDwtIHdpbmVbMzc1MTo0ODk4LCBdCgojIHJlZ3Jlc3Npb24gdHJlZSB1c2luZyBycGFydApsaWJyYXJ5KHJwYXJ0KQptLnJwYXJ0IDwtIHJwYXJ0KHF1YWxpdHkgfiAuLCBkYXRhID0gd2luZV90cmFpbikKIyBnZXQgYmFzaWMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHRyZWUKbS5ycGFydAojIGdldCBtb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IHRoZSB0cmVlCnN1bW1hcnkobS5ycGFydCkKCmluc3RhbGwucGFja2FnZXMoInJwYXJ0LnBsb3QiKQoKIyB1c2UgdGhlIHJwYXJ0LnBsb3QgcGFja2FnZSB0byBjcmVhdGUgYSB2aXN1YWxpemF0aW9uCmxpYnJhcnkocnBhcnQucGxvdCkKIyBhIGJhc2ljIGRlY2lzaW9uIHRyZWUgZGlhZ3JhbQpycGFydC5wbG90KG0ucnBhcnQsIGRpZ2l0cyA9IDMpCiMgYSBmZXcgYWRqdXN0bWVudHMgdG8gdGhlIGRpYWdyYW0KcnBhcnQucGxvdChtLnJwYXJ0LCBkaWdpdHMgPSA0LCBmYWxsZW4ubGVhdmVzID0gVFJVRSwgdHlwZSA9IDMsIGV4dHJhID0gMTAxKQoKIyBnZW5lcmF0ZSBwcmVkaWN0aW9ucyBmb3IgdGhlIHRlc3RpbmcgZGF0YXNldApwLnJwYXJ0IDwtIHByZWRpY3QobS5ycGFydCwgd2luZV90ZXN0KQoKIyBjb21wYXJlIHRoZSBkaXN0cmlidXRpb24gb2YgcHJlZGljdGVkIHZhbHVlcyB2cy4gYWN0dWFsIHZhbHVlcwpzdW1tYXJ5KHAucnBhcnQpCnN1bW1hcnkod2luZV90ZXN0JHF1YWxpdHkpCiMgY29tcGFyZSB0aGUgY29ycmVsYXRpb24KY29yKHAucnBhcnQsIHdpbmVfdGVzdCRxdWFsaXR5KQoKIyBmdW5jdGlvbiB0byBjYWxjdWxhdGUgdGhlIG1lYW4gYWJzb2x1dGUgZXJyb3IKTUFFIDwtIGZ1bmN0aW9uKGFjdHVhbCwgcHJlZGljdGVkKSB7CiAgbWVhbihhYnMoYWN0dWFsIC0gcHJlZGljdGVkKSkgIAp9CgpNQUUocC5ycGFydCwgd2luZV90ZXN0JHF1YWxpdHkpCiMgbWVhbiBhYnNvbHV0ZSBlcnJvciBiZXR3ZWVuIGFjdHVhbCB2YWx1ZXMgYW5kIG1lYW4gdmFsdWUKbWVhbih3aW5lX3RyYWluJHF1YWxpdHkpICMgcmVzdWx0ID0gNS44NwoKTUFFKDUuODcsIHdpbmVfdGVzdCRxdWFsaXR5KQoKaW5zdGFsbC5wYWNrYWdlcygicGx5ciIpCmluc3RhbGwucGFja2FnZXMoIkN1YmlzdCIpCiMgdHJhaW4gYSBDdWJpc3QgTW9kZWwgVHJlZQpsaWJyYXJ5KEN1YmlzdCkKbS5jdWJpc3QgPC0gY3ViaXN0KHggPSB3aW5lX3RyYWluWy0xMl0sIHkgPSB3aW5lX3RyYWluJHF1YWxpdHkpCiMgZGlzcGxheSBiYXNpYyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbW9kZWwgdHJlZQptLmN1YmlzdAoKIyBkaXNwbGF5IHRoZSB0cmVlIGl0c2VsZgpzdW1tYXJ5KG0uY3ViaXN0KQoKIyBnZW5lcmF0ZSBwcmVkaWN0aW9ucyBmb3IgdGhlIG1vZGVsCnAuY3ViaXN0IDwtIHByZWRpY3QobS5jdWJpc3QsIHdpbmVfdGVzdCkKCiMgc3VtbWFyeSBzdGF0aXN0aWNzIGFib3V0IHRoZSBwcmVkaWN0aW9ucwpzdW1tYXJ5KHAuY3ViaXN0KQoKIyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBwcmVkaWN0ZWQgYW5kIHRydWUgdmFsdWVzCmNvcihwLmN1YmlzdCwgd2luZV90ZXN0JHF1YWxpdHkpCgojIG1lYW4gYWJzb2x1dGUgZXJyb3Igb2YgcHJlZGljdGVkIGFuZCB0cnVlIHZhbHVlcwojICh1c2VzIGEgY3VzdG9tIGZ1bmN0aW9uIGRlZmluZWQgYWJvdmUpCk1BRSh3aW5lX3Rlc3QkcXVhbGl0eSwgcC5jdWJpc3QpIA==