Modify the given hard-coded Proxel-program to simulate the above Petri net.

Über den Code-Button rechts unter dem Text ist der gegebene Code einsehbar, welcher nach meinem besten Wissen überarbeitet und an die gegebene Aufgabe angepasst wurde.

MINPROB <- 1.0e-12
STAGE1 <- 1
STAGE2 <- 2
STAGE3 <- 3
HEALTHY <- 4
DELTA <- c(2, 1, 0.5, 0.25, 0.1)
ENDTIME <- 13
PI <- 3.1415926

setClass("Proxel",representation = list(id = "numeric", s = "numeric", tau1k = "numeric", tau2k = "numeric", val = "numeric", left = "Proxel", right = "Proxel"
  ))
Proxel <- function() {
  list(
    id = 0,
    s = 0,
    tau1k = 0,
    tau2k = 0,
    val = 0.0,
    left = NULL,
    right = NULL
  )
}

y <- list(NULL, NULL, NULL, NULL)
tmax <- 0.0
TAUMAX <- 0
totcnt <- 0
maxccp <- 0
ccpcnt <- 0
root <- list(NULL, NULL)
firstfree <- NULL
eerror <- 0
sw <- 0
len <- 0
dt <- 0

unihrf <- function(x, a, b) {
  if (a <= x && x < b) {
    return (1.0 / (b - x))
  } else {
    return (0)
  }
}

exphrf <- function(x, l) {
  return (l)
}

printtree <- function(p) {
  if (is.null(p)) {
    return
  }
  cat("s", p$s, "t1", p$tau1k, "t2", p$tau2k, "val", p$val, "\n")
  printtree(p$left)
  printtree(p$right)
}

plotsolution <- function(kmax) {
  cat("\n\n")
  for (k in 1:(kmax + 1)) {
    cat(sprintf("%.5f\t%.5e\t%.5e\t%.5e\t%.5e\n", k * dt, y[[1]][k], y[[2]][k], y[[3]][k], y[[4]][k]))
  }
}

printproxel <- function(c) {
  cat("processing", c$s, c$tau1k, c$val, "\n")
}

state2id <- function(s, t1k, t2k) {
  return (TAUMAX * (TAUMAX * s + t1k) + t2k)
}

size <- function(p) {
  if (is.null(p)) {
    return (0)
  }
  sl <- size(p$left)
  sr <- size(p$right)
  return (sl + sr + 1)
}

getproxel <- function() {
  LEFT <- 0
  RIGHT <- 1
  dir <- 1
  cont <- 1

  if (is.null(root[[1 - sw+1]])) {
    return(NULL)
  }

  temp <- root[[1 - sw+1]]
  old <- temp

  while (cont == 1) {
    if (!is.null(temp$right) && is.null(temp$left)) {
      old <- temp
      temp <- temp$right
      dir <- RIGHT
    } else if (is.null(temp$right) && !is.null(temp$left)) {
      old <- temp
      temp <- temp$left
      dir <- LEFT
    } else if (!is.null(temp$right) && !is.null(temp$left)) {
      if (runif(1) > 0.5) {
        old <- temp
        temp <- temp$left
        dir <- LEFT
      } else {
        old <- temp
        temp <- temp$right
        dir <- RIGHT
      }
    } else {
      cont <- 0
    }
  }

  if (identical(temp, root[[1 - sw+1]])) {
    root[[1 - sw+1]] <- NULL
  } else {
    if (dir == RIGHT) {
      old$right <- NULL
    } else {
      old$left <- NULL
    }
  }

  old <- firstfree
  firstfree <- temp
  temp$right <- old
  ccpcnt <- ccpcnt - 1
  return(temp)
}

insertproxel <- function(s, tau1k, tau2k, val) {
  if (is.null(firstfree)) {
    temp <- Proxel()
  } else {
    temp <- firstfree
    firstfree <- firstfree$right
  }

  temp$id <- state2id(s, tau1k, tau2k)
  temp$s <- s
  temp$tau1k <- tau1k
  temp$tau2k <- tau2k
  temp$val <- val
  ccpcnt <- ccpcnt + 1

  if (maxccp < ccpcnt) {
    maxccp <- ccpcnt
  }

  return(temp)
}

addproxel <- function(s, tau1k, tau2k, val) {
  temp <- NULL
  temp2 <- NULL
  cont <- 1
  id <- state2id(s, tau1k, tau2k)

  if (tau1k >= TAUMAX) {
    tau1k <- TAUMAX - 1
  }
  if (is.null(root[[sw+1]])) {
    root[[sw+1]] <- insertproxel(s, tau1k, tau2k, val)
    root[[sw+1]]$left <- NULL
    root[[sw+1]]$right <- NULL
    return(NULL)
  }

  temp <- root[[sw+1]]

  while (cont == 1) {
    if (!is.null(temp$left) && id < temp$id) {
      temp <- temp$left
    } else if (!is.null(temp$right) && id > temp$id) {
      temp <- temp$right
    } else {
      cont <- 0
    }
  }

  if (is.null(temp$left) && id < temp$id) {
    temp2 <- insertproxel(s, tau1k, tau2k, val)
    temp$left <- temp2
    temp2$left <- NULL
    temp2$right <- NULL
  } else if (is.null(temp$right) && id > temp$id) {
    temp2 <- insertproxel(s, tau1k, tau2k, val)
    temp$right <- temp2
    temp2$left <- NULL
    temp2$right <- NULL
  } else if (id == temp$id) {
    temp$val <- temp$val + val
  } else {
    cat("\n\n\n!!!!!! addproxel failed !!!!!\n\n\n")
  }
}

incubation <- function(age) {
  return (unihrf(age, 2, 4))
}

get_worse <- function(age) {
  return (exphrf(age, 1/10))
}

heal <- function(age) {
  return (unihrf(age, 7, 14))
}

main <- function() {
  root <- list(NULL, NULL)
  eerror <- 0.0
  totcnt <- 0
  maxccp <- 0
  tmax <- ENDTIME
  dt <- DELTA[2]
  kmax <- as.integer(tmax / dt) + 1

  for (k in 1:4) {
    y[[k]] <- rep(0.0, kmax + 2)
  }

  TAUMAX <- as.integer(tmax / dt) + 1

  addproxel(STAGE1, 0, 0, 1.0)

  for (k in 2:(kmax + 2)) {
    if (k %% 100 == 0) {
      cat("\nSTEP", k, "\n")
      cat("Size of tree", size(root[[sw+1]]), "\n")
    }

    while (!is.null(root[[1 - sw+1]])) {
      totcnt <- totcnt + 1
      currproxel <- getproxel()

      while (currproxel$val < MINPROB && !is.null(root[[1 - sw+1]])) {
        val <- currproxel$val
        eerror <- eerror + val
        currproxel <- getproxel()
      }

      val <- currproxel$val
      tau1k <- currproxel$tau1k
      tau2k <- currproxel$tau2k
      s <- currproxel$s
      y[[s]][k - 1] <- y[[s]][k - 1] + val

      if (s == STAGE1) {
        z <- dt * incubation(tau1k * dt)
        z2 <- dt * heal(tau2k * dt)
        if (z2 < 1.0) {
          if (z < 1.0) {
            addproxel(STAGE2, 0, tau2k + 1, val * z)
            addproxel(STAGE1, tau1k + 1, tau2k + 1, val * (1 - z - z2))
            addproxel(HEALTHY, 0, 0, val * (z2))
          } else {
            addproxel(STAGE2, 0, tau2k + 1, val)
          }
        } else {
          addproxel(HEALTHY, 0, 0, val)
        }
      } else if (s == STAGE2) {
        z <- dt * get_worse(tau1k * dt)
        z2 <- dt * heal(tau2k * dt)
        if (z2 < 1.0) {
          if (z < 1.0) {
            addproxel(STAGE3, 0, tau2k + 1, val * z)
            addproxel(STAGE2, tau1k + 1, tau2k + 1, val * (1 - z - z2))
            addproxel(HEALTHY, 0, 0, val * (z2))
          } else {
            addproxel(STAGE3, 0, tau2k + 1, val)
          }
        } else {
          addproxel(HEALTHY, 0, 0, val)
        }
      } else if (s == STAGE3) {
        z <- dt * heal(tau2k * dt)
        if (z < 1.0) {
          addproxel(HEALTHY, 0, 0, val * z)
          addproxel(STAGE3, tau1k + 1, tau2k + 1, val * (1 - z))
        } else {
          addproxel(HEALTHY, 0, 0, val)
        }
      } else if (s == HEALTHY) {
        addproxel(HEALTHY, tau1k + 1, tau2k + 1, 1)
      }
    }
    if (sw==0) sw=1
    if (sw==1) sw=0
  }

  #cat("\n\n")
  #cat("error =", sprintf("%.5e", eerror), "\n")
  #cat("ccpx =", maxccp, "\n")
  #cat("count =", totcnt, "\n")
  #plotsolution(kmax)
}

main()

Da R einige Unterschiede in der Programmierung zu C oder vergleichbaren Sprachen hat (z.B. zählweise startend bei 1 anstatt 0), war es für mich an der Stelle realistischer selbst ein Proxel-Programm zu schreiben, als wochenlang nach Kleinigkeiten in den Fehlern zu suchen. Dieser Code ist über den nächsten Button einsehbar.

max.ts = 15
delta = 1
startproxel=c(1,0,0,1,0)
RG=matrix(c(1,1,0,1,
            0,1,1,1,
            0,0,1,1,
            0,0,0,1),ncol = 4,byrow = T)

Proxel_algo=function(RG,startproxel,delta,max.ts,Print=T){
  
unihrf <- function(age, a, b) {
  if (a <= age && age < b) {
    return (1.0 / (b - age))
  } else {
    return (0)
  }
}

exphrf <- function(age, l) {
  return (l)
}
  
proxel_list=list()
proxel_list[[max.ts+1]]=list()
proxel_list[[1]]=list(STEP=c(0),proxel=data.frame(state=startproxel[1],tau=startproxel[2],tau_k=startproxel[3],prob=startproxel[4],prev=startproxel[5]))
if(Print) print("initial proxel:")
if(Print) print(proxel_list[[1]])

for (timestep in 1:max.ts) {
  proxel_list[[timestep+1]]=list(timestep=c(timestep),proxel=data.frame(state=numeric(),tau=numeric(),tau_k=numeric(),prob=numeric(),prev=numeric()))     # erstelle schonmal eine neue leere liste für den nächsten timestep
  
  for (l in 1:nrow(proxel_list[[timestep]]$proxel)) {
    currprox = proxel_list[[timestep]]$proxel[l,] # aktueller proxel zu dem folgeproxels erzeugt werden sollen
    folger = RG[as.numeric(currprox[1]),]         # folgestates von aktuellem proxel
    
    for (i in 1:4) {
      if (folger[i]==1) {     # erstelle folgeproxel falls pfeil dahin gibt
        proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel)+1,1] = i                         # state vom nächsten proxel
        
        if(currprox$state==i) proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),2] = currprox$tau + delta
          else proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),2] = 0                    # tau vom nächsten proxel
        
        if(currprox$state %in% c(1,2,3) & i!=4) proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),3] = currprox$tau_k + delta
          else if(currprox$state==4 & i==4) proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),3] = currprox$tau_k - delta
            else proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),3] = 0                   # tau_k vom nächsten proxel
          
        if(currprox$state==1 & i==2) {
          proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),4] = (unihrf(currprox$tau_k,2,4) * delta) * currprox$prob}                 # transition von S1 zu S2
        if(currprox$state==2 & i==3) {
          proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),4] = (exphrf(currprox$tau_k,0.1) * delta) * currprox$prob}                 # transition von S2 zu S3
        if(currprox$state!=4 & i==4) {
          proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),4] = (unihrf(currprox$tau_k,7,14)* delta) * currprox$prob}                 # transtion zu heal von S1,S2 oder S3
        if(currprox$state==1 & i==1) {
          proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),4] = (1 - (unihrf(currprox$tau_k,2,4) * delta) - (unihrf(currprox$tau_k,7,14)* delta)) * currprox$prob}
        if(currprox$state==2 & i==2) {
          proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),4] = (1 - (exphrf(currprox$tau_k,0.1) * delta) - (unihrf(currprox$tau_k,7,14)* delta)) * currprox$prob}
        if(currprox$state==3 & i==3) {
          proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),4] = (1 - (unihrf(currprox$tau_k,7,14)* delta)) * currprox$prob}
        if(currprox$state==4 & i==4) {
          proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),4] = 1 }
            
         proxel_list[[timestep+1]]$proxel[nrow(proxel_list[[timestep+1]]$proxel),5] = l   
            
      }
    } 
  }
  if(length(which(proxel_list[[timestep+1]]$proxel[,4]<=0))!=0) proxel_list[[timestep+1]]$proxel=proxel_list[[timestep+1]]$proxel[-which(proxel_list[[timestep+1]]$proxel[,4]<=0),]
  if(length(which(proxel_list[[timestep+1]]$proxel[,3]< 0))!=0) proxel_list[[timestep+1]]$proxel=proxel_list[[timestep+1]]$proxel[-which(proxel_list[[timestep+1]]$proxel[,3]< 0),]
  
  if(Print) print(paste("Time step:",timestep))
  if(Print) print(proxel_list[[timestep+1]])
}

return(proxel_list)
}
proxel_list=Proxel_algo(RG,startproxel,delta,max.ts,F)
#proxel_list

What is the probability that the patient is still sick after 8 days for different discrete time steps (e.g. 2, 1, 0.5, 0.25, 0.1)?

P2=Proxel_algo(RG,startproxel,2,8,F)
P1=Proxel_algo(RG,startproxel,1,15,F)
P05=Proxel_algo(RG,startproxel,0.5,29,F)
P025=Proxel_algo(RG,startproxel,0.25,57,F)
P01=Proxel_algo(RG,startproxel,0.1,82,F)
#P2[[5]]   
#P1[[9]]   
#P05[[17]] 
#P025[[33]]
#P01[[81]] 

sum(P2[[5]]$proxel$prob[P2[[5]]$proxel$state != 4])
sum(P1[[9]]$proxel$prob[P1[[9]]$proxel$state != 4])
sum(P05[[17]]$proxel$prob[P05[[17]]$proxel$state != 4])
sum(P025[[33]]$proxel$prob[P025[[33]]$proxel$state != 4])
sum(P01[[81]]$proxel$prob[P01[[81]]$proxel$state != 4])

What is the probability of measuring fever on the 9th day for different discrete time steps (e.g. 2, 1, 0.5, 0.25, 0.1)?

paste("Wkt =",sum(aggregate.data.frame(P2[[5]]$proxel$prob,by=list(P2[[5]]$proxel$state),FUN = sum)$x *c(0.5,0.8)))
paste("Wkt =",sum(aggregate.data.frame(P1[[9]]$proxel$prob,by=list(P1[[9]]$proxel$state),FUN = sum)$x *c(0.5,0.8,0)))
paste("Wkt =",sum(aggregate.data.frame(P05[[17]]$proxel$prob,by=list(P05[[17]]$proxel$state),FUN = sum)$x *c(0.5,0.8,0)))
paste("Wkt =",sum(aggregate.data.frame(P025[[33]]$proxel$prob,by=list(P025[[33]]$proxel$state),FUN = sum)$x *c(0.5,0.8,0)))
paste("Wkt =",sum(aggregate.data.frame(P01[[81]]$proxel$prob,by=list(P01[[81]]$proxel$state),FUN = sum)$x *c(0.5,0.8,0)))

What is the expected duration until healing with probability 99% for different discrete time steps (e.g. 2, 1, 0.5, 0.25, 0.1)?

i=7
#while (sum(P2[[i]]$proxel$prob[P2[[i]]$proxel$state != 4]) > 0.01 ) i=i+1
P2[[8]]$proxel[P2[[8]]$proxel$state != 4,]
print(paste("Für 2 An Tag:",(i-1)*2)) ## nach Tag 14

i=1
while (sum(P1[[i]]$proxel$prob[P1[[i]]$proxel$state != 4]) > 0.01 ) i=i+1
P1[[i]]$proxel[P1[[i]]$proxel$state != 4,]
print(paste("Für 1 An Tag:",(i-1)*1))

i=1
while (sum(P05[[i]]$proxel$prob[P05[[i]]$proxel$state != 4]) > 0.01 ) i=i+1
P05[[i]]$proxel[P05[[i]]$proxel$state != 4,]
print(paste("Für .5 An Tag:",(i-1)*0.5))

i=1
while (sum(P025[[i]]$proxel$prob[P025[[i]]$proxel$state != 4]) > 0.01 ) i=i+1
P025[[i]]$proxel[P025[[i]]$proxel$state != 4,]
print(paste("Für .25 An Tag:",(i-1)*0.25))
LS0tDQp0aXRsZTogIkFETSBBc3NpZ25tZW50IDQiDQphdXRob3I6ICJEb21pbmlrIERpZWRyaWNoIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZSANCi0tLQ0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShwZXRyaW5ldFIpDQpsaWJyYXJ5KG1hcmtvdmNoYWluKQ0KYGBgDQoNCmBgYHtyIG1vZGlmaWVkIFYxLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KIyBTcGVjaWFsIFB1cnBvc2UgUHJveGVsLUJhc2VkIFNvbHZlcg0KDQpNSU5QUk9CIDwtIDEuMGUtMTINClMxIDwtIDANClMyIDwtIDINClMzIDwtIDQNCkggPC0gIDYNCkRFTFRBIDwtIDENCkVORFRJTUUgPC0gNTANClBJIDwtIDMuMTQxNTkyNg0KDQojIERlZmluaXRpb24gb2YgYSBwcm94ZWwgc3RydWN0dXJlDQpwcm94ZWwgPC0gZnVuY3Rpb24oaWQsIHMsIHRhdTFrLCB0YXUyaywgdmFsLCBsZWZ0ID0gTlVMTCwgcmlnaHQgPSBOVUxMKSB7DQogIGxpc3QoaWQgPSBpZCwgcyA9IHMsIHRhdTFrID0gdGF1MWssIHRhdTJrID0gdGF1MmssIHZhbCA9IHZhbCwgbGVmdCA9IGxlZnQsIHJpZ2h0ID0gcmlnaHQpDQp9DQoNCnkgPC0gdmVjdG9yKCJsaXN0IiwgNCkNCnRtYXggPC0gRU5EVElNRQ0KVEFVTUFYIDwtIHRtYXggLyBERUxUQQ0KdG90Y250IDwtIDANCm1heGNjcCA8LSAwDQpjY3BjbnQgPC0gMA0Kcm9vdCA8LSB2ZWN0b3IoImxpc3QiLCAyKQ0KZmlyc3RmcmVlIDwtIE5VTEwNCmVlcnJvciA8LSAwDQpzdyA8LSAxDQpsZW4gPC0gMA0KZHQgPC0gREVMVEENCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIGRpc3RyaWJ1dGlvbnMgIyMjIyMjIyMjIyMjIyMjDQojIHVuaWZvcm0gSVJGDQp1bmlocmYgPC0gZnVuY3Rpb24oeCwgYSwgYikgew0KICBpZiAoeCA+PSBhICYmIHggPCBiKSB7DQogICAgeSA8LSAxLjAgLyAoYiAtIHgpDQogIH0gZWxzZSB7DQogICAgeSA8LSAwLjANCiAgfQ0KDQogIHJldHVybih5KQ0KfQ0KDQojIGV4cG9uZW50aWFsIElSRg0KZXhwaHJmIDwtIGZ1bmN0aW9uKHgsIGwpIHsNCiAgcmV0dXJuKGwpDQp9DQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBvdXRwdXQgZnVuY3Rpb25zICMjIyMjIyMjIyMjIyMjDQojIFByaW50IGFsbCBwcm94ZWxzIGluIHRyZWUNCnByaW50dHJlZSA8LSBmdW5jdGlvbihwKSB7DQogIGlmIChpcy5udWxsKHApKQ0KICAgIHJldHVybg0KICBjYXQoInMiLCBwJHMsICJ0MSIsIHAkdGF1MWssICJ0MiIsIHAkdGF1MmssICJ2YWwiLCBwJHZhbCwgIlxuIikNCiAgcHJpbnR0cmVlKHAkbGVmdCkNCiAgcHJpbnR0cmVlKHAkcmlnaHQpDQp9DQoNCiMgUHJpbnQgb3V0IGNvbXBsZXRlIHNvbHV0aW9uDQpwbG90c29sdXRpb24gPC0gZnVuY3Rpb24oa21heCkgew0KICBjYXQoIlxuXG4iKQ0KICBmb3IgKGsgaW4gMTooa21heCArIDEpKQ0KICAgIGNhdChmb3JtYXQoayAqIGR0LCBkaWdpdHMgPSA3KSwgIlx0IiwgZm9ybWF0KHlbWzFdXVtrXSwgc2NpZW50aWZpYyA9IFRSVUUsIGRpZ2l0cyA9IDcpLCAiXHQiLCBmb3JtYXQoeVtbM11dW2tdLCBzY2llbnRpZmljID0gVFJVRSwgZGlnaXRzID0gNyksICJcbiIpDQp9DQoNCiMgUHJpbnQgb3V0IGEgcHJveGVsDQpwcmludHByb3hlbCA8LSBmdW5jdGlvbihjKSB7DQogIGNhdCgicHJvY2Vzc2luZyIsIGMkcywgYyR0YXUxaywgYyR2YWwsICJcbiIpDQp9DQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHByb3hlbCBtYW5pcHVsYXRpb24gZnVuY3Rpb24gIyMjIyMjIyMjDQojIENvbXB1dGUgdW5pcXVlIGlkIGZyb20gcHJveGVsIHN0YXRlDQpzdGF0ZTJpZCA8LSBmdW5jdGlvbihzLCB0MWssIHQyaykgew0KICBUQVVNQVggKiAoVEFVTUFYICogcyArIHQxaykgKyB0MmsNCn0NCg0KIyBDb21wdXRlIHNpemUgb2YgdHJlZQ0Kc2l6ZSA8LSBmdW5jdGlvbihwKSB7DQogIGlmIChpcy5udWxsKHApKQ0KICAgIHJldHVybigwKQ0KICBzbCA8LSBzaXplKHAkbGVmdCkNCiAgc3IgPC0gc2l6ZShwJHJpZ2h0KQ0KICBzbCArIHNyICsgMQ0KfQ0KDQojIEdldCBhIHByb3hlbCBmcm9tIHRoZSB0cmVlDQpnZXRwcm94ZWwgPC0gZnVuY3Rpb24oKSB7DQogIHRlbXAgPC0gcm9vdFtbMSAtIHN3XV0NCiAgb2xkIDwtIHRlbXANCg0KICAjIE1vdmUgZG93biB0aGUgdHJlZSB0byBhIGxlYWYNCiAgd2hpbGUgKCFpcy5udWxsKHRlbXApKSB7DQogICAgIyBHbyByaWdodA0KICAgIGlmICghaXMubnVsbCh0ZW1wJHJpZ2h0KSAmJiBpcy5udWxsKHRlbXAkbGVmdCkpIHsNCiAgICAgIG9sZCA8LSB0ZW1wDQogICAgICB0ZW1wIDwtIHRlbXAkcmlnaHQNCiAgICB9DQogICAgIyBHbyBsZWZ0DQogICAgZWxzZSBpZiAoaXMubnVsbCh0ZW1wJHJpZ2h0KSAmJiAhaXMubnVsbCh0ZW1wJGxlZnQpKSB7DQogICAgICBvbGQgPC0gdGVtcA0KICAgICAgdGVtcCA8LSB0ZW1wJGxlZnQNCiAgICB9DQogICAgIyBDaG9vc2UgcmlnaHQvbGVmdCBhdCByYW5kb20NCiAgICBlbHNlIGlmICghaXMubnVsbCh0ZW1wJHJpZ2h0KSAmJiAhaXMubnVsbCh0ZW1wJGxlZnQpKSB7DQogICAgICBpZiAocnVuaWYoMSkgPiAwLjUpIHsNCiAgICAgICAgb2xkIDwtIHRlbXANCiAgICAgICAgdGVtcCA8LSB0ZW1wJGxlZnQNCiAgICAgIH0gZWxzZSB7DQogICAgICAgIG9sZCA8LSB0ZW1wDQogICAgICAgIHRlbXAgPC0gdGVtcCRyaWdodA0KICAgICAgfQ0KICAgIH0gZWxzZQ0KICAgICAgYnJlYWsNCiAgfQ0KDQogIGlmIChpZGVudGljYWwodGVtcCwgcm9vdFtbMSAtIHN3XV0pKQ0KICAgIHJvb3RbWzEgLSBzd11dIDwtIE5VTEwNCiAgZWxzZSB7DQogICAgaWYgKCFpcy5udWxsKHRlbXAkcmlnaHQpKQ0KICAgICAgb2xkJHJpZ2h0IDwtIE5VTEwNCiAgICBlbHNlDQogICAgICBvbGQkbGVmdCA8LSBOVUxMDQogIH0NCg0KICBvbGQgPC0gZmlyc3RmcmVlDQogIGZpcnN0ZnJlZSA8PC0gdGVtcA0KICB0ZW1wJHJpZ2h0IDwtIG9sZA0KICBjY3BjbnQgPDwtIGNjcGNudCAtIDENCg0KICByZXR1cm4odGVtcCkNCn0NCg0KIyBHZXQgYSBmcmVzaCBwcm94ZWwgYW5kIGNvcHkgZGF0YSBpbnRvIGl0DQppbnNlcnRwcm94ZWwgPC0gZnVuY3Rpb24ocywgdGF1MWssIHRhdTJrLCB2YWwpIHsNCiAgdGVtcCA8LSBwcm94ZWwoc3RhdGUyaWQocywgdGF1MWssIHRhdTJrKSwgcywgdGF1MWssIHRhdTJrLCB2YWwpDQogIGNjcGNudCA8PC0gY2NwY250ICsgMQ0KDQogIGlmIChtYXhjY3AgPCBjY3BjbnQpDQogICAgbWF4Y2NwIDw8LSBjY3BjbnQNCg0KICByZXR1cm4odGVtcCkNCn0NCg0KIyBBZGRzIGEgbmV3IHByb3hlbCB0byB0aGUgdHJlZQ0KYWRkcHJveGVsIDwtIGZ1bmN0aW9uKHMsIHRhdTFrLCB0YXUyaywgdmFsKSB7DQogIGNvbnQgPC0gMQ0KDQogICMgQWxhcm0hIFRBVU1BWCBvdmVyc3RlcHBlZCENCiAgaWYgKHRhdTFrID49IFRBVU1BWCkgew0KICAgIHRhdTFrIDw8LSBUQVVNQVggLSAxDQogIH0NCg0KICAjIE5ldyB0cmVlLCBhZGQgcm9vdA0KICBpZiAoaXMubnVsbChyb290W1tzd11dKSkgew0KICAgIHJvb3RbW3N3XV0gPDwtIGluc2VydHByb3hlbChzLCB0YXUxaywgdGF1MmssIHZhbCkNCiAgICByb290W1tzd11dJGxlZnQgPDwtIE5VTEwNCiAgICByb290W1tzd11dJHJpZ2h0IDw8LSBOVUxMDQogICAgcmV0dXJuKCkNCiAgfQ0KDQogICMgQ29tcHV0ZSBpZCBvZiBuZXcgcHJveGVsDQogIGlkIDwtIHN0YXRlMmlkKHMsIHRhdTFrLCB0YXUyaykNCg0KICAjIExvY2F0ZSBpbnNlcnRpb24gcG9pbnQgaW4gdHJlZQ0KICB0ZW1wIDwtIHJvb3RbW3N3XV0NCiAgd2hpbGUgKGNvbnQgPT0gMSkgew0KICAgIGlmICghaXMubnVsbCh0ZW1wJGxlZnQpICYmIGlkIDwgdGVtcCRpZCkNCiAgICAgIHRlbXAgPC0gdGVtcCRsZWZ0DQogICAgZWxzZSBpZiAoIWlzLm51bGwodGVtcCRyaWdodCkgJiYgaWQgPiB0ZW1wJGlkKQ0KICAgICAgdGVtcCA8LSB0ZW1wJHJpZ2h0DQogICAgZWxzZQ0KICAgICAgY29udCA8LSAwDQogIH0NCg0KICAjIEluc2VydCBsZWZ0IGxlYWYgaW50byB0cmVlDQogIGlmIChpcy5udWxsKHRlbXAkbGVmdCkgJiYgaWQgPCB0ZW1wJGlkKSB7DQogICAgdGVtcDIgPC0gaW5zZXJ0cHJveGVsKHMsIHRhdTFrLCB0YXUyaywgdmFsKQ0KICAgIHRlbXAkbGVmdCA8PC0gdGVtcDINCiAgICB0ZW1wMiRsZWZ0IDw8LSBOVUxMDQogICAgdGVtcDIkcmlnaHQgPDwtIE5VTEwNCiAgICByZXR1cm4oKQ0KICB9DQoNCiAgIyBJbnNlcnQgcmlnaHQgbGVhZiBpbnRvIHRyZWUNCiAgaWYgKGlzLm51bGwodGVtcCRyaWdodCkgJiYgaWQgPiB0ZW1wJGlkKSB7DQogICAgdGVtcDIgPC0gaW5zZXJ0cHJveGVsKHMsIHRhdTFrLCB0YXUyaywgdmFsKQ0KICAgIHRlbXAkcmlnaHQgPDwtIHRlbXAyDQogICAgdGVtcDIkbGVmdCA8PC0gTlVMTA0KICAgIHRlbXAyJHJpZ2h0IDw8LSBOVUxMDQogICAgcmV0dXJuKCkNCiAgfQ0KDQogICMgUHJveGVscyBoYXZlIHRoZSBzYW1lIGlkLCBqdXN0IGFkZCB0aGVpciB2YWxzDQogIGlmIChpZCA9PSB0ZW1wJGlkKSB7DQogICAgdGVtcCR2YWwgPDwtIHRlbXAkdmFsICsgdmFsDQogICAgcmV0dXJuKCkNCiAgfQ0KDQogIGNhdCgiXG5cblxuISEhISEhIGFkZHByb3hlbCBmYWlsZWQgISEhISFcblxuXG4iKQ0KfQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIG1vZGVsIHNwZWNpZmljIGRpc3RzICMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIEluc3RhbnRhbmVvdXMgcmF0ZSBmdW5jdGlvbiAxDQpTMV90b19TMiA8LSBmdW5jdGlvbihhZ2UpIHsNCiAgcmV0dXJuKHVuaWhyZihhZ2UsIDIsIDQpKQ0KfQ0KDQojIEluc3RhbnRhbmVvdXMgcmF0ZSBmdW5jdGlvbiAyDQpTMl90b19TMyA8LSBmdW5jdGlvbihhZ2UpIHsNCiAgcmV0dXJuKGV4cGhyZihhZ2UsIDAuMSkpDQp9DQoNCiMgSW5zdGFudGFuZW91cyByYXRlIGZ1bmN0aW9uIDMNCmhlYWwgPC0gZnVuY3Rpb24oYWdlKSB7DQogIHJldHVybih1bmlocmYoYWdlLCA3LCAxNCkpDQp9DQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIG1haW4gbG9vcCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCm1haW4gPC0gZnVuY3Rpb24oKSB7DQogIGttYXggPC0gYXMuaW50ZWdlcihFTkRUSU1FIC8gREVMVEEpICsgMQ0KDQogICMgSW5pdGlhbGl6ZSB0aGUgc2ltdWxhdGlvbg0KICByb290W1sxXV0gPDwtIE5VTEwNCiAgcm9vdFtbMl1dIDw8LSBOVUxMDQogIGVlcnJvciA8PC0gMC4wDQogIHRvdGNudCA8PC0gMA0KICBtYXhjY3AgPDwtIDANCiAgY2NwY250IDw8LSAwDQoNCiAgZm9yIChrIGluIDE6NCkgew0KICAgIHlbW2tdXSA8LSByZXAoMC4wLCBrbWF4ICsgMikNCiAgfQ0KDQogIFRBVU1BWCA8PC0gYXMuaW50ZWdlcihFTkRUSU1FIC8gREVMVEEpICsgMQ0KDQogICMgU2V0IGluaXRpYWwgcHJveGVsDQogIGFkZHByb3hlbChTMSwgMCwgMCwgMS4wKQ0KDQogICMgRmlyc3QgbG9vcDogaXRlcmF0aW9uIG92ZXIgYWxsIHRpbWUgc3RlcHMNCiAgZm9yIChrIGluIDI6KGttYXggKyAxKSkgew0KDQogICAgIyBQcmludCBwcm9ncmVzcyBpbmZvcm1hdGlvbg0KICAgIGlmIChrICUlIDEwMCA9PSAwKSB7DQogICAgICBjYXQoIlxuU1RFUCIsIGssICJcbiIpDQogICAgICBjYXQoIlNpemUgb2YgdHJlZSIsIHNpemUocm9vdFtbc3ddXSksICJcbiIpDQogICAgfQ0KDQogICAgc3cgPDwtIDEgLSBzdw0KDQogICAgIyBTZWNvbmQgbG9vcDogaXRlcmF0aW5nIG92ZXIgYWxsIHByb3hlbHMgb2YgYSB0aW1lIHN0ZXANCiAgICB3aGlsZSAoIWlzLm51bGwocm9vdFtbMSAtIHN3XV0pKSB7DQogICAgICB0b3RjbnQgPDwtIHRvdGNudCArIDENCiAgICAgIGN1cnJwcm94ZWwgPC0gZ2V0cHJveGVsKCkNCiAgICAgIHByaW50KHkpDQogICAgICB3aGlsZSAoY3VycnByb3hlbCR2YWwgPCBNSU5QUk9CICYmICFpcy5udWxsKHJvb3RbWzEgLSBzd11dKSkgew0KICAgICAgICB2YWwgPC0gY3VycnByb3hlbCR2YWwNCiAgICAgICAgZWVycm9yIDw8LSBlZXJyb3IgKyB2YWwNCiAgICAgICAgY3VycnByb3hlbCA8LSBnZXRwcm94ZWwoKQ0KICAgICAgfQ0KDQogICAgICB2YWwgPC0gY3VycnByb3hlbCR2YWwNCiAgICAgIHRhdTFrIDwtIGN1cnJwcm94ZWwkdGF1MWsNCiAgICAgIHRhdTJrIDwtIGN1cnJwcm94ZWwkdGF1MmsNCiAgICAgIHMgPC0gY3VycnByb3hlbCRzDQogICAgICB5W1tzXV1bayAtIDFdIDw8LSB5W1tzXV1bayAtIDFdICsgdmFsDQoNCiAgICAgICMgQ3JlYXRlIGNoaWxkIHByb3hlbHMNCiAgICAgIHN3aXRjaChzLA0KICAgICAgICAgICAgIFMxID0gew0KICAgICAgICAgICAgICAgeiA8LSBkdCAqIFMxX3RvX1MyKHRhdTFrICogZHQpDQogICAgICAgICAgICAgICB6MiA8LSBkdCAqIGhlYWwodGF1MmsgKiBkdCkNCiAgICAgICAgICAgICAgIGlmICh6IDwgMS4wICYgejIgPCAxLjApIHsNCiAgICAgICAgICAgICAgICAgYWRkcHJveGVsKFMyLCAwLCB0YXUyayArIDEsIHZhbCAqIHopDQogICAgICAgICAgICAgICAgIGFkZHByb3hlbChIICwgMCwgdGF1MmsgKyAxLCB2YWwgKiB6MikNCiAgICAgICAgICAgICAgICAgYWRkcHJveGVsKFMxLCB0YXUxayArIDEsIHRhdTJrICsgMSwgdmFsICogKDEgLSB6IC0gejIpKQ0KICAgICAgICAgICAgICAgfSANCiAgICAgICAgICAgICAgIGlmICh6PT0xLjApIHsNCiAgICAgICAgICAgICAgICAgYWRkcHJveGVsKFMyLCAwLCB0YXUyayArIDEsIHZhbCkNCiAgICAgICAgICAgICAgICAgfSBlbHNlDQogICAgICAgICAgICAgICAgICAgYWRkcHJveGVsKEgsIDAsIDAsIHZhbCkNCiAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgIFMyID0gew0KICAgICAgICAgICAgICAgeiA8LSBkdCAqIFMyX3RvX1MzKHRhdTFrICogZHQpDQogICAgICAgICAgICAgICB6MiA8LSBkdCAqIGhlYWwodGF1MmsgKiBkdCkNCiAgICAgICAgICAgICAgIGlmICh6IDwgMS4wICYgejIgPCAxLjApIHsNCiAgICAgICAgICAgICAgICAgYWRkcHJveGVsKFMzLCAwLCB0YXUyayArIDEsIHZhbCAqIHopDQogICAgICAgICAgICAgICAgIGFkZHByb3hlbChIICwgMCwgdGF1MmsgKyAxLCB2YWwgKiB6MikNCiAgICAgICAgICAgICAgICAgYWRkcHJveGVsKFMyLCB0YXUxayArIDEsIHRhdTJrICsgMSwgdmFsICogKDEgLSB6IC0gejIpKQ0KICAgICAgICAgICAgICAgfSANCiAgICAgICAgICAgICAgIGlmICh6PT0xLjApIHsNCiAgICAgICAgICAgICAgICAgYWRkcHJveGVsKFMzLCAwLCB0YXUyayArIDEsIHZhbCkNCiAgICAgICAgICAgICAgICAgfSBlbHNlDQogICAgICAgICAgICAgICAgICAgYWRkcHJveGVsKEgsIDAsIDAsIHZhbCkNCiAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgIFMzID0gew0KICAgICAgICAgICAgICAgeiA8LSBkdCAqIGhlYWwodGF1MmsgKiBkdCkNCiAgICAgICAgICAgICAgIGlmICh6IDwgMS4wKSB7DQogICAgICAgICAgICAgICAgIGFkZHByb3hlbChILCAwLCB0YXUyayArIDEsIHZhbCAqIHopDQogICAgICAgICAgICAgICAgIGFkZHByb3hlbChTMywgdGF1MWsgKyAxLCB0YXUyayArIDEsIHZhbCAqICgxIC0geikpDQogICAgICAgICAgICAgICB9IGVsc2UNCiAgICAgICAgICAgICAgICAgYWRkcHJveGVsKEgsIDAsIDAsIHZhbCkNCiAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgIEggPSB7DQogICAgICAgICAgICAgICBhZGRwcm94ZWwoSCwgdGF1MWsgKyAxLCAwLCAxKQ0KICAgICAgICAgICAgIH0pDQogICAgfQ0KICB9DQoNCiAgY2F0KCJlcnJvciA9IiwgZWVycm9yLCAiXG4iKQ0KICBjYXQoImNjcHggPSIsIG1heGNjcCwgIlxuIikNCiAgY2F0KCJjb3VudCA9IiwgdG90Y250LCAiXG4iKQ0KICBwbG90c29sdXRpb24oa21heCkNCn0NCm1haW4oKQ0KYGBgDQoNCiMjIE1vZGlmeSB0aGUgZ2l2ZW4gaGFyZC1jb2RlZCBQcm94ZWwtcHJvZ3JhbSB0byBzaW11bGF0ZSB0aGUgYWJvdmUgUGV0cmkgbmV0LiANCg0KKsOcYmVyIGRlbiBDb2RlLUJ1dHRvbiByZWNodHMgdW50ZXIgZGVtIFRleHQgaXN0IGRlciBnZWdlYmVuZSBDb2RlIGVpbnNlaGJhciwgd2VsY2hlciBuYWNoIG1laW5lbSBiZXN0ZW4gV2lzc2VuIMO8YmVyYXJiZWl0ZXQgdW5kIGFuIGRpZSBnZWdlYmVuZSBBdWZnYWJlIGFuZ2VwYXNzdCB3dXJkZS4qDQoNCmBgYHtyIEdpdmVuIFByb3hlbC1Qcm9ncmFtbSAobW9kaWZpZWQpLCB3YXJuaW5nPUZBTFNFfQ0KTUlOUFJPQiA8LSAxLjBlLTEyDQpTVEFHRTEgPC0gMQ0KU1RBR0UyIDwtIDINClNUQUdFMyA8LSAzDQpIRUFMVEhZIDwtIDQNCkRFTFRBIDwtIGMoMiwgMSwgMC41LCAwLjI1LCAwLjEpDQpFTkRUSU1FIDwtIDEzDQpQSSA8LSAzLjE0MTU5MjYNCg0Kc2V0Q2xhc3MoIlByb3hlbCIscmVwcmVzZW50YXRpb24gPSBsaXN0KGlkID0gIm51bWVyaWMiLCBzID0gIm51bWVyaWMiLCB0YXUxayA9ICJudW1lcmljIiwgdGF1MmsgPSAibnVtZXJpYyIsIHZhbCA9ICJudW1lcmljIiwgbGVmdCA9ICJQcm94ZWwiLCByaWdodCA9ICJQcm94ZWwiDQogICkpDQpQcm94ZWwgPC0gZnVuY3Rpb24oKSB7DQogIGxpc3QoDQogICAgaWQgPSAwLA0KICAgIHMgPSAwLA0KICAgIHRhdTFrID0gMCwNCiAgICB0YXUyayA9IDAsDQogICAgdmFsID0gMC4wLA0KICAgIGxlZnQgPSBOVUxMLA0KICAgIHJpZ2h0ID0gTlVMTA0KICApDQp9DQoNCnkgPC0gbGlzdChOVUxMLCBOVUxMLCBOVUxMLCBOVUxMKQ0KdG1heCA8LSAwLjANClRBVU1BWCA8LSAwDQp0b3RjbnQgPC0gMA0KbWF4Y2NwIDwtIDANCmNjcGNudCA8LSAwDQpyb290IDwtIGxpc3QoTlVMTCwgTlVMTCkNCmZpcnN0ZnJlZSA8LSBOVUxMDQplZXJyb3IgPC0gMA0Kc3cgPC0gMA0KbGVuIDwtIDANCmR0IDwtIDANCg0KdW5paHJmIDwtIGZ1bmN0aW9uKHgsIGEsIGIpIHsNCiAgaWYgKGEgPD0geCAmJiB4IDwgYikgew0KICAgIHJldHVybiAoMS4wIC8gKGIgLSB4KSkNCiAgfSBlbHNlIHsNCiAgICByZXR1cm4gKDApDQogIH0NCn0NCg0KZXhwaHJmIDwtIGZ1bmN0aW9uKHgsIGwpIHsNCiAgcmV0dXJuIChsKQ0KfQ0KDQpwcmludHRyZWUgPC0gZnVuY3Rpb24ocCkgew0KICBpZiAoaXMubnVsbChwKSkgew0KICAgIHJldHVybg0KICB9DQogIGNhdCgicyIsIHAkcywgInQxIiwgcCR0YXUxaywgInQyIiwgcCR0YXUyaywgInZhbCIsIHAkdmFsLCAiXG4iKQ0KICBwcmludHRyZWUocCRsZWZ0KQ0KICBwcmludHRyZWUocCRyaWdodCkNCn0NCg0KcGxvdHNvbHV0aW9uIDwtIGZ1bmN0aW9uKGttYXgpIHsNCiAgY2F0KCJcblxuIikNCiAgZm9yIChrIGluIDE6KGttYXggKyAxKSkgew0KICAgIGNhdChzcHJpbnRmKCIlLjVmXHQlLjVlXHQlLjVlXHQlLjVlXHQlLjVlXG4iLCBrICogZHQsIHlbWzFdXVtrXSwgeVtbMl1dW2tdLCB5W1szXV1ba10sIHlbWzRdXVtrXSkpDQogIH0NCn0NCg0KcHJpbnRwcm94ZWwgPC0gZnVuY3Rpb24oYykgew0KICBjYXQoInByb2Nlc3NpbmciLCBjJHMsIGMkdGF1MWssIGMkdmFsLCAiXG4iKQ0KfQ0KDQpzdGF0ZTJpZCA8LSBmdW5jdGlvbihzLCB0MWssIHQyaykgew0KICByZXR1cm4gKFRBVU1BWCAqIChUQVVNQVggKiBzICsgdDFrKSArIHQyaykNCn0NCg0Kc2l6ZSA8LSBmdW5jdGlvbihwKSB7DQogIGlmIChpcy5udWxsKHApKSB7DQogICAgcmV0dXJuICgwKQ0KICB9DQogIHNsIDwtIHNpemUocCRsZWZ0KQ0KICBzciA8LSBzaXplKHAkcmlnaHQpDQogIHJldHVybiAoc2wgKyBzciArIDEpDQp9DQoNCmdldHByb3hlbCA8LSBmdW5jdGlvbigpIHsNCiAgTEVGVCA8LSAwDQogIFJJR0hUIDwtIDENCiAgZGlyIDwtIDENCiAgY29udCA8LSAxDQoNCiAgaWYgKGlzLm51bGwocm9vdFtbMSAtIHN3KzFdXSkpIHsNCiAgICByZXR1cm4oTlVMTCkNCiAgfQ0KDQogIHRlbXAgPC0gcm9vdFtbMSAtIHN3KzFdXQ0KICBvbGQgPC0gdGVtcA0KDQogIHdoaWxlIChjb250ID09IDEpIHsNCiAgICBpZiAoIWlzLm51bGwodGVtcCRyaWdodCkgJiYgaXMubnVsbCh0ZW1wJGxlZnQpKSB7DQogICAgICBvbGQgPC0gdGVtcA0KICAgICAgdGVtcCA8LSB0ZW1wJHJpZ2h0DQogICAgICBkaXIgPC0gUklHSFQNCiAgICB9IGVsc2UgaWYgKGlzLm51bGwodGVtcCRyaWdodCkgJiYgIWlzLm51bGwodGVtcCRsZWZ0KSkgew0KICAgICAgb2xkIDwtIHRlbXANCiAgICAgIHRlbXAgPC0gdGVtcCRsZWZ0DQogICAgICBkaXIgPC0gTEVGVA0KICAgIH0gZWxzZSBpZiAoIWlzLm51bGwodGVtcCRyaWdodCkgJiYgIWlzLm51bGwodGVtcCRsZWZ0KSkgew0KICAgICAgaWYgKHJ1bmlmKDEpID4gMC41KSB7DQogICAgICAgIG9sZCA8LSB0ZW1wDQogICAgICAgIHRlbXAgPC0gdGVtcCRsZWZ0DQogICAgICAgIGRpciA8LSBMRUZUDQogICAgICB9IGVsc2Ugew0KICAgICAgICBvbGQgPC0gdGVtcA0KICAgICAgICB0ZW1wIDwtIHRlbXAkcmlnaHQNCiAgICAgICAgZGlyIDwtIFJJR0hUDQogICAgICB9DQogICAgfSBlbHNlIHsNCiAgICAgIGNvbnQgPC0gMA0KICAgIH0NCiAgfQ0KDQogIGlmIChpZGVudGljYWwodGVtcCwgcm9vdFtbMSAtIHN3KzFdXSkpIHsNCiAgICByb290W1sxIC0gc3crMV1dIDwtIE5VTEwNCiAgfSBlbHNlIHsNCiAgICBpZiAoZGlyID09IFJJR0hUKSB7DQogICAgICBvbGQkcmlnaHQgPC0gTlVMTA0KICAgIH0gZWxzZSB7DQogICAgICBvbGQkbGVmdCA8LSBOVUxMDQogICAgfQ0KICB9DQoNCiAgb2xkIDwtIGZpcnN0ZnJlZQ0KICBmaXJzdGZyZWUgPC0gdGVtcA0KICB0ZW1wJHJpZ2h0IDwtIG9sZA0KICBjY3BjbnQgPC0gY2NwY250IC0gMQ0KICByZXR1cm4odGVtcCkNCn0NCg0KaW5zZXJ0cHJveGVsIDwtIGZ1bmN0aW9uKHMsIHRhdTFrLCB0YXUyaywgdmFsKSB7DQogIGlmIChpcy5udWxsKGZpcnN0ZnJlZSkpIHsNCiAgICB0ZW1wIDwtIFByb3hlbCgpDQogIH0gZWxzZSB7DQogICAgdGVtcCA8LSBmaXJzdGZyZWUNCiAgICBmaXJzdGZyZWUgPC0gZmlyc3RmcmVlJHJpZ2h0DQogIH0NCg0KICB0ZW1wJGlkIDwtIHN0YXRlMmlkKHMsIHRhdTFrLCB0YXUyaykNCiAgdGVtcCRzIDwtIHMNCiAgdGVtcCR0YXUxayA8LSB0YXUxaw0KICB0ZW1wJHRhdTJrIDwtIHRhdTJrDQogIHRlbXAkdmFsIDwtIHZhbA0KICBjY3BjbnQgPC0gY2NwY250ICsgMQ0KDQogIGlmIChtYXhjY3AgPCBjY3BjbnQpIHsNCiAgICBtYXhjY3AgPC0gY2NwY250DQogIH0NCg0KICByZXR1cm4odGVtcCkNCn0NCg0KYWRkcHJveGVsIDwtIGZ1bmN0aW9uKHMsIHRhdTFrLCB0YXUyaywgdmFsKSB7DQogIHRlbXAgPC0gTlVMTA0KICB0ZW1wMiA8LSBOVUxMDQogIGNvbnQgPC0gMQ0KICBpZCA8LSBzdGF0ZTJpZChzLCB0YXUxaywgdGF1MmspDQoNCiAgaWYgKHRhdTFrID49IFRBVU1BWCkgew0KICAgIHRhdTFrIDwtIFRBVU1BWCAtIDENCiAgfQ0KICBpZiAoaXMubnVsbChyb290W1tzdysxXV0pKSB7DQogICAgcm9vdFtbc3crMV1dIDwtIGluc2VydHByb3hlbChzLCB0YXUxaywgdGF1MmssIHZhbCkNCiAgICByb290W1tzdysxXV0kbGVmdCA8LSBOVUxMDQogICAgcm9vdFtbc3crMV1dJHJpZ2h0IDwtIE5VTEwNCiAgICByZXR1cm4oTlVMTCkNCiAgfQ0KDQogIHRlbXAgPC0gcm9vdFtbc3crMV1dDQoNCiAgd2hpbGUgKGNvbnQgPT0gMSkgew0KICAgIGlmICghaXMubnVsbCh0ZW1wJGxlZnQpICYmIGlkIDwgdGVtcCRpZCkgew0KICAgICAgdGVtcCA8LSB0ZW1wJGxlZnQNCiAgICB9IGVsc2UgaWYgKCFpcy5udWxsKHRlbXAkcmlnaHQpICYmIGlkID4gdGVtcCRpZCkgew0KICAgICAgdGVtcCA8LSB0ZW1wJHJpZ2h0DQogICAgfSBlbHNlIHsNCiAgICAgIGNvbnQgPC0gMA0KICAgIH0NCiAgfQ0KDQogIGlmIChpcy5udWxsKHRlbXAkbGVmdCkgJiYgaWQgPCB0ZW1wJGlkKSB7DQogICAgdGVtcDIgPC0gaW5zZXJ0cHJveGVsKHMsIHRhdTFrLCB0YXUyaywgdmFsKQ0KICAgIHRlbXAkbGVmdCA8LSB0ZW1wMg0KICAgIHRlbXAyJGxlZnQgPC0gTlVMTA0KICAgIHRlbXAyJHJpZ2h0IDwtIE5VTEwNCiAgfSBlbHNlIGlmIChpcy5udWxsKHRlbXAkcmlnaHQpICYmIGlkID4gdGVtcCRpZCkgew0KICAgIHRlbXAyIDwtIGluc2VydHByb3hlbChzLCB0YXUxaywgdGF1MmssIHZhbCkNCiAgICB0ZW1wJHJpZ2h0IDwtIHRlbXAyDQogICAgdGVtcDIkbGVmdCA8LSBOVUxMDQogICAgdGVtcDIkcmlnaHQgPC0gTlVMTA0KICB9IGVsc2UgaWYgKGlkID09IHRlbXAkaWQpIHsNCiAgICB0ZW1wJHZhbCA8LSB0ZW1wJHZhbCArIHZhbA0KICB9IGVsc2Ugew0KICAgIGNhdCgiXG5cblxuISEhISEhIGFkZHByb3hlbCBmYWlsZWQgISEhISFcblxuXG4iKQ0KICB9DQp9DQoNCmluY3ViYXRpb24gPC0gZnVuY3Rpb24oYWdlKSB7DQogIHJldHVybiAodW5paHJmKGFnZSwgMiwgNCkpDQp9DQoNCmdldF93b3JzZSA8LSBmdW5jdGlvbihhZ2UpIHsNCiAgcmV0dXJuIChleHBocmYoYWdlLCAxLzEwKSkNCn0NCg0KaGVhbCA8LSBmdW5jdGlvbihhZ2UpIHsNCiAgcmV0dXJuICh1bmlocmYoYWdlLCA3LCAxNCkpDQp9DQoNCm1haW4gPC0gZnVuY3Rpb24oKSB7DQogIHJvb3QgPC0gbGlzdChOVUxMLCBOVUxMKQ0KICBlZXJyb3IgPC0gMC4wDQogIHRvdGNudCA8LSAwDQogIG1heGNjcCA8LSAwDQogIHRtYXggPC0gRU5EVElNRQ0KICBkdCA8LSBERUxUQVsyXQ0KICBrbWF4IDwtIGFzLmludGVnZXIodG1heCAvIGR0KSArIDENCg0KICBmb3IgKGsgaW4gMTo0KSB7DQogICAgeVtba11dIDwtIHJlcCgwLjAsIGttYXggKyAyKQ0KICB9DQoNCiAgVEFVTUFYIDwtIGFzLmludGVnZXIodG1heCAvIGR0KSArIDENCg0KICBhZGRwcm94ZWwoU1RBR0UxLCAwLCAwLCAxLjApDQoNCiAgZm9yIChrIGluIDI6KGttYXggKyAyKSkgew0KICAgIGlmIChrICUlIDEwMCA9PSAwKSB7DQogICAgICBjYXQoIlxuU1RFUCIsIGssICJcbiIpDQogICAgICBjYXQoIlNpemUgb2YgdHJlZSIsIHNpemUocm9vdFtbc3crMV1dKSwgIlxuIikNCiAgICB9DQoNCiAgICB3aGlsZSAoIWlzLm51bGwocm9vdFtbMSAtIHN3KzFdXSkpIHsNCiAgICAgIHRvdGNudCA8LSB0b3RjbnQgKyAxDQogICAgICBjdXJycHJveGVsIDwtIGdldHByb3hlbCgpDQoNCiAgICAgIHdoaWxlIChjdXJycHJveGVsJHZhbCA8IE1JTlBST0IgJiYgIWlzLm51bGwocm9vdFtbMSAtIHN3KzFdXSkpIHsNCiAgICAgICAgdmFsIDwtIGN1cnJwcm94ZWwkdmFsDQogICAgICAgIGVlcnJvciA8LSBlZXJyb3IgKyB2YWwNCiAgICAgICAgY3VycnByb3hlbCA8LSBnZXRwcm94ZWwoKQ0KICAgICAgfQ0KDQogICAgICB2YWwgPC0gY3VycnByb3hlbCR2YWwNCiAgICAgIHRhdTFrIDwtIGN1cnJwcm94ZWwkdGF1MWsNCiAgICAgIHRhdTJrIDwtIGN1cnJwcm94ZWwkdGF1MmsNCiAgICAgIHMgPC0gY3VycnByb3hlbCRzDQogICAgICB5W1tzXV1bayAtIDFdIDwtIHlbW3NdXVtrIC0gMV0gKyB2YWwNCg0KICAgICAgaWYgKHMgPT0gU1RBR0UxKSB7DQogICAgICAgIHogPC0gZHQgKiBpbmN1YmF0aW9uKHRhdTFrICogZHQpDQogICAgICAgIHoyIDwtIGR0ICogaGVhbCh0YXUyayAqIGR0KQ0KICAgICAgICBpZiAoejIgPCAxLjApIHsNCiAgICAgICAgICBpZiAoeiA8IDEuMCkgew0KICAgICAgICAgICAgYWRkcHJveGVsKFNUQUdFMiwgMCwgdGF1MmsgKyAxLCB2YWwgKiB6KQ0KICAgICAgICAgICAgYWRkcHJveGVsKFNUQUdFMSwgdGF1MWsgKyAxLCB0YXUyayArIDEsIHZhbCAqICgxIC0geiAtIHoyKSkNCiAgICAgICAgICAgIGFkZHByb3hlbChIRUFMVEhZLCAwLCAwLCB2YWwgKiAoejIpKQ0KICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBhZGRwcm94ZWwoU1RBR0UyLCAwLCB0YXUyayArIDEsIHZhbCkNCiAgICAgICAgICB9DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgYWRkcHJveGVsKEhFQUxUSFksIDAsIDAsIHZhbCkNCiAgICAgICAgfQ0KICAgICAgfSBlbHNlIGlmIChzID09IFNUQUdFMikgew0KICAgICAgICB6IDwtIGR0ICogZ2V0X3dvcnNlKHRhdTFrICogZHQpDQogICAgICAgIHoyIDwtIGR0ICogaGVhbCh0YXUyayAqIGR0KQ0KICAgICAgICBpZiAoejIgPCAxLjApIHsNCiAgICAgICAgICBpZiAoeiA8IDEuMCkgew0KICAgICAgICAgICAgYWRkcHJveGVsKFNUQUdFMywgMCwgdGF1MmsgKyAxLCB2YWwgKiB6KQ0KICAgICAgICAgICAgYWRkcHJveGVsKFNUQUdFMiwgdGF1MWsgKyAxLCB0YXUyayArIDEsIHZhbCAqICgxIC0geiAtIHoyKSkNCiAgICAgICAgICAgIGFkZHByb3hlbChIRUFMVEhZLCAwLCAwLCB2YWwgKiAoejIpKQ0KICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICBhZGRwcm94ZWwoU1RBR0UzLCAwLCB0YXUyayArIDEsIHZhbCkNCiAgICAgICAgICB9DQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgYWRkcHJveGVsKEhFQUxUSFksIDAsIDAsIHZhbCkNCiAgICAgICAgfQ0KICAgICAgfSBlbHNlIGlmIChzID09IFNUQUdFMykgew0KICAgICAgICB6IDwtIGR0ICogaGVhbCh0YXUyayAqIGR0KQ0KICAgICAgICBpZiAoeiA8IDEuMCkgew0KICAgICAgICAgIGFkZHByb3hlbChIRUFMVEhZLCAwLCAwLCB2YWwgKiB6KQ0KICAgICAgICAgIGFkZHByb3hlbChTVEFHRTMsIHRhdTFrICsgMSwgdGF1MmsgKyAxLCB2YWwgKiAoMSAtIHopKQ0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIGFkZHByb3hlbChIRUFMVEhZLCAwLCAwLCB2YWwpDQogICAgICAgIH0NCiAgICAgIH0gZWxzZSBpZiAocyA9PSBIRUFMVEhZKSB7DQogICAgICAgIGFkZHByb3hlbChIRUFMVEhZLCB0YXUxayArIDEsIHRhdTJrICsgMSwgMSkNCiAgICAgIH0NCiAgICB9DQogICAgaWYgKHN3PT0wKSBzdz0xDQogICAgaWYgKHN3PT0xKSBzdz0wDQogIH0NCg0KICAjY2F0KCJcblxuIikNCiAgI2NhdCgiZXJyb3IgPSIsIHNwcmludGYoIiUuNWUiLCBlZXJyb3IpLCAiXG4iKQ0KICAjY2F0KCJjY3B4ID0iLCBtYXhjY3AsICJcbiIpDQogICNjYXQoImNvdW50ID0iLCB0b3RjbnQsICJcbiIpDQogICNwbG90c29sdXRpb24oa21heCkNCn0NCg0KbWFpbigpDQpgYGANCg0KYGBge3IgRmFsc2NoZXMgc2VsYnN0Z2VzY2hyaWViZW5lcywgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCg0KbWF4LnRzID0gMTQNCmRlbHRhID0gMQ0Kc3RhcnRwcm94ZWw9YygxLDAsMSkNClJHPW1hdHJpeChjKDEsMSwwLDEsDQogICAgICAgICAgICAwLDEsMSwxLA0KICAgICAgICAgICAgMCwwLDEsMSwNCiAgICAgICAgICAgIDAsMCwwLDEpLG5jb2wgPSA0LGJ5cm93ID0gVCkNCg0KUHJveGVsX2FsZ289ZnVuY3Rpb24oUkcsc3RhcnRwcm94ZWwsZGVsdGEsbWF4LnRzLFByaW50PVQpew0KICANCmNvdW50ZXJfcHJvYj0wDQoNCnVuaWhyZiA8LSBmdW5jdGlvbihhZ2UsIGEsIGIpIHsNCiAgaWYgKGEgPD0gYWdlICYmIGFnZSA8IGIpIHsNCiAgICByZXR1cm4gKDEuMCAvIChiIC0gYWdlKSkNCiAgfSBlbHNlIHsNCiAgICByZXR1cm4gKDApDQogIH0NCn0NCg0KZXhwaHJmIDwtIGZ1bmN0aW9uKGFnZSwgbCkgew0KICByZXR1cm4gKGwpDQp9DQogIA0KcHJveGVsX2xpc3Q9bGlzdCgpDQpwcm94ZWxfbGlzdFtbbWF4LnRzKzFdXT1saXN0KCkNCnByb3hlbF9saXN0W1sxXV09bGlzdChTVEVQPWMoMCkscHJveGVsPWRhdGEuZnJhbWUoc3RhdGU9c3RhcnRwcm94ZWxbMV0sdGF1PXN0YXJ0cHJveGVsWzJdLHByb2I9c3RhcnRwcm94ZWxbM10pKQ0KaWYoUHJpbnQpIHByaW50KCJpbml0aWFsIHByb3hlbDoiKQ0KaWYoUHJpbnQpIHByaW50KHByb3hlbF9saXN0W1sxXV0pDQoNCmZvciAodGltZXN0ZXAgaW4gMTptYXgudHMpIHsNCiAgcHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXT1saXN0KHRpbWVzdGVwPWModGltZXN0ZXApLHByb3hlbD1kYXRhLmZyYW1lKHN0YXRlPW51bWVyaWMoKSx0YXU9bnVtZXJpYygpLHByb2I9bnVtZXJpYygpKSkgICAgICMgZXJzdGVsbGUgc2Nob25tYWwgZWluZSBuZXVlIGxlZXJlIGxpc3RlIGbDvHIgZGVuIG7DpGNoc3RlbiB0aW1lc3RlcA0KICANCiAgZm9yIChsIGluIDE6bnJvdyhwcm94ZWxfbGlzdFtbdGltZXN0ZXBdXSRwcm94ZWwpKSB7DQogICAgY3VycnByb3ggPSBwcm94ZWxfbGlzdFtbdGltZXN0ZXBdXSRwcm94ZWxbbCxdICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgYWt0dWVsbGVyIHByb3hlbCB6dSBkZW0gZm9sZ2Vwcm94ZWxzIGVyemV1Z3Qgd2VyZGVuIHNvbGxlbg0KICAgIGZvbGdlciA9IFJHW2FzLm51bWVyaWMoY3VycnByb3hbMV0pLF0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGZvbGdlc3RhdGVzIHZvbiBha3R1ZWxsZW0gcHJveGVsDQogICAgZm9yIChpIGluIDE6NCkgew0KICAgICAgaWYgKGZvbGdlcltpXT09MSkgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGVyc3RlbGxlIGZvbGdlcHJveGVsIGZhbGxzIHBmZWlsIGRhaGluIGdpYnQNCiAgICAgICAgcHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbbnJvdyhwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbCkrMSwxXSA9IGkgICAgICAgICAgICAgICAgICAgICAgICMgc3RhdGUgdm9tIG7DpGNoc3RlbiBwcm94ZWwNCiAgICAgICAgDQogICAgICAgIGlmKGN1cnJwcm94JHN0YXRlPT1pKSBwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbFtucm93KHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsKSwyXSA9IGN1cnJwcm94JHRhdSArIGRlbHRhDQogICAgICAgICAgZWxzZSBwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbFtucm93KHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsKSwyXSA9IDAgICAgICAgICAgICAgICAgICAgICMgdGF1IHZvbSBuw6RjaHN0ZW4gcHJveGVsDQogICAgICAgICAgDQogICAgICAgIGlmKGN1cnJwcm94JHN0YXRlPT0xICYgaT09Mikgew0KICAgICAgICAgIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsW25yb3cocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWwpLDNdID0gdW5paHJmKGN1cnJwcm94JHRhdSwyLDQpICogZGVsdGENCiAgICAgICAgICBjb3VudGVyX3Byb2IgPSBjb3VudGVyX3Byb2IgKyB1bmlocmYoY3VycnByb3gkdGF1LDIsNCkgKiBkZWx0YX0gICAgICAgICAgICAgICAgICMgdHJhbnNpdGlvbiB2b24gUzEgenUgUzINCiAgICAgICAgaWYoY3VycnByb3gkc3RhdGU9PTIgJiBpPT0zKSB7DQogICAgICAgICAgcHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbbnJvdyhwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbCksM10gPSBleHBocmYoY3VycnByb3gkdGF1LDAuMSkgKiBkZWx0YQ0KICAgICAgICAgIGNvdW50ZXJfcHJvYiA9IGNvdW50ZXJfcHJvYiArIGV4cGhyZihjdXJycHJveCR0YXUsMC4xKSAqIGRlbHRhfSAgICAgICAgICAgICAgICAgIyB0cmFuc2l0aW9uIHZvbiBTMiB6dSBTMw0KICAgICAgICBpZihjdXJycHJveCRzdGF0ZSE9NCAmIGk9PTQpIHsNCiAgICAgICAgICBwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbFtucm93KHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsKSwzXSA9IHVuaWhyZihjdXJycHJveCR0YXUsNywxNCkqIGRlbHRhIA0KICAgICAgICAgIGNvdW50ZXJfcHJvYiA9IGNvdW50ZXJfcHJvYiArIHVuaWhyZihjdXJycHJveCR0YXUsNywxNCkqIGRlbHRhfSAgICAgICAgICAgICAgICAgIyB0cmFuc3Rpb24genUgaGVhbCB2b24gUzEsUzIgb2RlciBTMw0KICAgICAgfQ0KICAgIH0gDQogICAgcHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbd2hpY2goaXMubmEocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbLDNdKSksM10gPSAxLWNvdW50ZXJfcHJvYiAgIyByZXN0IHdrdCBpbSBzdGF0ZSB6dSBibGVpYmVuDQogICAgY291bnRlcl9wcm9iPTANCiAgfQ0KICANCiAgcHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWw9cHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbLXdoaWNoKHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsWywzXT09MCksXQ0KICANCiAgaWYoUHJpbnQpIHByaW50KHBhc3RlKCJUaW1lIHN0ZXA6Iix0aW1lc3RlcCkpDQogIGlmKFByaW50KSBwcmludChwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dKQ0KfQ0KDQpyZXR1cm4ocHJveGVsX2xpc3QpDQp9DQpQcm94ZWxfYWxnbyhSRyxzdGFydHByb3hlbCxkZWx0YSxtYXgudHMsVCkNCmBgYA0KDQoNCipEYSBSIGVpbmlnZSBVbnRlcnNjaGllZGUgaW4gZGVyIFByb2dyYW1taWVydW5nIHp1IEMgb2RlciB2ZXJnbGVpY2hiYXJlbiBTcHJhY2hlbiBoYXQgKHouQi4gesOkaGx3ZWlzZSBzdGFydGVuZCBiZWkgMSBhbnN0YXR0IDApLCB3YXIgZXMgZsO8ciBtaWNoIGFuIGRlciBTdGVsbGUgcmVhbGlzdGlzY2hlciBzZWxic3QgZWluIFByb3hlbC1Qcm9ncmFtbSB6dSBzY2hyZWliZW4sIGFscyB3b2NoZW5sYW5nIG5hY2ggS2xlaW5pZ2tlaXRlbiBpbiBkZW4gRmVobGVybiB6dSBzdWNoZW4uKg0KKkRpZXNlciBDb2RlIGlzdCDDvGJlciBkZW4gbsOkY2hzdGVuIEJ1dHRvbiBlaW5zZWhiYXIuKg0KDQpgYGB7cn0NCm1heC50cyA9IDE1DQpkZWx0YSA9IDENCnN0YXJ0cHJveGVsPWMoMSwwLDAsMSwwKQ0KUkc9bWF0cml4KGMoMSwxLDAsMSwNCiAgICAgICAgICAgIDAsMSwxLDEsDQogICAgICAgICAgICAwLDAsMSwxLA0KICAgICAgICAgICAgMCwwLDAsMSksbmNvbCA9IDQsYnlyb3cgPSBUKQ0KDQpQcm94ZWxfYWxnbz1mdW5jdGlvbihSRyxzdGFydHByb3hlbCxkZWx0YSxtYXgudHMsUHJpbnQ9VCl7DQogIA0KdW5paHJmIDwtIGZ1bmN0aW9uKGFnZSwgYSwgYikgew0KICBpZiAoYSA8PSBhZ2UgJiYgYWdlIDwgYikgew0KICAgIHJldHVybiAoMS4wIC8gKGIgLSBhZ2UpKQ0KICB9IGVsc2Ugew0KICAgIHJldHVybiAoMCkNCiAgfQ0KfQ0KDQpleHBocmYgPC0gZnVuY3Rpb24oYWdlLCBsKSB7DQogIHJldHVybiAobCkNCn0NCiAgDQpwcm94ZWxfbGlzdD1saXN0KCkNCnByb3hlbF9saXN0W1ttYXgudHMrMV1dPWxpc3QoKQ0KcHJveGVsX2xpc3RbWzFdXT1saXN0KFNURVA9YygwKSxwcm94ZWw9ZGF0YS5mcmFtZShzdGF0ZT1zdGFydHByb3hlbFsxXSx0YXU9c3RhcnRwcm94ZWxbMl0sdGF1X2s9c3RhcnRwcm94ZWxbM10scHJvYj1zdGFydHByb3hlbFs0XSxwcmV2PXN0YXJ0cHJveGVsWzVdKSkNCmlmKFByaW50KSBwcmludCgiaW5pdGlhbCBwcm94ZWw6IikNCmlmKFByaW50KSBwcmludChwcm94ZWxfbGlzdFtbMV1dKQ0KDQpmb3IgKHRpbWVzdGVwIGluIDE6bWF4LnRzKSB7DQogIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV09bGlzdCh0aW1lc3RlcD1jKHRpbWVzdGVwKSxwcm94ZWw9ZGF0YS5mcmFtZShzdGF0ZT1udW1lcmljKCksdGF1PW51bWVyaWMoKSx0YXVfaz1udW1lcmljKCkscHJvYj1udW1lcmljKCkscHJldj1udW1lcmljKCkpKSAgICAgIyBlcnN0ZWxsZSBzY2hvbm1hbCBlaW5lIG5ldWUgbGVlcmUgbGlzdGUgZsO8ciBkZW4gbsOkY2hzdGVuIHRpbWVzdGVwDQogIA0KICBmb3IgKGwgaW4gMTpucm93KHByb3hlbF9saXN0W1t0aW1lc3RlcF1dJHByb3hlbCkpIHsNCiAgICBjdXJycHJveCA9IHByb3hlbF9saXN0W1t0aW1lc3RlcF1dJHByb3hlbFtsLF0gIyBha3R1ZWxsZXIgcHJveGVsIHp1IGRlbSBmb2xnZXByb3hlbHMgZXJ6ZXVndCB3ZXJkZW4gc29sbGVuDQogICAgZm9sZ2VyID0gUkdbYXMubnVtZXJpYyhjdXJycHJveFsxXSksXSAgICAgICAgICMgZm9sZ2VzdGF0ZXMgdm9uIGFrdHVlbGxlbSBwcm94ZWwNCiAgICANCiAgICBmb3IgKGkgaW4gMTo0KSB7DQogICAgICBpZiAoZm9sZ2VyW2ldPT0xKSB7ICAgICAjIGVyc3RlbGxlIGZvbGdlcHJveGVsIGZhbGxzIHBmZWlsIGRhaGluIGdpYnQNCiAgICAgICAgcHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbbnJvdyhwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbCkrMSwxXSA9IGkgICAgICAgICAgICAgICAgICAgICAgICAgIyBzdGF0ZSB2b20gbsOkY2hzdGVuIHByb3hlbA0KICAgICAgICANCiAgICAgICAgaWYoY3VycnByb3gkc3RhdGU9PWkpIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsW25yb3cocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWwpLDJdID0gY3VycnByb3gkdGF1ICsgZGVsdGENCiAgICAgICAgICBlbHNlIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsW25yb3cocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWwpLDJdID0gMCAgICAgICAgICAgICAgICAgICAgIyB0YXUgdm9tIG7DpGNoc3RlbiBwcm94ZWwNCiAgICAgICAgDQogICAgICAgIGlmKGN1cnJwcm94JHN0YXRlICVpbiUgYygxLDIsMykgJiBpIT00KSBwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbFtucm93KHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsKSwzXSA9IGN1cnJwcm94JHRhdV9rICsgZGVsdGENCiAgICAgICAgICBlbHNlIGlmKGN1cnJwcm94JHN0YXRlPT00ICYgaT09NCkgcHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbbnJvdyhwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbCksM10gPSBjdXJycHJveCR0YXVfayAtIGRlbHRhDQogICAgICAgICAgICBlbHNlIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsW25yb3cocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWwpLDNdID0gMCAgICAgICAgICAgICAgICAgICAjIHRhdV9rIHZvbSBuw6RjaHN0ZW4gcHJveGVsDQogICAgICAgICAgDQogICAgICAgIGlmKGN1cnJwcm94JHN0YXRlPT0xICYgaT09Mikgew0KICAgICAgICAgIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsW25yb3cocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWwpLDRdID0gKHVuaWhyZihjdXJycHJveCR0YXVfaywyLDQpICogZGVsdGEpICogY3VycnByb3gkcHJvYn0gICAgICAgICAgICAgICAgICMgdHJhbnNpdGlvbiB2b24gUzEgenUgUzINCiAgICAgICAgaWYoY3VycnByb3gkc3RhdGU9PTIgJiBpPT0zKSB7DQogICAgICAgICAgcHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbbnJvdyhwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbCksNF0gPSAoZXhwaHJmKGN1cnJwcm94JHRhdV9rLDAuMSkgKiBkZWx0YSkgKiBjdXJycHJveCRwcm9ifSAgICAgICAgICAgICAgICAgIyB0cmFuc2l0aW9uIHZvbiBTMiB6dSBTMw0KICAgICAgICBpZihjdXJycHJveCRzdGF0ZSE9NCAmIGk9PTQpIHsNCiAgICAgICAgICBwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbFtucm93KHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsKSw0XSA9ICh1bmlocmYoY3VycnByb3gkdGF1X2ssNywxNCkqIGRlbHRhKSAqIGN1cnJwcm94JHByb2J9ICAgICAgICAgICAgICAgICAjIHRyYW5zdGlvbiB6dSBoZWFsIHZvbiBTMSxTMiBvZGVyIFMzDQogICAgICAgIGlmKGN1cnJwcm94JHN0YXRlPT0xICYgaT09MSkgew0KICAgICAgICAgIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsW25yb3cocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWwpLDRdID0gKDEgLSAodW5paHJmKGN1cnJwcm94JHRhdV9rLDIsNCkgKiBkZWx0YSkgLSAodW5paHJmKGN1cnJwcm94JHRhdV9rLDcsMTQpKiBkZWx0YSkpICogY3VycnByb3gkcHJvYn0NCiAgICAgICAgaWYoY3VycnByb3gkc3RhdGU9PTIgJiBpPT0yKSB7DQogICAgICAgICAgcHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbbnJvdyhwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbCksNF0gPSAoMSAtIChleHBocmYoY3VycnByb3gkdGF1X2ssMC4xKSAqIGRlbHRhKSAtICh1bmlocmYoY3VycnByb3gkdGF1X2ssNywxNCkqIGRlbHRhKSkgKiBjdXJycHJveCRwcm9ifQ0KICAgICAgICBpZihjdXJycHJveCRzdGF0ZT09MyAmIGk9PTMpIHsNCiAgICAgICAgICBwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbFtucm93KHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsKSw0XSA9ICgxIC0gKHVuaWhyZihjdXJycHJveCR0YXVfayw3LDE0KSogZGVsdGEpKSAqIGN1cnJwcm94JHByb2J9DQogICAgICAgIGlmKGN1cnJwcm94JHN0YXRlPT00ICYgaT09NCkgew0KICAgICAgICAgIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsW25yb3cocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWwpLDRdID0gMSB9DQogICAgICAgICAgICANCiAgICAgICAgIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsW25yb3cocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWwpLDVdID0gbCAgIA0KICAgICAgICAgICAgDQogICAgICB9DQogICAgfSANCiAgfQ0KICBpZihsZW5ndGgod2hpY2gocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbLDRdPD0wKSkhPTApIHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsPXByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsWy13aGljaChwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbFssNF08PTApLF0NCiAgaWYobGVuZ3RoKHdoaWNoKHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0kcHJveGVsWywzXTwgMCkpIT0wKSBwcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbD1wcm94ZWxfbGlzdFtbdGltZXN0ZXArMV1dJHByb3hlbFstd2hpY2gocHJveGVsX2xpc3RbW3RpbWVzdGVwKzFdXSRwcm94ZWxbLDNdPCAwKSxdDQogIA0KICBpZihQcmludCkgcHJpbnQocGFzdGUoIlRpbWUgc3RlcDoiLHRpbWVzdGVwKSkNCiAgaWYoUHJpbnQpIHByaW50KHByb3hlbF9saXN0W1t0aW1lc3RlcCsxXV0pDQp9DQoNCnJldHVybihwcm94ZWxfbGlzdCkNCn0NCnByb3hlbF9saXN0PVByb3hlbF9hbGdvKFJHLHN0YXJ0cHJveGVsLGRlbHRhLG1heC50cyxGKQ0KI3Byb3hlbF9saXN0DQoNCmBgYA0KDQoNCiMjIFdoYXQgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIHBhdGllbnQgaXMgc3RpbGwgc2ljayBhZnRlciA4IGRheXMgZm9yIGRpZmZlcmVudCBkaXNjcmV0ZSB0aW1lIHN0ZXBzIChlLmcuIDIsIDEsIDAuNSwgMC4yNSwgMC4xKT8NCg0KYGBge3J9DQpQMj1Qcm94ZWxfYWxnbyhSRyxzdGFydHByb3hlbCwyLDgsRikNClAxPVByb3hlbF9hbGdvKFJHLHN0YXJ0cHJveGVsLDEsMTUsRikNClAwNT1Qcm94ZWxfYWxnbyhSRyxzdGFydHByb3hlbCwwLjUsMjksRikNClAwMjU9UHJveGVsX2FsZ28oUkcsc3RhcnRwcm94ZWwsMC4yNSw1NyxGKQ0KUDAxPVByb3hlbF9hbGdvKFJHLHN0YXJ0cHJveGVsLDAuMSw4MixGKQ0KYGBgDQpgYGB7ciBldmFsPUZBTFNFfQ0KI1AyW1s1XV0gICANCiNQMVtbOV1dICAgDQojUDA1W1sxN11dIA0KI1AwMjVbWzMzXV0NCiNQMDFbWzgxXV0gDQoNCnN1bShQMltbNV1dJHByb3hlbCRwcm9iW1AyW1s1XV0kcHJveGVsJHN0YXRlICE9IDRdKQ0Kc3VtKFAxW1s5XV0kcHJveGVsJHByb2JbUDFbWzldXSRwcm94ZWwkc3RhdGUgIT0gNF0pDQpzdW0oUDA1W1sxN11dJHByb3hlbCRwcm9iW1AwNVtbMTddXSRwcm94ZWwkc3RhdGUgIT0gNF0pDQpzdW0oUDAyNVtbMzNdXSRwcm94ZWwkcHJvYltQMDI1W1szM11dJHByb3hlbCRzdGF0ZSAhPSA0XSkNCnN1bShQMDFbWzgxXV0kcHJveGVsJHByb2JbUDAxW1s4MV1dJHByb3hlbCRzdGF0ZSAhPSA0XSkNCmBgYA0KKiBQcm9iKGR0PTIpID0gYHIgc3VtKFAyW1s1XV0kcHJveGVsJHByb2JbUDJbWzVdXSRwcm94ZWwkc3RhdGUgIT0gNF0pICoxMDBgICUNCiogUHJvYihkdD0xKSA9IGByIHN1bShQMVtbOV1dJHByb3hlbCRwcm9iW1AxW1s5XV0kcHJveGVsJHN0YXRlICE9IDRdKSAqMTAwYCAlDQoqIFByb2IoZHQ9MC41KSA9IGByIHN1bShQMDVbWzE3XV0kcHJveGVsJHByb2JbUDA1W1sxN11dJHByb3hlbCRzdGF0ZSAhPSA0XSkgKjEwMGAgJQ0KKiBQcm9iKGR0PTAuMjUpID0gYHIgc3VtKFAwMjVbWzMzXV0kcHJveGVsJHByb2JbUDAyNVtbMzNdXSRwcm94ZWwkc3RhdGUgIT0gNF0pICoxMDBgICUNCiogUHJvYihkdD0wLjEpID0gYHIgc3VtKFAwMVtbODFdXSRwcm94ZWwkcHJvYltQMDFbWzgxXV0kcHJveGVsJHN0YXRlICE9IDRdKSAqMTAwYCAlDQoNCiMjIFdoYXQgaXMgdGhlIHByb2JhYmlsaXR5IG9mIG1lYXN1cmluZyBmZXZlciBvbiB0aGUgOXRoIGRheSBmb3IgZGlmZmVyZW50IGRpc2NyZXRlIHRpbWUgc3RlcHMgKGUuZy4gMiwgMSwgMC41LCAwLjI1LCAwLjEpPyANCg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KDQpwYXN0ZSgiV2t0ID0iLHN1bShhZ2dyZWdhdGUuZGF0YS5mcmFtZShQMltbNV1dJHByb3hlbCRwcm9iLGJ5PWxpc3QoUDJbWzVdXSRwcm94ZWwkc3RhdGUpLEZVTiA9IHN1bSkkeCAqYygwLjUsMC44KSkpDQpwYXN0ZSgiV2t0ID0iLHN1bShhZ2dyZWdhdGUuZGF0YS5mcmFtZShQMVtbOV1dJHByb3hlbCRwcm9iLGJ5PWxpc3QoUDFbWzldXSRwcm94ZWwkc3RhdGUpLEZVTiA9IHN1bSkkeCAqYygwLjUsMC44LDApKSkNCnBhc3RlKCJXa3QgPSIsc3VtKGFnZ3JlZ2F0ZS5kYXRhLmZyYW1lKFAwNVtbMTddXSRwcm94ZWwkcHJvYixieT1saXN0KFAwNVtbMTddXSRwcm94ZWwkc3RhdGUpLEZVTiA9IHN1bSkkeCAqYygwLjUsMC44LDApKSkNCnBhc3RlKCJXa3QgPSIsc3VtKGFnZ3JlZ2F0ZS5kYXRhLmZyYW1lKFAwMjVbWzMzXV0kcHJveGVsJHByb2IsYnk9bGlzdChQMDI1W1szM11dJHByb3hlbCRzdGF0ZSksRlVOID0gc3VtKSR4ICpjKDAuNSwwLjgsMCkpKQ0KcGFzdGUoIldrdCA9IixzdW0oYWdncmVnYXRlLmRhdGEuZnJhbWUoUDAxW1s4MV1dJHByb3hlbCRwcm9iLGJ5PWxpc3QoUDAxW1s4MV1dJHByb3hlbCRzdGF0ZSksRlVOID0gc3VtKSR4ICpjKDAuNSwwLjgsMCkpKQ0KYGBgDQoNCiogUHJvYihkdD0yKSA9IGByIHN1bShhZ2dyZWdhdGUuZGF0YS5mcmFtZShQMltbNV1dJHByb3hlbCRwcm9iLGJ5PWxpc3QoUDJbWzVdXSRwcm94ZWwkc3RhdGUpLEZVTiA9IHN1bSkkeCAqYygwLjUsMC44KSkgKjEwMGAgJQ0KKiBQcm9iKGR0PTEpID0gYHIgc3VtKGFnZ3JlZ2F0ZS5kYXRhLmZyYW1lKFAxW1s5XV0kcHJveGVsJHByb2IsYnk9bGlzdChQMVtbOV1dJHByb3hlbCRzdGF0ZSksRlVOID0gc3VtKSR4ICpjKDAuNSwwLjgsMCkpICoxMDBgICUNCiogUHJvYihkdD0wLjUpID0gYHIgc3VtKGFnZ3JlZ2F0ZS5kYXRhLmZyYW1lKFAwNVtbMTddXSRwcm94ZWwkcHJvYixieT1saXN0KFAwNVtbMTddXSRwcm94ZWwkc3RhdGUpLEZVTiA9IHN1bSkkeCAqYygwLjUsMC44LDApKSAqMTAwYCAlDQoqIFByb2IoZHQ9MC4yNSkgPSBgciBzdW0oYWdncmVnYXRlLmRhdGEuZnJhbWUoUDAyNVtbMzNdXSRwcm94ZWwkcHJvYixieT1saXN0KFAwMjVbWzMzXV0kcHJveGVsJHN0YXRlKSxGVU4gPSBzdW0pJHggKmMoMC41LDAuOCwwKSkgKjEwMGAgJQ0KKiBQcm9iKGR0PTAuMSkgPSBgciBzdW0oYWdncmVnYXRlLmRhdGEuZnJhbWUoUDAxW1s4MV1dJHByb3hlbCRwcm9iLGJ5PWxpc3QoUDAxW1s4MV1dJHByb3hlbCRzdGF0ZSksRlVOID0gc3VtKSR4ICpjKDAuNSwwLjgsMCkpICoxMDBgICUNCg0KIyMgV2hhdCBpcyB0aGUgZXhwZWN0ZWQgZHVyYXRpb24gdW50aWwgaGVhbGluZyB3aXRoIHByb2JhYmlsaXR5IDk5JSBmb3IgZGlmZmVyZW50IGRpc2NyZXRlIHRpbWUgc3RlcHMgKGUuZy4gMiwgMSwgMC41LCAwLjI1LCAwLjEpPw0KDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQppPTcNCiN3aGlsZSAoc3VtKFAyW1tpXV0kcHJveGVsJHByb2JbUDJbW2ldXSRwcm94ZWwkc3RhdGUgIT0gNF0pID4gMC4wMSApIGk9aSsxDQpQMltbOF1dJHByb3hlbFtQMltbOF1dJHByb3hlbCRzdGF0ZSAhPSA0LF0NCnByaW50KHBhc3RlKCJGw7xyIDIgQW4gVGFnOiIsKGktMSkqMikpICMjIG5hY2ggVGFnIDE0DQoNCmk9MQ0Kd2hpbGUgKHN1bShQMVtbaV1dJHByb3hlbCRwcm9iW1AxW1tpXV0kcHJveGVsJHN0YXRlICE9IDRdKSA+IDAuMDEgKSBpPWkrMQ0KUDFbW2ldXSRwcm94ZWxbUDFbW2ldXSRwcm94ZWwkc3RhdGUgIT0gNCxdDQpwcmludChwYXN0ZSgiRsO8ciAxIEFuIFRhZzoiLChpLTEpKjEpKQ0KDQppPTENCndoaWxlIChzdW0oUDA1W1tpXV0kcHJveGVsJHByb2JbUDA1W1tpXV0kcHJveGVsJHN0YXRlICE9IDRdKSA+IDAuMDEgKSBpPWkrMQ0KUDA1W1tpXV0kcHJveGVsW1AwNVtbaV1dJHByb3hlbCRzdGF0ZSAhPSA0LF0NCnByaW50KHBhc3RlKCJGw7xyIC41IEFuIFRhZzoiLChpLTEpKjAuNSkpDQoNCmk9MQ0Kd2hpbGUgKHN1bShQMDI1W1tpXV0kcHJveGVsJHByb2JbUDAyNVtbaV1dJHByb3hlbCRzdGF0ZSAhPSA0XSkgPiAwLjAxICkgaT1pKzENClAwMjVbW2ldXSRwcm94ZWxbUDAyNVtbaV1dJHByb3hlbCRzdGF0ZSAhPSA0LF0NCnByaW50KHBhc3RlKCJGw7xyIC4yNSBBbiBUYWc6IiwoaS0xKSowLjI1KSkNCmBgYA0KDQoqIEbDvHIgMiBBbiBUYWc6IDEyDQoqIEbDvHIgMSBBbiBUYWc6IDE0DQoqIEbDvHIgMC41IEFuIFRhZzogMTQNCiogRsO8ciAwLjI1IEFuIFRhZzogMTQNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=