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==