if(!require("tidyverse")) install.packages("tidyverse")
if(!require("readr")) install.packages("readr")
if(!require("mvnormtest")) install.packages("mvnormtest")
if(!require("MVN")) install.packages("MVN")
if(!require("DescTools")) install.packages("DescTools")
if(!require("ConfidenceEllipse")) install.packages("ConfidenceEllipse")
if(!require("e1071")) install.packages("e1071")

Importar el dataset

banco_datos <- read_csv("C:/Users/Usuario/Downloads/Taller_1.csv", 
                     col_types = cols(...1 = col_skip()))
New names:
• `` -> `...1`

Exploración de normalidad

Previo a las pruebas de hipótesis, debemos comprobar si se cumple el supuesto de normalidad.

# Pruebas Shapiro y Mardia
mshapiro.test(t(banco_datos))

    Shapiro-Wilk normality test

data:  Z
W = 0.49079, p-value < 2.2e-16
mvn(data = banco_datos, mvnTest = "mardia")$multivariateNormality
# qqplot multivariado
mvn(data = banco_datos,
    multivariatePlot = "qq")$multivariatePlot
NULL

Como podemos observar, los tests sumado al qqplot nos dejan ver que el dataset no cumple con la normalidad, por lo que procedemos a analizar la normalidad de cada variable.

shapiro.test(banco_datos$V1)

    Shapiro-Wilk normality test

data:  banco_datos$V1
W = 0.99451, p-value = 0.07036
shapiro.test(banco_datos$V2)

    Shapiro-Wilk normality test

data:  banco_datos$V2
W = 0.44986, p-value < 2.2e-16
shapiro.test(banco_datos$V3)

    Shapiro-Wilk normality test

data:  banco_datos$V3
W = 0.89873, p-value < 2.2e-16
shapiro.test(banco_datos$V4)

    Shapiro-Wilk normality test

data:  banco_datos$V4
W = 0.99747, p-value = 0.6499
#qqplot univariado
mvn(data = banco_datos,
    univariatePlot = "qqplot")$multivariatePlot
NULL

#histogramas
mvn(data = banco_datos,
    univariatePlot = "histogram")$multivariatePlot
NULL

Con estos resultados, concluimos que es necesario realizar transformaciones en las variables “V2” y “V3”. Después de probar con diferentes métodos, se decidió utilizar la raíz catorceava conservando el signo del dato para “V2”, y la raíz del logaritmo del valor absoluto más uno, con una función añadida que preserva el signo del dato (dado que teníamos valores negativos), para “V3”. Además, se analizó la simetría, que resultó ser positiva en ambos casos, lo cual ayudó a determinar la transformación adecuada a aplicar.

skewness(banco_datos$V2)
[1] 5.641109
skewness(banco_datos$V3)
[1] 1.674798
root_with_sign <- function(x) {
  sign(x) * abs(x)^(1/14)
}

log_with_sign <- function(x) {
  sign(x) * (log1p(abs(x)))^(1/2)
}

banco_datos$V2 <- log_with_sign(banco_datos$V2)
banco_datos$V3 <- root_with_sign(banco_datos$V3)
skewness(banco_datos$V2)
[1] 0.03101506
skewness(banco_datos$V3)
[1] 0.06810174

Los resultados sugieren que estas dos variables corrigieron su asimetría, por lo que se harán las pruebas univariadas otra vez para comprobar.

shapiro.test(banco_datos$V1)

    Shapiro-Wilk normality test

data:  banco_datos$V1
W = 0.99451, p-value = 0.07036
shapiro.test(banco_datos$V2)

    Shapiro-Wilk normality test

data:  banco_datos$V2
W = 0.98958, p-value = 0.001281
shapiro.test(banco_datos$V3)

    Shapiro-Wilk normality test

data:  banco_datos$V3
W = 0.99727, p-value = 0.5807
shapiro.test(banco_datos$V4)

    Shapiro-Wilk normality test

data:  banco_datos$V4
W = 0.99747, p-value = 0.6499
mvn(data = banco_datos,
    univariatePlot = "qqplot")$multivariatePlot
NULL

Aunque la variable “V2” sigue sin ser normal según las pruebas, al hacer los tests multivariados los resultados mejoran bastante, como podemos ver a continuación:

mshapiro.test(t(banco_datos))

    Shapiro-Wilk normality test

data:  Z
W = 0.99524, p-value = 0.1289
mvn(data = banco_datos, mvnTest = "mardia")$multivariateNormality
# qqplot multivariado
mvn(data = banco_datos,
    multivariatePlot = "qq")$multivariatePlot
NULL

mvn(data = banco_datos,
    univariatePlot = "histogram")$multivariatePlot
NULL

Por tanto, se considera que los datos con las transformaciones aplicadas anteriormente cumplen con el supuesto de normalidad.

Constraste de hipótesis usando \(T^2\) Hotelling.

HotellingsT2Test(banco_datos,
                 mu = c(0.7, root_with_sign(0.14), log_with_sign(1.21), 0.6))

    Hotelling's one sample T2-test

data:  banco_datos
T.2 = 7347.9, df1 = 4, df2 = 496, p-value < 2.2e-16
alternative hypothesis: true location is not equal to c(0.7,0.868978728112495,0.890501272053927,0.6)

La primera prueba de hipótesis se hizo sobre el vector de medias (0.7, 0.14, 1.21, 0.6), se obtuvo un p_value menor a 0.05, por lo que se rechazaría la hipótesis de que el vector de medias (se tiene en cuenta la transformación para las variables “V2” y “V3”) sea igual a (0.7, 0.868978728112495, 0.890501272053927, 0.6) con una significancia del 5%.

HotellingsT2Test(banco_datos,
                 mu = c(1.2, root_with_sign(0.09), log_with_sign(1.49), 0.2))

    Hotelling's one sample T2-test

data:  banco_datos
T.2 = 1472.2, df1 = 4, df2 = 496, p-value < 2.2e-16
alternative hypothesis: true location is not equal to c(1.2,0.84198244434502,0.955134917420893,0.2)

La segunda prueba de hipótesis se hizo sobre el vector de medias (1.2, 0.09, 1.49, 0.2), se obtuvo un p_value menor a 0.05, por lo que se rechazaría la hipótesis de que el vector de medias (se tiene en cuenta la transformación para las variables “V2” y “V3”) sea igual a (1.2, 0.84198244434502, 0.955134917420893, 0.2) con una significancia del 5%.

Subvector (V3, V4).

banco_datos_subvector = banco_datos %>% select(V3, V4)

mshapiro.test(t(banco_datos_subvector))

    Shapiro-Wilk normality test

data:  Z
W = 0.99657, p-value = 0.3646
mvn(data = banco_datos_subvector, mvnTest = "mardia")$multivariateNormality
mvn(data = banco_datos_subvector, mvnTest = "hz")$multivariateNormality

Al hacer las pruebas de normalidad sobre el subvector (V3, V4) se obtuvo que no se rechaza la hipótesis que indica que el subvector se distribuye normal con una significancia del 5%.

Elipse de confianza

elipse_95 <- confidence_ellipse(banco_datos_subvector, 
                                x = V3, 
                                y = V4,
                                conf_level = 0.95)

X_barra = colMeans(banco_datos_subvector)

dim(X_barra) <- c(2,1)

ggplot() +
  geom_path(data = elipse_95, aes(x = x, y = y), color = "blue", linewidth = 1L) +
  geom_point(data = banco_datos_subvector, aes(x = V3, y = V4), color = "black", size = 1L)+
  geom_point(data = as_tibble(X_barra), aes(x = X_barra[1,1], y = X_barra[2,1]), color = "red")+
  labs(x = "V3", y = "V4") +
  theme_minimal() +
  theme(legend.position = "none")

NA
NA

El anterior gráfico representa la elipse de confianza respecto a la media con un 95% de significancia del subvector (V3,V4).

posible_punto = c(root_with_sign(1), .5)
dim(posible_punto) <- c(2,1)

ggplot() +
  geom_path(data = elipse_95, aes(x = x, y = y), color = "blue", linewidth = 1L) +
  geom_point(data = banco_datos_subvector, aes(x = V3, y = V4), color = "black", size = 1L)+
  geom_point(data = as_tibble(X_barra), aes(x = X_barra[1,1], y = X_barra[2,1]), color = "red")+
  geom_point(data = as_tibble(X_barra), aes(x = posible_punto[1,1], y = posible_punto[2,1]), color = "green")+
  labs(x = "V3", y = "V4") +
  theme_minimal() +
  theme(legend.position = "none")

Al graficar, el punto verde que representa que un cliente del banco tiene, en promedio, un puntaje crediticio de 0.5 y un saldo promedio de 1 millón de pesos en su cuenta de ahorros se encuentra claramente dentro de la elipse de confianza, lo que sugiere que es una posible media del subvector.

Diferencia entre el saldo promedio de las tarjetas Visa y Mastercard

C_matriz = matrix(c(1, -1, 0, 0), byrow = TRUE, nrow = 1) 
HotellingsT2Test(as.matrix(banco_datos)%*%t(C_matriz), 
                 mu = c(0))

    Hotelling's one sample T2-test

data:  as.matrix(banco_datos) %*% t(C_matriz)
T.2 = 894.59, df1 = 1, df2 = 499, p-value < 2.2e-16
alternative hypothesis: true location is not equal to c(0)

Al realizar la prueba de hipótesis se obtuvo un p_value mucho más pequeño que 0.05 por lo que, con una significancia del 5%, se concluye que existe una diferencia significativa entre el saldo promedio de cada una de las tarjetas de crédito. Como la diferencia resulto ser significativa, entonces se realizara un intervalo de confianza para obtener más información.

dif = as.matrix(banco_datos)%*%t(C_matriz)
colMeans(dif)
[1] 0.8654841
res <- t.test(x=dif, conf.level=0.95)
res$conf.int
[1] 0.8086315 0.9223367
attr(,"conf.level")
[1] 0.95

Se obtuvo un intervalo de confianza entre (0.80, 0,92), por lo que se concluye que, los usuarios en promedio tienen más saldo en promedio en las tarjetas de crédito del banco Visa.

LS0tDQp0aXRsZTogIlRhbGxlciAxIg0Kc3VidGl0bGU6IA0KICBBbsOhbGlzaXMgRXN0YWTDrXN0aWNvIGRlIERhdG9zICA8YnI+DQogIFVuaXZlcnNpZGFkIEVsIFJvc2FyaW8gDQphdXRob3I6DQogIC0gbmFtZTogIlJvYmVydCBEYW5pZWwgRm9uc2VjYSBMZXNtZXosIEp1YW4gU2ViYXN0aWFuIEFsdmFyYWRvIFJhbW9zLCBMdWNldGggQ2F0ZXJpbmUgQXJnb3RlIFJhZGlsbG8iDQogICAgYWZmaWxpYXRpb246ICJFc2N1ZWxhIGRlIEluZ2VuaWVyw61hLCBDaWVuY2lhIHkgVGVjbm9sb2fDrWEiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmlmKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCmlmKCFyZXF1aXJlKCJyZWFkciIpKSBpbnN0YWxsLnBhY2thZ2VzKCJyZWFkciIpDQppZighcmVxdWlyZSgibXZub3JtdGVzdCIpKSBpbnN0YWxsLnBhY2thZ2VzKCJtdm5vcm10ZXN0IikNCmlmKCFyZXF1aXJlKCJNVk4iKSkgaW5zdGFsbC5wYWNrYWdlcygiTVZOIikNCmlmKCFyZXF1aXJlKCJEZXNjVG9vbHMiKSkgaW5zdGFsbC5wYWNrYWdlcygiRGVzY1Rvb2xzIikNCmlmKCFyZXF1aXJlKCJDb25maWRlbmNlRWxsaXBzZSIpKSBpbnN0YWxsLnBhY2thZ2VzKCJDb25maWRlbmNlRWxsaXBzZSIpDQppZighcmVxdWlyZSgiZTEwNzEiKSkgaW5zdGFsbC5wYWNrYWdlcygiZTEwNzEiKQ0KYGBgDQoNCiMjICoqSW1wb3J0YXIgZWwgZGF0YXNldCoqDQpgYGB7cn0NCmJhbmNvX2RhdG9zIDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9Vc3VhcmlvL0Rvd25sb2Fkcy9UYWxsZXJfMS5jc3YiLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGNvbHMoLi4uMSA9IGNvbF9za2lwKCkpKQ0KYGBgDQoNCiMjICoqRXhwbG9yYWNpw7NuIGRlIG5vcm1hbGlkYWQqKg0KUHJldmlvIGEgbGFzIHBydWViYXMgZGUgaGlww7N0ZXNpcywgZGViZW1vcyBjb21wcm9iYXIgc2kgc2UgY3VtcGxlIGVsIHN1cHVlc3RvIGRlIG5vcm1hbGlkYWQuDQpgYGB7cn0NCiMgUHJ1ZWJhcyBTaGFwaXJvIHkgTWFyZGlhDQptc2hhcGlyby50ZXN0KHQoYmFuY29fZGF0b3MpKQ0KbXZuKGRhdGEgPSBiYW5jb19kYXRvcywgbXZuVGVzdCA9ICJtYXJkaWEiKSRtdWx0aXZhcmlhdGVOb3JtYWxpdHkNCiMgcXFwbG90IG11bHRpdmFyaWFkbw0KbXZuKGRhdGEgPSBiYW5jb19kYXRvcywNCiAgICBtdWx0aXZhcmlhdGVQbG90ID0gInFxIikkbXVsdGl2YXJpYXRlUGxvdA0KYGBgDQpDb21vIHBvZGVtb3Mgb2JzZXJ2YXIsIGxvcyB0ZXN0cyBzdW1hZG8gYWwgcXFwbG90IG5vcyBkZWphbiB2ZXIgcXVlIGVsIGRhdGFzZXQgbm8gY3VtcGxlIGNvbiBsYSBub3JtYWxpZGFkLCBwb3IgbG8gcXVlIHByb2NlZGVtb3MgYSBhbmFsaXphciBsYSBub3JtYWxpZGFkIGRlIGNhZGEgdmFyaWFibGUuDQoNCmBgYHtyfQ0Kc2hhcGlyby50ZXN0KGJhbmNvX2RhdG9zJFYxKQ0Kc2hhcGlyby50ZXN0KGJhbmNvX2RhdG9zJFYyKQ0Kc2hhcGlyby50ZXN0KGJhbmNvX2RhdG9zJFYzKQ0Kc2hhcGlyby50ZXN0KGJhbmNvX2RhdG9zJFY0KQ0KDQojcXFwbG90IHVuaXZhcmlhZG8NCm12bihkYXRhID0gYmFuY29fZGF0b3MsDQogICAgdW5pdmFyaWF0ZVBsb3QgPSAicXFwbG90IikkbXVsdGl2YXJpYXRlUGxvdA0KDQojaGlzdG9ncmFtYXMNCm12bihkYXRhID0gYmFuY29fZGF0b3MsDQogICAgdW5pdmFyaWF0ZVBsb3QgPSAiaGlzdG9ncmFtIikkbXVsdGl2YXJpYXRlUGxvdA0KYGBgDQpDb24gZXN0b3MgcmVzdWx0YWRvcywgY29uY2x1aW1vcyBxdWUgZXMgbmVjZXNhcmlvIHJlYWxpemFyIHRyYW5zZm9ybWFjaW9uZXMgZW4gbGFzIHZhcmlhYmxlcyDigJxWMuKAnSB5IOKAnFYz4oCdLiBEZXNwdcOpcyBkZSBwcm9iYXIgY29uIGRpZmVyZW50ZXMgbcOpdG9kb3MsIHNlIGRlY2lkacOzIHV0aWxpemFyIGxhIHJhw616IGNhdG9yY2VhdmEgY29uc2VydmFuZG8gZWwgc2lnbm8gZGVsIGRhdG8gcGFyYSDigJxWMuKAnSwgeSBsYSByYcOteiBkZWwgbG9nYXJpdG1vIGRlbCB2YWxvciBhYnNvbHV0byBtw6FzIHVubywgY29uIHVuYSBmdW5jacOzbiBhw7FhZGlkYSBxdWUgcHJlc2VydmEgZWwgc2lnbm8gZGVsIGRhdG8gKGRhZG8gcXVlIHRlbsOtYW1vcyB2YWxvcmVzIG5lZ2F0aXZvcyksIHBhcmEg4oCcVjPigJ0uIEFkZW3DoXMsIHNlIGFuYWxpesOzIGxhIHNpbWV0csOtYSwgcXVlIHJlc3VsdMOzIHNlciBwb3NpdGl2YSBlbiBhbWJvcyBjYXNvcywgbG8gY3VhbCBheXVkw7MgYSBkZXRlcm1pbmFyIGxhIHRyYW5zZm9ybWFjacOzbiBhZGVjdWFkYSBhIGFwbGljYXIuDQpgYGB7cn0NCnNrZXduZXNzKGJhbmNvX2RhdG9zJFYyKQ0Kc2tld25lc3MoYmFuY29fZGF0b3MkVjMpDQpgYGANCg0KYGBge3J9DQpyb290X3dpdGhfc2lnbiA8LSBmdW5jdGlvbih4KSB7DQogIHNpZ24oeCkgKiBhYnMoeCleKDEvMTQpDQp9DQoNCmxvZ193aXRoX3NpZ24gPC0gZnVuY3Rpb24oeCkgew0KICBzaWduKHgpICogKGxvZzFwKGFicyh4KSkpXigxLzIpDQp9DQoNCmJhbmNvX2RhdG9zJFYyIDwtIGxvZ193aXRoX3NpZ24oYmFuY29fZGF0b3MkVjIpDQpiYW5jb19kYXRvcyRWMyA8LSByb290X3dpdGhfc2lnbihiYW5jb19kYXRvcyRWMykNCmBgYA0KDQpgYGB7cn0NCnNrZXduZXNzKGJhbmNvX2RhdG9zJFYyKQ0Kc2tld25lc3MoYmFuY29fZGF0b3MkVjMpDQpgYGANCkxvcyByZXN1bHRhZG9zIHN1Z2llcmVuIHF1ZSBlc3RhcyBkb3MgdmFyaWFibGVzIGNvcnJpZ2llcm9uIHN1IGFzaW1ldHLDrWEsIHBvciBsbyBxdWUgc2UgaGFyw6FuIGxhcyBwcnVlYmFzIHVuaXZhcmlhZGFzIG90cmEgdmV6IHBhcmEgY29tcHJvYmFyLg0KYGBge3J9DQpzaGFwaXJvLnRlc3QoYmFuY29fZGF0b3MkVjEpDQpzaGFwaXJvLnRlc3QoYmFuY29fZGF0b3MkVjIpDQpzaGFwaXJvLnRlc3QoYmFuY29fZGF0b3MkVjMpDQpzaGFwaXJvLnRlc3QoYmFuY29fZGF0b3MkVjQpDQptdm4oZGF0YSA9IGJhbmNvX2RhdG9zLA0KICAgIHVuaXZhcmlhdGVQbG90ID0gInFxcGxvdCIpJG11bHRpdmFyaWF0ZVBsb3QNCmBgYA0KQXVucXVlIGxhIHZhcmlhYmxlICJWMiIgc2lndWUgc2luIHNlciBub3JtYWwgc2Vnw7puIGxhcyBwcnVlYmFzLCBhbCBoYWNlciBsb3MgdGVzdHMgbXVsdGl2YXJpYWRvcyBsb3MgcmVzdWx0YWRvcyBtZWpvcmFuIGJhc3RhbnRlLCBjb21vIHBvZGVtb3MgdmVyIGEgY29udGludWFjacOzbjoNCmBgYHtyfQ0KbXNoYXBpcm8udGVzdCh0KGJhbmNvX2RhdG9zKSkNCm12bihkYXRhID0gYmFuY29fZGF0b3MsIG12blRlc3QgPSAibWFyZGlhIikkbXVsdGl2YXJpYXRlTm9ybWFsaXR5DQojIHFxcGxvdCBtdWx0aXZhcmlhZG8NCm12bihkYXRhID0gYmFuY29fZGF0b3MsDQogICAgbXVsdGl2YXJpYXRlUGxvdCA9ICJxcSIpJG11bHRpdmFyaWF0ZVBsb3QNCm12bihkYXRhID0gYmFuY29fZGF0b3MsDQogICAgdW5pdmFyaWF0ZVBsb3QgPSAiaGlzdG9ncmFtIikkbXVsdGl2YXJpYXRlUGxvdA0KYGBgDQpQb3IgdGFudG8sIHNlIGNvbnNpZGVyYSBxdWUgbG9zIGRhdG9zIGNvbiBsYXMgdHJhbnNmb3JtYWNpb25lcyBhcGxpY2FkYXMgYW50ZXJpb3JtZW50ZSBjdW1wbGVuIGNvbiBlbCBzdXB1ZXN0byBkZSBub3JtYWxpZGFkLg0KDQojIyAqKkNvbnN0cmFzdGUgZGUgaGlww7N0ZXNpcyB1c2FuZG8gJFReMiQgSG90ZWxsaW5nLioqDQoNCmBgYHtyfQ0KSG90ZWxsaW5nc1QyVGVzdChiYW5jb19kYXRvcywNCiAgICAgICAgICAgICAgICAgbXUgPSBjKDAuNywgcm9vdF93aXRoX3NpZ24oMC4xNCksIGxvZ193aXRoX3NpZ24oMS4yMSksIDAuNikpDQoNCmBgYA0KDQpMYSBwcmltZXJhIHBydWViYSBkZSBoaXDDs3Rlc2lzIHNlIGhpem8gc29icmUgZWwgdmVjdG9yIGRlIG1lZGlhcyAoMC43LCAwLjE0LCAxLjIxLCAwLjYpLCBzZSBvYnR1dm8gdW4gcF92YWx1ZSBtZW5vciBhIDAuMDUsIHBvciBsbyBxdWUgc2UgcmVjaGF6YXLDrWEgbGEgaGlww7N0ZXNpcyBkZSBxdWUgZWwgdmVjdG9yIGRlIG1lZGlhcyAoc2UgdGllbmUgZW4gY3VlbnRhIGxhIHRyYW5zZm9ybWFjacOzbiBwYXJhIGxhcyB2YXJpYWJsZXMgIlYyIiB5ICJWMyIpIHNlYSBpZ3VhbCBhICgwLjcsIDAuODY4OTc4NzI4MTEyNDk1LCAwLjg5MDUwMTI3MjA1MzkyNywgMC42KSBjb24gdW5hIHNpZ25pZmljYW5jaWEgZGVsIDUlLg0KDQpgYGB7cn0NCkhvdGVsbGluZ3NUMlRlc3QoYmFuY29fZGF0b3MsDQogICAgICAgICAgICAgICAgIG11ID0gYygxLjIsIHJvb3Rfd2l0aF9zaWduKDAuMDkpLCBsb2dfd2l0aF9zaWduKDEuNDkpLCAwLjIpKQ0KDQpgYGANCg0KTGEgc2VndW5kYSBwcnVlYmEgZGUgaGlww7N0ZXNpcyBzZSBoaXpvIHNvYnJlIGVsIHZlY3RvciBkZSBtZWRpYXMgKDEuMiwgMC4wOSwgMS40OSwgMC4yKSwgc2Ugb2J0dXZvIHVuIHBfdmFsdWUgbWVub3IgYSAwLjA1LCBwb3IgbG8gcXVlIHNlIHJlY2hhemFyw61hIGxhIGhpcMOzdGVzaXMgZGUgcXVlIGVsIHZlY3RvciBkZSBtZWRpYXMgKHNlIHRpZW5lIGVuIGN1ZW50YSBsYSB0cmFuc2Zvcm1hY2nDs24gcGFyYSBsYXMgdmFyaWFibGVzICJWMiIgeSAiVjMiKSBzZWEgaWd1YWwgYSAoMS4yLCAwLjg0MTk4MjQ0NDM0NTAyLCAwLjk1NTEzNDkxNzQyMDg5MywgMC4yKSBjb24gdW5hIHNpZ25pZmljYW5jaWEgZGVsIDUlLg0KDQoNCiMjICoqU3VidmVjdG9yIChWMywgVjQpLioqDQpgYGB7cn0NCmJhbmNvX2RhdG9zX3N1YnZlY3RvciA9IGJhbmNvX2RhdG9zICU+JSBzZWxlY3QoVjMsIFY0KQ0KDQptc2hhcGlyby50ZXN0KHQoYmFuY29fZGF0b3Nfc3VidmVjdG9yKSkNCm12bihkYXRhID0gYmFuY29fZGF0b3Nfc3VidmVjdG9yLCBtdm5UZXN0ID0gIm1hcmRpYSIpJG11bHRpdmFyaWF0ZU5vcm1hbGl0eQ0KbXZuKGRhdGEgPSBiYW5jb19kYXRvc19zdWJ2ZWN0b3IsIG12blRlc3QgPSAiaHoiKSRtdWx0aXZhcmlhdGVOb3JtYWxpdHkNCmBgYA0KDQpBbCBoYWNlciBsYXMgcHJ1ZWJhcyBkZSBub3JtYWxpZGFkIHNvYnJlIGVsIHN1YnZlY3RvciAoVjMsIFY0KSBzZSBvYnR1dm8gcXVlIG5vIHNlIHJlY2hhemEgbGEgaGlww7N0ZXNpcyBxdWUgaW5kaWNhIHF1ZSBlbCBzdWJ2ZWN0b3Igc2UgZGlzdHJpYnV5ZSBub3JtYWwgY29uIHVuYSBzaWduaWZpY2FuY2lhIGRlbCA1JS4NCg0KIyMjICpFbGlwc2UgZGUgY29uZmlhbnphKg0KYGBge3IsIHdhcm5pbmcgPSBGQUxTRX0NCmVsaXBzZV85NSA8LSBjb25maWRlbmNlX2VsbGlwc2UoYmFuY29fZGF0b3Nfc3VidmVjdG9yLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IFYzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IFY0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25mX2xldmVsID0gMC45NSkNCg0KWF9iYXJyYSA9IGNvbE1lYW5zKGJhbmNvX2RhdG9zX3N1YnZlY3RvcikNCg0KZGltKFhfYmFycmEpIDwtIGMoMiwxKQ0KDQpnZ3Bsb3QoKSArDQogIGdlb21fcGF0aChkYXRhID0gZWxpcHNlXzk1LCBhZXMoeCA9IHgsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV3aWR0aCA9IDFMKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGJhbmNvX2RhdG9zX3N1YnZlY3RvciwgYWVzKHggPSBWMywgeSA9IFY0KSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMUwpKw0KICBnZW9tX3BvaW50KGRhdGEgPSBhc190aWJibGUoWF9iYXJyYSksIGFlcyh4ID0gWF9iYXJyYVsxLDFdLCB5ID0gWF9iYXJyYVsyLDFdKSwgY29sb3IgPSAicmVkIikrDQogIGxhYnMoeCA9ICJWMyIsIHkgPSAiVjQiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KDQpgYGANCkVsIGFudGVyaW9yIGdyw6FmaWNvIHJlcHJlc2VudGEgbGEgZWxpcHNlIGRlIGNvbmZpYW56YSByZXNwZWN0byBhIGxhIG1lZGlhIGNvbiB1biA5NSUgZGUgc2lnbmlmaWNhbmNpYSBkZWwgc3VidmVjdG9yIChWMyxWNCkuDQoNCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UgfQ0KcG9zaWJsZV9wdW50byA9IGMocm9vdF93aXRoX3NpZ24oMSksIC41KQ0KZGltKHBvc2libGVfcHVudG8pIDwtIGMoMiwxKQ0KDQpnZ3Bsb3QoKSArDQogIGdlb21fcGF0aChkYXRhID0gZWxpcHNlXzk1LCBhZXMoeCA9IHgsIHkgPSB5KSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV3aWR0aCA9IDFMKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGJhbmNvX2RhdG9zX3N1YnZlY3RvciwgYWVzKHggPSBWMywgeSA9IFY0KSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMUwpKw0KICBnZW9tX3BvaW50KGRhdGEgPSBhc190aWJibGUoWF9iYXJyYSksIGFlcyh4ID0gWF9iYXJyYVsxLDFdLCB5ID0gWF9iYXJyYVsyLDFdKSwgY29sb3IgPSAicmVkIikrDQogIGdlb21fcG9pbnQoZGF0YSA9IGFzX3RpYmJsZShYX2JhcnJhKSwgYWVzKHggPSBwb3NpYmxlX3B1bnRvWzEsMV0sIHkgPSBwb3NpYmxlX3B1bnRvWzIsMV0pLCBjb2xvciA9ICJncmVlbiIpKw0KICBsYWJzKHggPSAiVjMiLCB5ID0gIlY0IikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCg0KQWwgZ3JhZmljYXIsIGVsIHB1bnRvIHZlcmRlIHF1ZSByZXByZXNlbnRhIHF1ZSB1biBjbGllbnRlIGRlbCBiYW5jbyB0aWVuZSwgZW4gcHJvbWVkaW8sIHVuIHB1bnRhamUgY3JlZGl0aWNpbyBkZSAwLjUgeSB1biBzYWxkbyBwcm9tZWRpbyBkZSAxIG1pbGzDs24gZGUgcGVzb3MgZW4gc3UgY3VlbnRhIGRlIGFob3Jyb3Mgc2UgZW5jdWVudHJhIGNsYXJhbWVudGUgZGVudHJvIGRlIGxhIGVsaXBzZSBkZSBjb25maWFuemEsIGxvIHF1ZSBzdWdpZXJlIHF1ZSBlcyB1bmEgcG9zaWJsZSBtZWRpYSBkZWwgc3VidmVjdG9yLg0KDQojIyAqKkRpZmVyZW5jaWEgZW50cmUgZWwgc2FsZG8gcHJvbWVkaW8gZGUgbGFzIHRhcmpldGFzIFZpc2EgeSBNYXN0ZXJjYXJkKioNCg0KYGBge3J9DQpDX21hdHJpeiA9IG1hdHJpeChjKDEsIC0xLCAwLCAwKSwgYnlyb3cgPSBUUlVFLCBucm93ID0gMSkgDQpIb3RlbGxpbmdzVDJUZXN0KGFzLm1hdHJpeChiYW5jb19kYXRvcyklKiV0KENfbWF0cml6KSwgDQogICAgICAgICAgICAgICAgIG11ID0gYygwKSkNCmBgYA0KDQpBbCByZWFsaXphciBsYSBwcnVlYmEgZGUgaGlww7N0ZXNpcyBzZSBvYnR1dm8gdW4gcF92YWx1ZSBtdWNobyBtw6FzIHBlcXVlw7FvIHF1ZSAwLjA1IHBvciBsbyBxdWUsIGNvbiB1bmEgc2lnbmlmaWNhbmNpYSBkZWwgNSUsIHNlIGNvbmNsdXllICBxdWUgZXhpc3RlIHVuYSBkaWZlcmVuY2lhIHNpZ25pZmljYXRpdmEgZW50cmUgZWwgc2FsZG8gcHJvbWVkaW8gZGUgY2FkYSB1bmEgZGUgbGFzIHRhcmpldGFzIGRlIGNyw6lkaXRvLiBDb21vIGxhIGRpZmVyZW5jaWEgcmVzdWx0byBzZXIgc2lnbmlmaWNhdGl2YSwgZW50b25jZXMgc2UgcmVhbGl6YXJhIHVuIGludGVydmFsbyBkZSBjb25maWFuemEgcGFyYSBvYnRlbmVyIG3DoXMgaW5mb3JtYWNpw7NuLg0KDQpgYGB7cn0NCmRpZiA9IGFzLm1hdHJpeChiYW5jb19kYXRvcyklKiV0KENfbWF0cml6KQ0KY29sTWVhbnMoZGlmKQ0KDQpyZXMgPC0gdC50ZXN0KHg9ZGlmLCBjb25mLmxldmVsPTAuOTUpDQpyZXMkY29uZi5pbnQNCmBgYA0KDQpTZSBvYnR1dm8gdW4gaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBlbnRyZSAoMC44MCwgMCw5MiksIHBvciBsbyBxdWUgc2UgY29uY2x1eWUgcXVlLCBsb3MgdXN1YXJpb3MgZW4gcHJvbWVkaW8gdGllbmVuIG3DoXMgc2FsZG8gZW4gcHJvbWVkaW8gZW4gbGFzIHRhcmpldGFzIGRlIGNyw6lkaXRvIGRlbCBiYW5jbyBWaXNhLg==