rm(list=ls())

Problem Determination

## Data (including year 2007-2016)
dat <- read.table("earthquakes.txt", header = FALSE)
names(dat) <- c("year","earthquake")
plot(dat,type = "b", xlab = "Year", ylab = "Number",
     main = "Number of major earthquakes")
earthquake.table <- table(dat$earthquake)
plot(earthquake.table, xlim = c(0,45), ylim = c(0,30), xlab = "Number", ylab = "Frequency", main = "Frequency of numbers of major earthquakes")
points(0:45, dpois(0:45, lambda = mean(dat$earthquake)) * dim(dat)[1], pch = 19)
mean(dat$earthquake)
var(dat$earthquake)

Hence overdispersion.

acf(dat$earthquake)

The function acf computes (and by default plots) estimates of the autocovariance or autocorrelation function. Hence autocorreltaion.

Mixture Model for number of Earthquake

Poisson mixture: transform

## natural to working parameters
poisMix.pn2pw <- function(nDist, lambda, delta){
    # length(lambda) = nDist
    # length(delta) = nDist - 1
    if(sum(delta) >= 1){print("sum(delta) should be < 1")
    return()}
    if(length(lambda) != nDist){
        print("length(lambda) should be nDist")
        return()
    }
    if(length(delta) != (nDist - 1)){
        print("length(delta) should be nDist - 1")
        return()
    }
    eta <- log(lambda)
    tau <- log(delta / (1 - sum(delta)))
    return(list(eta = eta, tau = tau))
}

## Poisson mixture: transform
## working to natural parameters
poisMix.pw2pn <- function(nDist,eta,tau){
    if(nDist == 1){return(exp(eta))}
    if(length(eta) != nDist){
        print("length(lambda) should be nDist")
    return()}
    if(length(tau) != (nDist-1)){
        print("length(delta) should be nDist-1")
        return()
    }
    lambda <- exp(eta)
    delta <- exp(tau) / (1 + sum(exp(tau)))
    delta <- c(1 - sum(delta), delta)
    return(list(lambda = lambda, delta = delta))
}
## negative log likelihood function
negaLogL <- function(theta, nDist, y){
    if(nDist == 1){
        return(- sum(dpois(y, lambda = exp(theta), log = TRUE)))
    }
    eta <- theta[1: nDist]
    tau <- theta[(nDist + 1): (2 * nDist - 1)]
    naturalPars <- poisMix.pw2pn(nDist, eta, tau)
    n <- length(y)
    nll <- 0  # negative log likelihood
    for(i in 1:n){
        nll <- nll - log(sum(naturalPars$delta * 
                             dpois(y[i], lambda = naturalPars$lambda)))
    }
    return(nll)
}

Estimation with one distribution

m_HMM_mix_1 <- 1; ## No of states
## Initial values
lambda_mix.0_1 <- mean(dat$earthquake); 
delta_mix.0_1 <- c()
## Working parameters
workPars_mix_1 <- poisMix.pn2pw(m_HMM_mix_1, lambda_mix.0_1, delta_mix.0_1)
theta_mix.0_1 <- c(workPars_mix_1$eta, workPars_mix_1$tau)
## MLE
opt_mix_1 <- nlminb(theta_mix.0_1, negaLogL, nDist = m_HMM_mix_1, y = dat$earthquake)
sprintf("Max-Likelihood estimation with one distribution")
print(opt_mix_1)
## Natural parameters
naturalPars_mix_1 <- poisMix.pw2pn(m_HMM_mix_1, opt_mix_1$par[1: m_HMM_mix_1], 
                                   opt_mix_1$par[(m_HMM_mix_1 + 1) : (2 * m_HMM_mix_1 - 1)])
sprintf("Natural parameters by estimation with one distribution")
print(naturalPars_mix_1)

Estimation with two distributions

m_HMM_mix_2 <- 2; ## No of states
## Initial values
lambda_mix.0_2 <- mean(dat$earthquake) * c(1/2, 3/2);
delta_mix.0_2 <- c(0.5)
## Working parameters
workPars_mix_2 <- poisMix.pn2pw(m_HMM_mix_2, lambda_mix.0_2, delta_mix.0_2)
theta_mix.0_2 <- c(workPars_mix_2$eta, workPars_mix_2$tau)
## MLE
opt_mix_2 <- nlminb(theta_mix.0_2, negaLogL, nDist = m_HMM_mix_2, y = dat$earthquake)
sprintf("Max-Likelihood estimation with two distributions")
print(opt_mix_2)
## Natural parameters
naturalPars_mix_2 <- poisMix.pw2pn(m_HMM_mix_2, opt_mix_2$par[1: m_HMM_mix_2],
                                   opt_mix_2$par[(m_HMM_mix_2 + 1): (2 * m_HMM_mix_2 - 1)])
sprintf("Natural parameters by estimation with two distributions")
print(naturalPars_mix_2)

Estimation with 3 distributions

m_HMM_mix_3 <- 3;
lambda_mix.0_3 <- mean(dat$earthquake) * c(1/2, 1, 3/2);
delta_mix.0_3 <- c(1/3, 1/3)
workPars_mix_3 <- poisMix.pn2pw(m_HMM_mix_3, lambda_mix.0_3, delta_mix.0_3)
theta_mix.0_3 <- c(workPars_mix_3$eta, workPars_mix_3$tau)
opt_mix_3 <- nlminb(theta_mix.0_3, negaLogL, nDist = m_HMM_mix_3, y = dat$earthquake)
sprintf("Max-Likelihood estimation with three distributions")
print(opt_mix_3)
naturalPars_mix_3 <- poisMix.pw2pn(m_HMM_mix_3, opt_mix_3$par[1: m_HMM_mix_3],
                                   opt_mix_3$par[(m_HMM_mix_3 + 1): (2 * m_HMM_mix_3 - 1)])
sprintf("Natural parameters by estimation with three distributions")
print(naturalPars_mix_3)

Estimation with 4 distributions

m_HMM_mix_4 <- 4;
lambda_mix.0_4 <- mean(dat$earthquake) * c(1/4, 3/4, 5/4, 7/4);
delta_mix.0_4 <- c(1, 1, 1) / 4
workPars_mix_4 <- poisMix.pn2pw(m_HMM_mix_4, lambda_mix.0_4, delta_mix.0_4)
theta_mix.0_4 <- c(workPars_mix_4$eta, workPars_mix_4$tau)
opt_mix_4 <- nlminb(theta_mix.0_4, negaLogL, nDist = m_HMM_mix_4, y = dat$earthquake)
sprintf("Max-Likelihood estimation with four distributions")
print(opt_mix_4)
naturalPars_mix_4 <- poisMix.pw2pn(m_HMM_mix_4, opt_mix_4$par[1: m_HMM_mix_4],
                                   opt_mix_4$par[(m_HMM_mix_4 + 1): (2 * m_HMM_mix_4 - 1)])
sprintf("Natural parameters by estimation with four distributions")
print(naturalPars_mix_4)

Plot the result

plot(earthquake.table / sum(earthquake.table), xlim = c(0,45), axes = FALSE,
     xlab = "Number", ylab = "Density", 
     main = "Poisson Mixture Model for numbers of major earthquakes")
axis(1); axis(2)
x <- 0:45
mixDist <- function(x, naturalPars){
    ## Function to calculate mixture dist
    sum(naturalPars$delta * dpois(x, lambda = naturalPars$lambda))
}  
lines(x, dpois(x, lambda = naturalPars_mix_1), 
      type = "b", col = 1, pch = 19)
lines(x, sapply(x, mixDist, naturalPars = naturalPars_mix_2), 
      type = "b", col = 2, pch = 19)
lines(x, sapply(x, mixDist, naturalPars = naturalPars_mix_3), 
      type = "b", col = 3, pch = 19)
lines(x, sapply(x, mixDist, naturalPars =naturalPars_mix_4), 
      type = "b", col = 4, pch = 19)
legend("topright", col = seq(1, 4), lwd = 2, 
       c("1 distritution", "2 distritutions", 
         "3 distritutions", "4 distritutions"))

Choose the most suitable model using AIC

AIC_poisMix <- 2 * c(opt_mix_1$objective, opt_mix_2$objective,
                     opt_mix_3$objective, opt_mix_4$objective) +
               2 * c(length(opt_mix_1$par), length(opt_mix_2$par),
                     length(opt_mix_3$par), length(opt_mix_4$par))
print(AIC_poisMix)

Hence we choose 3-state model.

Choose the most suitable model using likelihood ratio test

1 - pchisq(2 * (opt_mix_1$objective - opt_mix_2$objective),
           df = length(opt_mix_2$par)-length(opt_mix_1$par))
1 - pchisq(2 * (opt_mix_2$objective - opt_mix_3$objective),
           df=length(opt_mix_3$par)-length(opt_mix_2$par))
1 - pchisq(2 * (opt_mix_3$objective - opt_mix_4$objective),
           df=length(opt_mix_4$par) - length(opt_mix_3$par))

Hence same conclusion as for AIC.

Hidden Markov Model for number of Earthquake

source("A1.R")
y <- dat$earthquake

Hidden Markov Model with 1 State

m_HMM_1 <- 1
lambda_HMM.0_1 <- mean(y)
gamma_HMM.0_1 <- 0
opt_HMM_1 <- pois.HMM.mle(y, m_HMM_1, lambda_HMM.0_1, gamma_HMM.0_1)

Hidden Markov Model with 2 State

m_HMM_2 <- 2
lambda_HMM.0_2 <- quantile(y, c(0.25, 0.75))
gamma_HMM.0_2 <- matrix(0.05, ncol = m_HMM_2, nrow = m_HMM_2)
diag(gamma_HMM.0_2) <- 1 - (m_HMM_2 - 1) * gamma_HMM.0_2[1,1]
opt_HMM_2 <- pois.HMM.mle(y, m_HMM_2, lambda_HMM.0_2, gamma_HMM.0_2)

Hidden Markov Model with 3 State

m_HMM_3 <- 3
lambda_HMM.0_3 <- quantile(y, c(0.25, 0.5, 0.75))
gamma_HMM.0_3 <- matrix(0.05, ncol = m_HMM_3, nrow = m_HMM_3)
diag(gamma_HMM.0_3) <- 1 - (m_HMM_3 - 1) * gamma_HMM.0_3[1, 1]
opt_HMM_3 <- pois.HMM.mle(y, m_HMM_3, lambda_HMM.0_3, gamma_HMM.0_3)

Hidden Markov Model with 4 State

m_HMM_4 <- 4
lambda_HMM.0_4 <- quantile(y,c(0.2, 0.4, 0.6, 0.8))
gamma_HMM.0_4 <- matrix(0.025, ncol = m_HMM_4, nrow = m_HMM_4)
diag(gamma_HMM.0_4) <- 1 - (m_HMM_4 - 1) * gamma_HMM.0_4[1, 1]
opt_HMM_4 <- pois.HMM.mle(y, m_HMM_4, lambda_HMM.0_4, gamma_HMM.0_4)

AIC

AIC_HMM <- c(opt_HMM_1$AIC, opt_HMM_2$AIC, opt_HMM_3$AIC, opt_HMM_4$AIC)
logL_HMM <- -c(opt_HMM_1$mllk, opt_HMM_2$mllk, opt_HMM_3$mllk, opt_HMM_4$mllk)
m_HMM_HMM <- c(1, 2, 3, 4)
df_HMM <- m_HMM_HMM + (m_HMM_HMM^2 - m_HMM_HMM)  # lambda + gamma
cbind(df_HMM, logL_HMM, AIC_HMM)

So we choose HMM with 3 states.

## Finding the standard errors
m_HMM <- 3
## working parameters
partsWork_HMM  <- pois.HMM.pn2pw(m_HMM, opt_HMM_3$lambda, opt_HMM_3$gamma)
mod_HMM <- nlm(pois.HMM.mllk, partsWork_HMM, x = y, m = m_HMM, hessian = TRUE)  
## Organize the result
partsWork.nlm_HMM <- mod_HMM$estimate
names(partsWork.nlm_HMM) <- c("lambda1", "lambda2", "lambda3", "tau21", "tau31", "tau12", "tau32", "tau13", "tau23")
se_HMM <- sqrt(diag(solve(mod_HMM$hessian)))

## Working pars + standard error
round(cbind(partsWork.nlm_HMM, se_HMM), digits = 2)
opt_HMM_3$gamma

Parametric bootstrap

source("A2.R")
## Initailize
n <- length(y)
k <- 100
m <- 3
lambda0 <- quantile(y, c(0.25, 0.5, 0.75))
gamma0 <- matrix(0.025, ncol = m, nrow = m)
diag(gamma0) <- 1 - (m - 1) * gamma0[1,1]
## Matrices to stores bootstap result
GAMMA <- matrix(ncol = m * m, nrow = k)
Lambda <- matrix(ncol = m, nrow = k)
Delta <- matrix(ncol = m, nrow = k)
Code <- numeric(k)
## Boot strap with two different optimizers
for(i in 1:k){
    set.seed(i)
    ## generate sample
    y.sim <- pois.HMM.generate_sample(n, m, opt_HMM_3$lambda, opt_HMM_3$gamma)
    ## fit model to sample
    opt_HMM_3.tmp <- pois.HMM.mle(y.sim, m, lambda0, gamma0)
    ## Store result
    GAMMA[i, ] <- c(opt_HMM_3.tmp$gamma[1, ],
                    opt_HMM_3.tmp$gamma[2, ],
                    opt_HMM_3.tmp$gamma[3, ])
    Lambda[i, ] <- opt_HMM_3.tmp$lambda
    Delta[i, ] <- opt_HMM_3.tmp$delta
    Code[i] <- opt_HMM_3.tmp$code
    print(c(i,Code[i]))
}
NA/Inf replaced by maximum positive value
[1] 1 1
[1] 2 1
[1] 3 1
NA/Inf replaced by maximum positive value
[1] 4 1
NA/Inf replaced by maximum positive value
[1] 5 1
[1] 6 1
[1] 7 1
[1] 8 1
[1] 9 1
NA/Inf replaced by maximum positive value
[1] 10  1
[1] 11  1
[1] 12  1
[1] 13  1
[1] 14  1
[1] 15  1
[1] 16  1
[1] 17  1
[1] 18  1
[1] 19  2
[1] 20  1
[1] 21  1
NA/Inf replaced by maximum positive value
[1] 22  1
[1] 23  1
[1] 24  1
[1] 25  1
[1] 26  1
[1] 27  1
[1] 28  1
[1] 29  1
[1] 30  5
[1] 31  1
[1] 32  1
NA/Inf replaced by maximum positive value
[1] 33  1
[1] 34  1
NA/Inf replaced by maximum positive value
[1] 35  1
[1] 36  1
[1] 37  1
NA/Inf replaced by maximum positive value
[1] 38  1
[1] 39  1
[1] 40  1
NA/Inf replaced by maximum positive value
[1] 41  1
[1] 42  1
[1] 43  1
[1] 44  1
[1] 45  1
[1] 46  1
[1] 47  1
[1] 48  1
NA/Inf replaced by maximum positive value
[1] 49  1
[1] 50  1
[1] 51  1
[1] 52  1
[1] 53  1
[1] 54  1
[1] 55  1
[1] 56  1
[1] 57  1
[1] 58  1
[1] 59  1
[1] 60  1
[1] 61  1
[1] 62  1
[1] 63  1
[1] 64  1
[1] 65  1
[1] 66  1
[1] 67  1
[1] 68  1
[1] 69  1
[1] 70  1
[1] 71  1
[1] 72  1
[1] 73  1
[1] 74  1
[1] 75  1
[1] 76  1
[1] 77  1
[1] 78  1
[1] 79  1
[1] 80  1
[1] 81  1
[1] 82  1
[1] 83  1
NA/Inf replaced by maximum positive value
[1] 84  1
[1] 85  5
[1] 86  1
[1] 87  1
[1] 88  1
[1] 89  1
NA/Inf replaced by maximum positive value
[1] 90  1
[1] 91  1
[1] 92  1
[1] 93  1
NA/Inf replaced by maximum positive value
[1] 94  1
[1] 95  1
[1] 96  1
[1] 97  5
[1] 98  1
[1] 99  1
[1] 100   1
sum(Code!=1)
[1] 4
## Same as above with different optimizer
for(i in 1:k){
    set.seed(i)
    y.sim <- pois.HMM.generate_sample(n, m,
                                      opt_HMM_3$lambda, opt_HMM_3$gamma)
    lambda0 <- quantile(y.sim,c(0.25,0.5,0.75))
    opt_HMM_3.tmp <- pois.HMM.mle.nlminb(y.sim, m,lambda0, gamma0)
    GAMMA[i, ] <- c(opt_HMM_3.tmp$gamma[1, ],
                    opt_HMM_3.tmp$gamma[2, ],
                    opt_HMM_3.tmp$gamma[3, ])
    Lambda[i, ] <- opt_HMM_3.tmp$lambda
    Delta[i, ] <- opt_HMM_3.tmp$delta
    Code[i] <- opt_HMM_3.tmp$code
    print(c(i,Code[i]))
}
[1] 1 0
[1] 2 0
[1] 3 0
[1] 4 0
[1] 5 0
[1] 6 0
[1] 7 0
[1] 8 0
[1] 9 0
[1] 10  0
[1] 11  0
[1] 12  0
[1] 13  0
[1] 14  0
[1] 15  0
[1] 16  0
[1] 17  0
[1] 18  0
[1] 19  0
[1] 20  0
[1] 21  0
[1] 22  0
[1] 23  0
[1] 24  0
[1] 25  0
[1] 26  0
[1] 27  0
[1] 28  0
[1] 29  0
[1] 30  0
[1] 31  0
[1] 32  0
[1] 33  0
[1] 34  0
[1] 35  0
[1] 36  0
[1] 37  0
[1] 38  0
[1] 39  0
[1] 40  0
[1] 41  0
[1] 42  0
[1] 43  0
[1] 44  0
[1] 45  0
[1] 46  0
[1] 47  0
[1] 48  0
[1] 49  0
[1] 50  0
[1] 51  0
[1] 52  0
[1] 53  0
[1] 54  0
[1] 55  0
[1] 56  0
[1] 57  0
[1] 58  0
[1] 59  0
[1] 60  0
[1] 61  0
[1] 62  0
[1] 63  0
[1] 64  0
[1] 65  0
[1] 66  0
[1] 67  0
[1] 68  0
[1] 69  0
[1] 70  0
[1] 71  0
[1] 72  0
[1] 73  0
[1] 74  0
[1] 75  0
[1] 76  0
[1] 77  0
[1] 78  0
[1] 79  0
[1] 80  0
[1] 81  0
[1] 82  0
[1] 83  0
[1] 84  0
[1] 85  0
[1] 86  0
[1] 87  0
[1] 88  0
[1] 89  0
[1] 90  0
[1] 91  0
[1] 92  0
[1] 93  0
[1] 94  0
[1] 95  0
[1] 96  0
[1] 97  0
[1] 98  0
[1] 99  0
[1] 100   0
sum(Code!=0)
[1] 0
## Plot the results (i.e. statistical distribution of
## estimates
par(mfrow = c(1,3))
hist(Lambda[ ,1])
rug(opt_HMM_3$lambda, lwd = 2, col = 2)
some values will be clipped
hist(Lambda[ ,2])
rug(opt_HMM_3$lambda, lwd = 2, col = 2)
some values will be clipped
hist(Lambda[ ,3])
rug(opt_HMM_3$lambda, lwd = 2, col = 2)
some values will be clipped

LS0tCnRpdGxlOiAiTWl4dHVyZSBvZiBQb2lzc29uIE1vZGVsczogRWFydGhxdWFrZSIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogRWR3YXJkIEouIFh1CmRhdGU6IERlY2VtYmVyIDFzdCwgMjAxOAotLS0KCmBgYHtyfQpybShsaXN0PWxzKCkpCmBgYAoKIyBQcm9ibGVtIERldGVybWluYXRpb24KCmBgYHtyfQojIyBEYXRhIChpbmNsdWRpbmcgeWVhciAyMDA3LTIwMTYpCmRhdCA8LSByZWFkLnRhYmxlKCJlYXJ0aHF1YWtlcy50eHQiLCBoZWFkZXIgPSBGQUxTRSkKbmFtZXMoZGF0KSA8LSBjKCJ5ZWFyIiwiZWFydGhxdWFrZSIpCmBgYAoKYGBge3J9CnBsb3QoZGF0LHR5cGUgPSAiYiIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiTnVtYmVyIiwKICAgICBtYWluID0gIk51bWJlciBvZiBtYWpvciBlYXJ0aHF1YWtlcyIpCmBgYAoKYGBge3J9CmVhcnRocXVha2UudGFibGUgPC0gdGFibGUoZGF0JGVhcnRocXVha2UpCnBsb3QoZWFydGhxdWFrZS50YWJsZSwgeGxpbSA9IGMoMCw0NSksIHlsaW0gPSBjKDAsMzApLCB4bGFiID0gIk51bWJlciIsIHlsYWIgPSAiRnJlcXVlbmN5IiwgbWFpbiA9ICJGcmVxdWVuY3kgb2YgbnVtYmVycyBvZiBtYWpvciBlYXJ0aHF1YWtlcyIpCnBvaW50cygwOjQ1LCBkcG9pcygwOjQ1LCBsYW1iZGEgPSBtZWFuKGRhdCRlYXJ0aHF1YWtlKSkgKiBkaW0oZGF0KVsxXSwgcGNoID0gMTkpCmBgYAoKYGBge3J9Cm1lYW4oZGF0JGVhcnRocXVha2UpCnZhcihkYXQkZWFydGhxdWFrZSkKYGBgCkhlbmNlIG92ZXJkaXNwZXJzaW9uLgoKYGBge3J9CmFjZihkYXQkZWFydGhxdWFrZSkKYGBgClRoZSBmdW5jdGlvbiBhY2YgY29tcHV0ZXMgKGFuZCBieSBkZWZhdWx0IHBsb3RzKSBlc3RpbWF0ZXMgb2YgdGhlIGF1dG9jb3ZhcmlhbmNlIG9yIGF1dG9jb3JyZWxhdGlvbiBmdW5jdGlvbi4gSGVuY2UgYXV0b2NvcnJlbHRhaW9uLgoKIyBNaXh0dXJlIE1vZGVsIGZvciBudW1iZXIgb2YgRWFydGhxdWFrZQoKIyMgUG9pc3NvbiBtaXh0dXJlOiB0cmFuc2Zvcm0KCmBgYHtyfQojIyBuYXR1cmFsIHRvIHdvcmtpbmcgcGFyYW1ldGVycwpwb2lzTWl4LnBuMnB3IDwtIGZ1bmN0aW9uKG5EaXN0LCBsYW1iZGEsIGRlbHRhKXsKICAgICMgbGVuZ3RoKGxhbWJkYSkgPSBuRGlzdAogICAgIyBsZW5ndGgoZGVsdGEpID0gbkRpc3QgLSAxCiAgICBpZihzdW0oZGVsdGEpID49IDEpe3ByaW50KCJzdW0oZGVsdGEpIHNob3VsZCBiZSA8IDEiKQogICAgcmV0dXJuKCl9CiAgICBpZihsZW5ndGgobGFtYmRhKSAhPSBuRGlzdCl7CiAgICAgICAgcHJpbnQoImxlbmd0aChsYW1iZGEpIHNob3VsZCBiZSBuRGlzdCIpCiAgICAgICAgcmV0dXJuKCkKICAgIH0KICAgIGlmKGxlbmd0aChkZWx0YSkgIT0gKG5EaXN0IC0gMSkpewogICAgICAgIHByaW50KCJsZW5ndGgoZGVsdGEpIHNob3VsZCBiZSBuRGlzdCAtIDEiKQogICAgICAgIHJldHVybigpCiAgICB9CiAgICBldGEgPC0gbG9nKGxhbWJkYSkKICAgIHRhdSA8LSBsb2coZGVsdGEgLyAoMSAtIHN1bShkZWx0YSkpKQogICAgcmV0dXJuKGxpc3QoZXRhID0gZXRhLCB0YXUgPSB0YXUpKQp9CgojIyBQb2lzc29uIG1peHR1cmU6IHRyYW5zZm9ybQojIyB3b3JraW5nIHRvIG5hdHVyYWwgcGFyYW1ldGVycwpwb2lzTWl4LnB3MnBuIDwtIGZ1bmN0aW9uKG5EaXN0LGV0YSx0YXUpewogICAgaWYobkRpc3QgPT0gMSl7cmV0dXJuKGV4cChldGEpKX0KICAgIGlmKGxlbmd0aChldGEpICE9IG5EaXN0KXsKICAgICAgICBwcmludCgibGVuZ3RoKGxhbWJkYSkgc2hvdWxkIGJlIG5EaXN0IikKICAgIHJldHVybigpfQogICAgaWYobGVuZ3RoKHRhdSkgIT0gKG5EaXN0LTEpKXsKICAgICAgICBwcmludCgibGVuZ3RoKGRlbHRhKSBzaG91bGQgYmUgbkRpc3QtMSIpCiAgICAgICAgcmV0dXJuKCkKICAgIH0KICAgIGxhbWJkYSA8LSBleHAoZXRhKQogICAgZGVsdGEgPC0gZXhwKHRhdSkgLyAoMSArIHN1bShleHAodGF1KSkpCiAgICBkZWx0YSA8LSBjKDEgLSBzdW0oZGVsdGEpLCBkZWx0YSkKICAgIHJldHVybihsaXN0KGxhbWJkYSA9IGxhbWJkYSwgZGVsdGEgPSBkZWx0YSkpCn0KYGBgCgpgYGB7cn0KIyMgbmVnYXRpdmUgbG9nIGxpa2VsaWhvb2QgZnVuY3Rpb24KbmVnYUxvZ0wgPC0gZnVuY3Rpb24odGhldGEsIG5EaXN0LCB5KXsKICAgIGlmKG5EaXN0ID09IDEpewogICAgICAgIHJldHVybigtIHN1bShkcG9pcyh5LCBsYW1iZGEgPSBleHAodGhldGEpLCBsb2cgPSBUUlVFKSkpCiAgICB9CiAgICBldGEgPC0gdGhldGFbMTogbkRpc3RdCiAgICB0YXUgPC0gdGhldGFbKG5EaXN0ICsgMSk6ICgyICogbkRpc3QgLSAxKV0KICAgIG5hdHVyYWxQYXJzIDwtIHBvaXNNaXgucHcycG4obkRpc3QsIGV0YSwgdGF1KQogICAgbiA8LSBsZW5ndGgoeSkKICAgIG5sbCA8LSAwICAjIG5lZ2F0aXZlIGxvZyBsaWtlbGlob29kCiAgICBmb3IoaSBpbiAxOm4pewogICAgICAgIG5sbCA8LSBubGwgLSBsb2coc3VtKG5hdHVyYWxQYXJzJGRlbHRhICogCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBvaXMoeVtpXSwgbGFtYmRhID0gbmF0dXJhbFBhcnMkbGFtYmRhKSkpCiAgICB9CiAgICByZXR1cm4obmxsKQp9CmBgYAoKIyMgRXN0aW1hdGlvbiB3aXRoIG9uZSBkaXN0cmlidXRpb24KCmBgYHtyfQptX0hNTV9taXhfMSA8LSAxOyAjIyBObyBvZiBzdGF0ZXMKIyMgSW5pdGlhbCB2YWx1ZXMKbGFtYmRhX21peC4wXzEgPC0gbWVhbihkYXQkZWFydGhxdWFrZSk7IApkZWx0YV9taXguMF8xIDwtIGMoKQojIyBXb3JraW5nIHBhcmFtZXRlcnMKd29ya1BhcnNfbWl4XzEgPC0gcG9pc01peC5wbjJwdyhtX0hNTV9taXhfMSwgbGFtYmRhX21peC4wXzEsIGRlbHRhX21peC4wXzEpCnRoZXRhX21peC4wXzEgPC0gYyh3b3JrUGFyc19taXhfMSRldGEsIHdvcmtQYXJzX21peF8xJHRhdSkKIyMgTUxFCm9wdF9taXhfMSA8LSBubG1pbmIodGhldGFfbWl4LjBfMSwgbmVnYUxvZ0wsIG5EaXN0ID0gbV9ITU1fbWl4XzEsIHkgPSBkYXQkZWFydGhxdWFrZSkKc3ByaW50ZigiTWF4LUxpa2VsaWhvb2QgZXN0aW1hdGlvbiB3aXRoIG9uZSBkaXN0cmlidXRpb24iKQpwcmludChvcHRfbWl4XzEpCiMjIE5hdHVyYWwgcGFyYW1ldGVycwpuYXR1cmFsUGFyc19taXhfMSA8LSBwb2lzTWl4LnB3MnBuKG1fSE1NX21peF8xLCBvcHRfbWl4XzEkcGFyWzE6IG1fSE1NX21peF8xXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0X21peF8xJHBhclsobV9ITU1fbWl4XzEgKyAxKSA6ICgyICogbV9ITU1fbWl4XzEgLSAxKV0pCnNwcmludGYoIk5hdHVyYWwgcGFyYW1ldGVycyBieSBlc3RpbWF0aW9uIHdpdGggb25lIGRpc3RyaWJ1dGlvbiIpCnByaW50KG5hdHVyYWxQYXJzX21peF8xKQpgYGAKCiMjIEVzdGltYXRpb24gd2l0aCB0d28gZGlzdHJpYnV0aW9ucwoKYGBge3J9Cm1fSE1NX21peF8yIDwtIDI7ICMjIE5vIG9mIHN0YXRlcwojIyBJbml0aWFsIHZhbHVlcwpsYW1iZGFfbWl4LjBfMiA8LSBtZWFuKGRhdCRlYXJ0aHF1YWtlKSAqIGMoMS8yLCAzLzIpOwpkZWx0YV9taXguMF8yIDwtIGMoMC41KQojIyBXb3JraW5nIHBhcmFtZXRlcnMKd29ya1BhcnNfbWl4XzIgPC0gcG9pc01peC5wbjJwdyhtX0hNTV9taXhfMiwgbGFtYmRhX21peC4wXzIsIGRlbHRhX21peC4wXzIpCnRoZXRhX21peC4wXzIgPC0gYyh3b3JrUGFyc19taXhfMiRldGEsIHdvcmtQYXJzX21peF8yJHRhdSkKIyMgTUxFCm9wdF9taXhfMiA8LSBubG1pbmIodGhldGFfbWl4LjBfMiwgbmVnYUxvZ0wsIG5EaXN0ID0gbV9ITU1fbWl4XzIsIHkgPSBkYXQkZWFydGhxdWFrZSkKc3ByaW50ZigiTWF4LUxpa2VsaWhvb2QgZXN0aW1hdGlvbiB3aXRoIHR3byBkaXN0cmlidXRpb25zIikKcHJpbnQob3B0X21peF8yKQojIyBOYXR1cmFsIHBhcmFtZXRlcnMKbmF0dXJhbFBhcnNfbWl4XzIgPC0gcG9pc01peC5wdzJwbihtX0hNTV9taXhfMiwgb3B0X21peF8yJHBhclsxOiBtX0hNTV9taXhfMl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0X21peF8yJHBhclsobV9ITU1fbWl4XzIgKyAxKTogKDIgKiBtX0hNTV9taXhfMiAtIDEpXSkKc3ByaW50ZigiTmF0dXJhbCBwYXJhbWV0ZXJzIGJ5IGVzdGltYXRpb24gd2l0aCB0d28gZGlzdHJpYnV0aW9ucyIpCnByaW50KG5hdHVyYWxQYXJzX21peF8yKQpgYGAKCiMjIEVzdGltYXRpb24gd2l0aCAzIGRpc3RyaWJ1dGlvbnMKCmBgYHtyfQptX0hNTV9taXhfMyA8LSAzOwpsYW1iZGFfbWl4LjBfMyA8LSBtZWFuKGRhdCRlYXJ0aHF1YWtlKSAqIGMoMS8yLCAxLCAzLzIpOwpkZWx0YV9taXguMF8zIDwtIGMoMS8zLCAxLzMpCndvcmtQYXJzX21peF8zIDwtIHBvaXNNaXgucG4ycHcobV9ITU1fbWl4XzMsIGxhbWJkYV9taXguMF8zLCBkZWx0YV9taXguMF8zKQp0aGV0YV9taXguMF8zIDwtIGMod29ya1BhcnNfbWl4XzMkZXRhLCB3b3JrUGFyc19taXhfMyR0YXUpCm9wdF9taXhfMyA8LSBubG1pbmIodGhldGFfbWl4LjBfMywgbmVnYUxvZ0wsIG5EaXN0ID0gbV9ITU1fbWl4XzMsIHkgPSBkYXQkZWFydGhxdWFrZSkKc3ByaW50ZigiTWF4LUxpa2VsaWhvb2QgZXN0aW1hdGlvbiB3aXRoIHRocmVlIGRpc3RyaWJ1dGlvbnMiKQpwcmludChvcHRfbWl4XzMpCm5hdHVyYWxQYXJzX21peF8zIDwtIHBvaXNNaXgucHcycG4obV9ITU1fbWl4XzMsIG9wdF9taXhfMyRwYXJbMTogbV9ITU1fbWl4XzNdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdF9taXhfMyRwYXJbKG1fSE1NX21peF8zICsgMSk6ICgyICogbV9ITU1fbWl4XzMgLSAxKV0pCnNwcmludGYoIk5hdHVyYWwgcGFyYW1ldGVycyBieSBlc3RpbWF0aW9uIHdpdGggdGhyZWUgZGlzdHJpYnV0aW9ucyIpCnByaW50KG5hdHVyYWxQYXJzX21peF8zKQpgYGAKCiMjIEVzdGltYXRpb24gd2l0aCA0IGRpc3RyaWJ1dGlvbnMKCmBgYHtyfQptX0hNTV9taXhfNCA8LSA0OwpsYW1iZGFfbWl4LjBfNCA8LSBtZWFuKGRhdCRlYXJ0aHF1YWtlKSAqIGMoMS80LCAzLzQsIDUvNCwgNy80KTsKZGVsdGFfbWl4LjBfNCA8LSBjKDEsIDEsIDEpIC8gNAp3b3JrUGFyc19taXhfNCA8LSBwb2lzTWl4LnBuMnB3KG1fSE1NX21peF80LCBsYW1iZGFfbWl4LjBfNCwgZGVsdGFfbWl4LjBfNCkKdGhldGFfbWl4LjBfNCA8LSBjKHdvcmtQYXJzX21peF80JGV0YSwgd29ya1BhcnNfbWl4XzQkdGF1KQpvcHRfbWl4XzQgPC0gbmxtaW5iKHRoZXRhX21peC4wXzQsIG5lZ2FMb2dMLCBuRGlzdCA9IG1fSE1NX21peF80LCB5ID0gZGF0JGVhcnRocXVha2UpCnNwcmludGYoIk1heC1MaWtlbGlob29kIGVzdGltYXRpb24gd2l0aCBmb3VyIGRpc3RyaWJ1dGlvbnMiKQpwcmludChvcHRfbWl4XzQpCm5hdHVyYWxQYXJzX21peF80IDwtIHBvaXNNaXgucHcycG4obV9ITU1fbWl4XzQsIG9wdF9taXhfNCRwYXJbMTogbV9ITU1fbWl4XzRdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdF9taXhfNCRwYXJbKG1fSE1NX21peF80ICsgMSk6ICgyICogbV9ITU1fbWl4XzQgLSAxKV0pCnNwcmludGYoIk5hdHVyYWwgcGFyYW1ldGVycyBieSBlc3RpbWF0aW9uIHdpdGggZm91ciBkaXN0cmlidXRpb25zIikKcHJpbnQobmF0dXJhbFBhcnNfbWl4XzQpCmBgYAoKIyMgUGxvdCB0aGUgcmVzdWx0CgpgYGB7cn0KcGxvdChlYXJ0aHF1YWtlLnRhYmxlIC8gc3VtKGVhcnRocXVha2UudGFibGUpLCB4bGltID0gYygwLDQ1KSwgYXhlcyA9IEZBTFNFLAogICAgIHhsYWIgPSAiTnVtYmVyIiwgeWxhYiA9ICJEZW5zaXR5IiwgCiAgICAgbWFpbiA9ICJQb2lzc29uIE1peHR1cmUgTW9kZWwgZm9yIG51bWJlcnMgb2YgbWFqb3IgZWFydGhxdWFrZXMiKQpheGlzKDEpOyBheGlzKDIpCnggPC0gMDo0NQptaXhEaXN0IDwtIGZ1bmN0aW9uKHgsIG5hdHVyYWxQYXJzKXsKICAgICMjIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBtaXh0dXJlIGRpc3QKICAgIHN1bShuYXR1cmFsUGFycyRkZWx0YSAqIGRwb2lzKHgsIGxhbWJkYSA9IG5hdHVyYWxQYXJzJGxhbWJkYSkpCn0gIApsaW5lcyh4LCBkcG9pcyh4LCBsYW1iZGEgPSBuYXR1cmFsUGFyc19taXhfMSksIAogICAgICB0eXBlID0gImIiLCBjb2wgPSAxLCBwY2ggPSAxOSkKbGluZXMoeCwgc2FwcGx5KHgsIG1peERpc3QsIG5hdHVyYWxQYXJzID0gbmF0dXJhbFBhcnNfbWl4XzIpLCAKICAgICAgdHlwZSA9ICJiIiwgY29sID0gMiwgcGNoID0gMTkpCmxpbmVzKHgsIHNhcHBseSh4LCBtaXhEaXN0LCBuYXR1cmFsUGFycyA9IG5hdHVyYWxQYXJzX21peF8zKSwgCiAgICAgIHR5cGUgPSAiYiIsIGNvbCA9IDMsIHBjaCA9IDE5KQpsaW5lcyh4LCBzYXBwbHkoeCwgbWl4RGlzdCwgbmF0dXJhbFBhcnMgPW5hdHVyYWxQYXJzX21peF80KSwgCiAgICAgIHR5cGUgPSAiYiIsIGNvbCA9IDQsIHBjaCA9IDE5KQpsZWdlbmQoInRvcHJpZ2h0IiwgY29sID0gc2VxKDEsIDQpLCBsd2QgPSAyLCAKICAgICAgIGMoIjEgZGlzdHJpdHV0aW9uIiwgIjIgZGlzdHJpdHV0aW9ucyIsIAogICAgICAgICAiMyBkaXN0cml0dXRpb25zIiwgIjQgZGlzdHJpdHV0aW9ucyIpKQpgYGAKCiMjIENob29zZSB0aGUgbW9zdCBzdWl0YWJsZSBtb2RlbCB1c2luZyBBSUMKCmBgYHtyfQpBSUNfcG9pc01peCA8LSAyICogYyhvcHRfbWl4XzEkb2JqZWN0aXZlLCBvcHRfbWl4XzIkb2JqZWN0aXZlLAogICAgICAgICAgICAgICAgICAgICBvcHRfbWl4XzMkb2JqZWN0aXZlLCBvcHRfbWl4XzQkb2JqZWN0aXZlKSArCiAgICAgICAgICAgICAgIDIgKiBjKGxlbmd0aChvcHRfbWl4XzEkcGFyKSwgbGVuZ3RoKG9wdF9taXhfMiRwYXIpLAogICAgICAgICAgICAgICAgICAgICBsZW5ndGgob3B0X21peF8zJHBhciksIGxlbmd0aChvcHRfbWl4XzQkcGFyKSkKcHJpbnQoQUlDX3BvaXNNaXgpCmBgYApIZW5jZSB3ZSBjaG9vc2UgMy1zdGF0ZSBtb2RlbC4KCiMjIENob29zZSB0aGUgbW9zdCBzdWl0YWJsZSBtb2RlbCB1c2luZyBsaWtlbGlob29kIHJhdGlvIHRlc3QKCmBgYHtyfQoxIC0gcGNoaXNxKDIgKiAob3B0X21peF8xJG9iamVjdGl2ZSAtIG9wdF9taXhfMiRvYmplY3RpdmUpLAogICAgICAgICAgIGRmID0gbGVuZ3RoKG9wdF9taXhfMiRwYXIpLWxlbmd0aChvcHRfbWl4XzEkcGFyKSkKMSAtIHBjaGlzcSgyICogKG9wdF9taXhfMiRvYmplY3RpdmUgLSBvcHRfbWl4XzMkb2JqZWN0aXZlKSwKICAgICAgICAgICBkZj1sZW5ndGgob3B0X21peF8zJHBhciktbGVuZ3RoKG9wdF9taXhfMiRwYXIpKQoxIC0gcGNoaXNxKDIgKiAob3B0X21peF8zJG9iamVjdGl2ZSAtIG9wdF9taXhfNCRvYmplY3RpdmUpLAogICAgICAgICAgIGRmPWxlbmd0aChvcHRfbWl4XzQkcGFyKSAtIGxlbmd0aChvcHRfbWl4XzMkcGFyKSkKYGBgCkhlbmNlIHNhbWUgY29uY2x1c2lvbiBhcyBmb3IgQUlDLgoKIyBIaWRkZW4gTWFya292IE1vZGVsIGZvciBudW1iZXIgb2YgRWFydGhxdWFrZQoKYGBge3J9CnNvdXJjZSgiQTEuUiIpCnkgPC0gZGF0JGVhcnRocXVha2UKYGBgCgojIyBIaWRkZW4gTWFya292IE1vZGVsIHdpdGggMSBTdGF0ZSAKCmBgYHtyfQptX0hNTV8xIDwtIDEKbGFtYmRhX0hNTS4wXzEgPC0gbWVhbih5KQpnYW1tYV9ITU0uMF8xIDwtIDAKb3B0X0hNTV8xIDwtIHBvaXMuSE1NLm1sZSh5LCBtX0hNTV8xLCBsYW1iZGFfSE1NLjBfMSwgZ2FtbWFfSE1NLjBfMSkKYGBgCgojIyBIaWRkZW4gTWFya292IE1vZGVsIHdpdGggMiBTdGF0ZSAKCmBgYHtyfQptX0hNTV8yIDwtIDIKbGFtYmRhX0hNTS4wXzIgPC0gcXVhbnRpbGUoeSwgYygwLjI1LCAwLjc1KSkKZ2FtbWFfSE1NLjBfMiA8LSBtYXRyaXgoMC4wNSwgbmNvbCA9IG1fSE1NXzIsIG5yb3cgPSBtX0hNTV8yKQpkaWFnKGdhbW1hX0hNTS4wXzIpIDwtIDEgLSAobV9ITU1fMiAtIDEpICogZ2FtbWFfSE1NLjBfMlsxLDFdCm9wdF9ITU1fMiA8LSBwb2lzLkhNTS5tbGUoeSwgbV9ITU1fMiwgbGFtYmRhX0hNTS4wXzIsIGdhbW1hX0hNTS4wXzIpCmBgYAoKIyMgSGlkZGVuIE1hcmtvdiBNb2RlbCB3aXRoIDMgU3RhdGUgCgpgYGB7cn0KbV9ITU1fMyA8LSAzCmxhbWJkYV9ITU0uMF8zIDwtIHF1YW50aWxlKHksIGMoMC4yNSwgMC41LCAwLjc1KSkKZ2FtbWFfSE1NLjBfMyA8LSBtYXRyaXgoMC4wNSwgbmNvbCA9IG1fSE1NXzMsIG5yb3cgPSBtX0hNTV8zKQpkaWFnKGdhbW1hX0hNTS4wXzMpIDwtIDEgLSAobV9ITU1fMyAtIDEpICogZ2FtbWFfSE1NLjBfM1sxLCAxXQpvcHRfSE1NXzMgPC0gcG9pcy5ITU0ubWxlKHksIG1fSE1NXzMsIGxhbWJkYV9ITU0uMF8zLCBnYW1tYV9ITU0uMF8zKQpgYGAKCiMjIEhpZGRlbiBNYXJrb3YgTW9kZWwgd2l0aCA0IFN0YXRlIAoKYGBge3J9Cm1fSE1NXzQgPC0gNApsYW1iZGFfSE1NLjBfNCA8LSBxdWFudGlsZSh5LGMoMC4yLCAwLjQsIDAuNiwgMC44KSkKZ2FtbWFfSE1NLjBfNCA8LSBtYXRyaXgoMC4wMjUsIG5jb2wgPSBtX0hNTV80LCBucm93ID0gbV9ITU1fNCkKZGlhZyhnYW1tYV9ITU0uMF80KSA8LSAxIC0gKG1fSE1NXzQgLSAxKSAqIGdhbW1hX0hNTS4wXzRbMSwgMV0Kb3B0X0hNTV80IDwtIHBvaXMuSE1NLm1sZSh5LCBtX0hNTV80LCBsYW1iZGFfSE1NLjBfNCwgZ2FtbWFfSE1NLjBfNCkKYGBgCgojIyBBSUMKCmBgYHtyfQpBSUNfSE1NIDwtIGMob3B0X0hNTV8xJEFJQywgb3B0X0hNTV8yJEFJQywgb3B0X0hNTV8zJEFJQywgb3B0X0hNTV80JEFJQykKbG9nTF9ITU0gPC0gLWMob3B0X0hNTV8xJG1sbGssIG9wdF9ITU1fMiRtbGxrLCBvcHRfSE1NXzMkbWxsaywgb3B0X0hNTV80JG1sbGspCm1fSE1NX0hNTSA8LSBjKDEsIDIsIDMsIDQpCmRmX0hNTSA8LSBtX0hNTV9ITU0gKyAobV9ITU1fSE1NXjIgLSBtX0hNTV9ITU0pICAjIGxhbWJkYSArIGdhbW1hCmNiaW5kKGRmX0hNTSwgbG9nTF9ITU0sIEFJQ19ITU0pCmBgYApTbyB3ZSBjaG9vc2UgSE1NIHdpdGggMyBzdGF0ZXMuCgojIAoKCmBgYHtyfQojIyBGaW5kaW5nIHRoZSBzdGFuZGFyZCBlcnJvcnMKbV9ITU0gPC0gMwojIyB3b3JraW5nIHBhcmFtZXRlcnMKcGFydHNXb3JrX0hNTSAgPC0gcG9pcy5ITU0ucG4ycHcobV9ITU0sIG9wdF9ITU1fMyRsYW1iZGEsIG9wdF9ITU1fMyRnYW1tYSkKbW9kX0hNTSA8LSBubG0ocG9pcy5ITU0ubWxsaywgcGFydHNXb3JrX0hNTSwgeCA9IHksIG0gPSBtX0hNTSwgaGVzc2lhbiA9IFRSVUUpICAKIyMgT3JnYW5pemUgdGhlIHJlc3VsdApwYXJ0c1dvcmsubmxtX0hNTSA8LSBtb2RfSE1NJGVzdGltYXRlCm5hbWVzKHBhcnRzV29yay5ubG1fSE1NKSA8LSBjKCJsYW1iZGExIiwgImxhbWJkYTIiLCAibGFtYmRhMyIsICJ0YXUyMSIsICJ0YXUzMSIsICJ0YXUxMiIsICJ0YXUzMiIsICJ0YXUxMyIsICJ0YXUyMyIpCnNlX0hNTSA8LSBzcXJ0KGRpYWcoc29sdmUobW9kX0hNTSRoZXNzaWFuKSkpCgojIyBXb3JraW5nIHBhcnMgKyBzdGFuZGFyZCBlcnJvcgpyb3VuZChjYmluZChwYXJ0c1dvcmsubmxtX0hNTSwgc2VfSE1NKSwgZGlnaXRzID0gMikKb3B0X0hNTV8zJGdhbW1hCmBgYAoKIyMgUGFyYW1ldHJpYyBib290c3RyYXAKCmBgYHtyfQpzb3VyY2UoIkEyLlIiKQojIyBJbml0YWlsaXplCm4gPC0gbGVuZ3RoKHkpCmsgPC0gMTAwCm0gPC0gMwpsYW1iZGEwIDwtIHF1YW50aWxlKHksIGMoMC4yNSwgMC41LCAwLjc1KSkKZ2FtbWEwIDwtIG1hdHJpeCgwLjAyNSwgbmNvbCA9IG0sIG5yb3cgPSBtKQpkaWFnKGdhbW1hMCkgPC0gMSAtIChtIC0gMSkgKiBnYW1tYTBbMSwxXQoKIyMgTWF0cmljZXMgdG8gc3RvcmVzIGJvb3RzdGFwIHJlc3VsdApHQU1NQSA8LSBtYXRyaXgobmNvbCA9IG0gKiBtLCBucm93ID0gaykKTGFtYmRhIDwtIG1hdHJpeChuY29sID0gbSwgbnJvdyA9IGspCkRlbHRhIDwtIG1hdHJpeChuY29sID0gbSwgbnJvdyA9IGspCkNvZGUgPC0gbnVtZXJpYyhrKQoKIyMgQm9vdCBzdHJhcCB3aXRoIHR3byBkaWZmZXJlbnQgb3B0aW1pemVycwpmb3IoaSBpbiAxOmspewogICAgc2V0LnNlZWQoaSkKICAgICMjIGdlbmVyYXRlIHNhbXBsZQogICAgeS5zaW0gPC0gcG9pcy5ITU0uZ2VuZXJhdGVfc2FtcGxlKG4sIG0sIG9wdF9ITU1fMyRsYW1iZGEsIG9wdF9ITU1fMyRnYW1tYSkKICAgICMjIGZpdCBtb2RlbCB0byBzYW1wbGUKICAgIG9wdF9ITU1fMy50bXAgPC0gcG9pcy5ITU0ubWxlKHkuc2ltLCBtLCBsYW1iZGEwLCBnYW1tYTApCiAgICAjIyBTdG9yZSByZXN1bHQKICAgIEdBTU1BW2ksIF0gPC0gYyhvcHRfSE1NXzMudG1wJGdhbW1hWzEsIF0sCiAgICAgICAgICAgICAgICAgICAgb3B0X0hNTV8zLnRtcCRnYW1tYVsyLCBdLAogICAgICAgICAgICAgICAgICAgIG9wdF9ITU1fMy50bXAkZ2FtbWFbMywgXSkKICAgIExhbWJkYVtpLCBdIDwtIG9wdF9ITU1fMy50bXAkbGFtYmRhCiAgICBEZWx0YVtpLCBdIDwtIG9wdF9ITU1fMy50bXAkZGVsdGEKICAgIENvZGVbaV0gPC0gb3B0X0hNTV8zLnRtcCRjb2RlCiAgICBwcmludChjKGksQ29kZVtpXSkpCn0Kc3VtKENvZGUhPTEpCgojIyBTYW1lIGFzIGFib3ZlIHdpdGggZGlmZmVyZW50IG9wdGltaXplcgpmb3IoaSBpbiAxOmspewogICAgc2V0LnNlZWQoaSkKICAgIHkuc2ltIDwtIHBvaXMuSE1NLmdlbmVyYXRlX3NhbXBsZShuLCBtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdF9ITU1fMyRsYW1iZGEsIG9wdF9ITU1fMyRnYW1tYSkKICAgIGxhbWJkYTAgPC0gcXVhbnRpbGUoeS5zaW0sYygwLjI1LDAuNSwwLjc1KSkKICAgIG9wdF9ITU1fMy50bXAgPC0gcG9pcy5ITU0ubWxlLm5sbWluYih5LnNpbSwgbSxsYW1iZGEwLCBnYW1tYTApCiAgICBHQU1NQVtpLCBdIDwtIGMob3B0X0hNTV8zLnRtcCRnYW1tYVsxLCBdLAogICAgICAgICAgICAgICAgICAgIG9wdF9ITU1fMy50bXAkZ2FtbWFbMiwgXSwKICAgICAgICAgICAgICAgICAgICBvcHRfSE1NXzMudG1wJGdhbW1hWzMsIF0pCiAgICBMYW1iZGFbaSwgXSA8LSBvcHRfSE1NXzMudG1wJGxhbWJkYQogICAgRGVsdGFbaSwgXSA8LSBvcHRfSE1NXzMudG1wJGRlbHRhCiAgICBDb2RlW2ldIDwtIG9wdF9ITU1fMy50bXAkY29kZQogICAgcHJpbnQoYyhpLENvZGVbaV0pKQp9CnN1bShDb2RlIT0wKQoKIyMgUGxvdCB0aGUgcmVzdWx0cyAoaS5lLiBzdGF0aXN0aWNhbCBkaXN0cmlidXRpb24gb2YKIyMgZXN0aW1hdGVzCnBhcihtZnJvdyA9IGMoMSwzKSkKaGlzdChMYW1iZGFbICwxXSkKcnVnKG9wdF9ITU1fMyRsYW1iZGEsIGx3ZCA9IDIsIGNvbCA9IDIpCmhpc3QoTGFtYmRhWyAsMl0pCnJ1ZyhvcHRfSE1NXzMkbGFtYmRhLCBsd2QgPSAyLCBjb2wgPSAyKQpoaXN0KExhbWJkYVsgLDNdKQpydWcob3B0X0hNTV8zJGxhbWJkYSwgbHdkID0gMiwgY29sID0gMikKYGBgCgo=