library(binom)
library(collapsibleTree)
library(dbplyr)
library(devtools)
library(dplyr)
library(EnvStats)
library(ggformula)
library(ggplot2)
library(ggpubr)
library(htmltools)
library(ISLR)
library(knitr)
library(lawstat)
library(markdown)
library(mosaic)
library(mdsr)
library(mosaicData)
library(nycflights13)
library(plyr)
library(purrr)
library(rmarkdown)
library(stringi)
library(tibble)
library(tidyr)
library(tidyselect)
library(tinytex)
library(yaml)

Q1 a.

0.4 * 0.4
[1] 0.16

\[ P(X=2) = 0.1600 \] b.

(1-0.4) * (1-0.4)
[1] 0.36

\[ P(X=0) = 0.3600 \] c.

choose(2,1)*0.4*(1-0.4) + choose(2,2)*0.4*(1-0.4)
[1] 0.72

\[ P(X\geq1) = 0.7200 \] d. \[ P(1 \leq X \leq n) = 0.95 \] \[ Then \; P(X=0) = 1 - P(1 \leq X \leq n) = 0.05 \]

\[ P(X=0)=0.4^n = 0.05 \] \[ Then \; \ln{0.4^n} = n\ln{0.4} = \ln{0.05} \] \[ Then \; n = \ln{0.05} / \ln{0.4} \]

log(0.05) / log(0.4)
[1] 3.269412

\[ n = 3.2694 \approx 4 \] Q2

Step 1: Create a series of vectors to hold output

nsims = 1000  # the number of simulations
outcome = numeric(nsims) #create empty vector that will be filled with numeric outcomes

Step 2: Run the Simulation

for(i in 1:nsims){ #we are going to perform the body of the loop 1000 times
  outcome[i] = sample(c(1,2,3,4,5,6), 1, replace=FALSE) #stores the outcome of the ith toss in position i of outcome
  }  #close the for-loop
simresult = data.frame(outcome) #creates a data frame with two columns
head(simresult,3)  #shows the first three rows of the data frame, outcome of each die toss in column 2
tail(simresult,3)  #shows the last three rows of the data frame, die toss outcome in column 2

Step 3: Visualize the Simulation with ggplot2

sum(simresult$outcome)  #computes the sum of the 1000 tosses appearing in the outcome variable of simresult data frame
[1] 3580
ggplot(data = simresult, aes(x = outcome, fill = outcome)) + geom_histogram(col = 'black', fill = "red", binwidth = 1)

Step 4: Using Simulation to Compute a Probability

nsims = 3000  # the number of simulations
outcome = numeric(nsims) #create empty vector that will be filled with numeric outcomes
fivesix = numeric(nsims) #create empty vector that will be filled with outcomes of five or six 
for(i in 1:nsims){ #we are going to perform the body of the loop 1000 times
  outcome[i] = sample(c(1,2,3,4,5,6), 1, replace=FALSE) #stores the outcome of the ith toss in position i of outcome
  fivesix[i] = if (outcome[i] == 5 || outcome[i] == 6) 1 else 0 #stores the outcome of five or six 
  }  #close the for-loop
simresult = data.frame(outcome) #creates a data frame with two columns
head(simresult,3)  #shows the first three rows of the data frame, outcome of each die toss in column 2
simresultfivesix = data.frame(fivesix)
head(simresultfivesix, 10)
nsims = 3000  # the number of simulations
outcome1 = numeric(nsims) #create empty vector that will be filled with numeric outcomes
toss1 = numeric(nsims) #create empty vector that will be filled with outcomes of toss1
toss2 = numeric(nsims) #create empty vector that will be filled with outcomes of toss2
toss3 = numeric(nsims) #create empty vector that will be filled with outcomes of toss3
for(i in 1:nsims){ #we are going to perform the body of the loop 1000 times
  toss1[i] = sample(c(1,2,3,4,5,6), 1, replace=FALSE) #stores the outcome of the ith toss1 in position i of outcome
  toss2[i] = sample(c(1,2,3,4,5,6), 1, replace=FALSE) #stores the outcome of the ith toss2 in position i of outcome
  toss3[i] = sample(c(1,2,3,4,5,6), 1, replace=FALSE) #stores the outcome of the ith toss2 in position i of outcome
  outcome1[i] = if (toss1[i]+toss2[i]+toss3[i] >= 14 ) 1 else 0 #stores the outcome of five or six 
  }  #close the for-loop
simresult1 = data.frame(outcome1) #creates a data frame with two columns
head(simresult1,10)  #shows the first three rows of the data frame, outcome of each die toss in column 2
tail(simresult1, 10)
sum(simresult1$outcome1)  #computes the sum of the 3000 tosses appearing in the outcome variable of simresult1 data frame
[1] 495
495 / 3000
[1] 0.165

\[ P(Sum \geq 14) = 0.165 \]

Q3

  1. Compute the probability that your hand will have neither ♠s nor ♣s.
(choose(10,1)*choose(10,4) + choose(10,2)*choose(10,3) + choose(10,3)*choose(10,2) + choose(10,4)*choose(10,1) + choose(10,5)) / choose(20,5)
[1] 0.9837461

\[ P(♠s \; or \; ♣s) = 0.9837461 \]

  1. Compute the probability your hand will consist of a 10, Jack, Queen, King, and Ace of the same suit. One example of such a hand is: (10♡,J♡,Q♡,K♡,Ace♡).
 4 / choose(20,5)
[1] 0.0002579979

\[ P(suits) = 0.0002579979 \approx 0.0003 \]

  1. Compute the probability that you get a three-of-a-kind. For example, (10♡, 10♢, 10♠, J♣, K♡).
choose(4,3)*choose(16,2)*5 / choose(20,5)  #calculate probability all three of a kind hands, times 5 because there are 10, Jack, Queen, King, Ace, 5 kinds
[1] 0.1547988

\[ P(three of a kind) = 0.1547988 \approx 0.1548 \]

  1. Compute probability that one observes two Aces and two ♢’s.
choose(4,2)*choose(5,2)*choose(11,1) / choose(20,5)
[1] 0.04256966

\[ P(two Aces and two ♢s) = 0.04256966 \approx 0.0426 \] Q4

  1. The executive has called the office of the lobby-group to say they have missed their connecting flight. Compute the probability that the executive called from Chicago (or is flying Airline UA).

\[ P(AA) = 0.15 \;\; P(UA) = x \;\; P(D) = 3x \] P(AA) + P(UA) + P(D) = 1, Then 0.15 + x + 3x = 1

(1-0.15) / 4 #solving x
[1] 0.2125

\[ P(UA) = 0.2125 \]

0.2125 * 3 #determine P(D)
[1] 0.6375

\[ P(D) = 0.6375 \]

(0.2125*0.3) / ((0.2125*0.3) + (0.15*0.15) + (0.6375*0.1)) #calculate P(Chicago) 
[1] 0.425

\[ P(Chicago) = 0.425 \] b. The executive has not missed a connecting flight and made it to IAD. Compute the probability that they flew on a Delta flight

(0.6375*0.9) / ((0.2125*0.7) + (0.15*0.85) + (0.6375*0.9))
[1] 0.675

\[ P(Minneapolis-St.Paul) = 0.675 \] c. Provide a statement that interprets the meaning of the probability computed in (b) in the context of these data.

Ans: The executive will most likey flying with Detal airline because the probability is over 50% and Detal airline has the best chance of getting on the connecting flight and arriving in IAD.

Q5.

a.Using R Studio, create a display that shows the probability distribution of this particular random variable X. Refer to the various code provided for examples appearing in both Probability Module 4 and Review Exercise 5 from Thursday, September 10th. For values of x, use xvalues = 0:15.

pdf1 <- function(x) # create a probablity distribution function of 2 / 3^(x+1)
{
  2 / (3^(x+1))
}
curve(pdf1, 0, 15, xlab="Values of X", ylab="Values of pdf1(x)", main="Distribution of X", col='red')

  1. Compute P(X>3)
integrate(pdf1, lower=3, upper=15)$value
[1] 0.022475

\[ P(X>3) = 0.022475 \] c. Compute the mean or expected value of X, E(X) or μX. (Hint: In computing E(X), change the upper limit on xvalues from 15 to 50…)

pdf1mean <- function(x) #create a funiction of x*pdf1(x) so that it can be integrated using integrate commande with lower=0 and upper=50
{
  x*pdf1(x)
}
integrate(pdf1mean, lower=0, upper=50)$value
[1] 0.552357

\[ E(X) \; or \; \mu{x} = 0.552357 \] d. Compute the standard deviation of X, SD(X) or σX. (use the same values of x as you did in part (c))

pdf1sd <- function(x) #create a function of x^2 * pdf1(x) so that it can be integrated using integrate commande with lower=0 and upper=50
{
  x*pdf1mean(x)
}
sqrt(integrate(pdf1sd, lower=0, upper=50)$value - (integrate(pdf1mean, lower=0, upper=50)$value)^2)
[1] 0.8369323

\[ SD(X) \; = \; 0.8369323 \]

e.Consider the interval (μx−σx, μx+σx). Compute P(μx−σx <X< μx+σx)

0.552357 - 0.8369323
[1] -0.2845753

\[ \mu{x} - σx = -0.2845753 \]

integrate(pdf1, lower=(0), upper=(0.552357+0.8369323))$value
[1] 0.4749383

Q6.

pdf2 <- function(n,x) #create the function for the probability of number of canadians disagree with internet companies 
{
  choose(n,x)*(0.6^x)*(0.4^(n-x))
}
pdf2(40,30) #calculate exactly 30 will disagree with internet companies handing over private information to authorities
[1] 0.01964986
p2835 = 0           #define a variable stores P(28 =< x <= 35)
for (i in 28:35)    #for loop to calculate P(x = 28), P(x = 29)...P(x = 35) and sum them up
{
  p2835 = p2835 + pdf2(40,i) #sum up P(x = 28), P(x = 29)...P(x = 35) and stores the total in p2835
}
p2835
[1] 0.1284811
p15 = 0
for (i in 15:25)    
{
  p15 = p15 + pdf2(i,15) 
}
p15
[1] 0.868853

\[ P(15th \; person \; disagree) = 0.868853 \]

OddPersonOut <- function(x)
{
  0.6875^(x-1)*0.3125
}
OddPersonOut(10)
[1] 0.0107227

\[ P(x=10) = 0.0107227 \]

OddPersonOutMean <- function(x)
{
  x * OddPersonOut(x)
}

integrate(OddPersonOutMean, lower=1, upper=50)$value
[1] 3.059875

\[ E(X) = 3.059875 \; trials \]

Ans: when x >=50, expected trails to obersve “odd person out” converges to 3.059875, then yes, 10 trails is more than expected to observe “Odd person out”

Q8.

pnorm(1.91, 1.89, 0.05) - pnorm(1.83, 1.89, 0.05)
[1] 0.5403521

\[ P(1.83 \leq x \leq 1.91) = 0.5403521 \]

qnorm(0.9, 1.89, 0.05)
[1] 1.954078

Interpretation: 90% of 2-liter bottles have 1.954078 liter or less soft drink filled.

1 - pnorm(2, 1.89, 0.05) #calculate the probability of 2-liter botters being overfilled
[1] 0.01390345

\[ P(x > 2) = 0.01390345 \]

pnorm(1.85, 1.89, 0.05) #calculate the probability of 2-liter bottle has less than 1.85 liters of soft-drink filled
[1] 0.2118554
1 - pnorm(1.85, 1.89, 0.05) #calculate the probability of a 2-liter bottle has more than 1.85 liters of soft-drink filled
[1] 0.7881446
P510 = 0 
for (i in 5:10)
{
  P510 = P510 + choose(50,i)*(0.2118554^i)*(0.7881446^(50-i))
}
P510
[1] 0.4892489

\[ P( Between \; 5 \; and \; 10 \; bottles \; have \; less \; 1.85 \; liters \; of \; soft \; drink) = 0.4892489 \]

Q9.

gss = read.csv("http://people.ucalgary.ca/~jbstall/DataFiles/GSS2002.csv")
head(gss, 4)
ggplot(data=gss, aes(x = Religion, fill=Religion)) + geom_bar(position="dodge", na.rm=TRUE) + theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())

counts=as.data.frame(sort(table(gss$Religion)))
head(counts, 4)
ggplot(data = gss, aes(x = Education, fill = Race)) + geom_bar(position = "dodge", na.rm = TRUE)

Interpretation: White people are majority population in each education level, then followed by black people.

ggplot(data=gss, aes(x = Marital, fill = Education)) + geom_bar(position = "dodge", na.rm=TRUE) 

The plot above shows that each marital category has similar distribution in each education level. Majority of population has HS, then Bachelors, Left HS, Graduate,…, only exception is Widowed, it has Left HS come in as second.

ggplot(data=gss, aes(x = Education, fill = Marital)) + geom_bar(position = "dodge", na.rm=TRUE)

Second plot shows each education level has similar distribution in each marital category. Majority people in each education level are married and followed by Never Married, Divorced, Widowed, etc.

ggplot(data=gss, aes(x = Gender, fill=Politics)) + geom_bar(position = "dodge", na.rm=TRUE) 

It seems like Female and Male has similar distribution across different politics. Majority of them are Moderate, and followed by Conservative, Slightly conservative, Slightly liberal. Wemon has higher probability than men to be conservative(including Extremely conservative, Conservative, slightly conservative)

library(ISLR)
head(Default, 4) #shows the first four lines of the Default data set
ggplot(data=Default, aes(x = balance, y = income, color = student)) + geom_point(size = 2, position = "jitter") + xlab("Balance") + ylab("Income") + ggtitle("Monthly Income vs Monthly Credit Card Balance")

ggplot(data=Default, aes(x= student, y=balance, color = student)) + geom_boxplot(na.rm=TRUE) + xlab("Student Status") + ylab("Monthly Balance")

mean(~balance, data=Default, na.rm=TRUE)   #calculate the mean of balances from the data frame Default
[1] 835.3749
median(~balance, data=Default, na.rm=TRUE)  #calculate the mean of balances from the data frame Default
[1] 823.637
sd(~balance, data=Default, na.rm=TRUE)
[1] 483.715
balancedata = c(Default$balance)  #create a vector that stores all balances from data frame Default
quantile(balancedata, 0.05)   #calculate 5th percentiles of all balances
       5% 
0.4246597 
quantile(balancedata, 0.95)
     95% 
1665.963 

Q11.

courier <- read.csv('Data602Assignment1Question11.csv', header = TRUE)
courier = courier %>% mutate(Courier = "Local Courier")
courier
ggplot(data = courier, aes(x = Courier , y = Delivery_time)) + geom_violin(col = "blue", fill = "red", na.rm = TRUE) + xlab("Courier") + ylab("Delivery time") + ggtitle("Voilin plot of this courier delivery time")

mean(~Delivery_time, data = courier, na.rm = TRUE)
[1] 5.6875
median(~Delivery_time, data = courier, na.rm = TRUE)
[1] 5.775
sd(~Delivery_time, data = courier, na.rm = TRUE)
[1] 1.580369
qdata(~Delivery_time, c(0.25, 0.75), data = courier)
  25%   75% 
4.750 6.565 
qdata(~Delivery_time, 0.99, data = courier)
   99% 
7.9778 
qnorm(0.99, 5, 1.5)
[1] 8.489522

Because the amount of delivery time can be modeled by the Normal distribution with a mean delivery time of 5 hours and a standard deviation of 1.2 hours, so 99th percentile is 8.489522 hours, which means all 99% of packages will be delivered within 8.489522 hours or less. Anything is over this delivery time will be refunded.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoYmlub20pCmxpYnJhcnkoY29sbGFwc2libGVUcmVlKQpsaWJyYXJ5KGRicGx5cikKbGlicmFyeShkZXZ0b29scykKbGlicmFyeShkcGx5cikKbGlicmFyeShFbnZTdGF0cykKbGlicmFyeShnZ2Zvcm11bGEpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkoaHRtbHRvb2xzKQpsaWJyYXJ5KElTTFIpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkobGF3c3RhdCkKbGlicmFyeShtYXJrZG93bikKbGlicmFyeShtb3NhaWMpCmxpYnJhcnkobWRzcikKbGlicmFyeShtb3NhaWNEYXRhKQpsaWJyYXJ5KG55Y2ZsaWdodHMxMykKbGlicmFyeShwbHlyKQpsaWJyYXJ5KHB1cnJyKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeShzdHJpbmdpKQpsaWJyYXJ5KHRpYmJsZSkKbGlicmFyeSh0aWR5cikKbGlicmFyeSh0aWR5c2VsZWN0KQpsaWJyYXJ5KHRpbnl0ZXgpCmxpYnJhcnkoeWFtbCkKYGBgCgpRMSAKYS4gCmBgYHtyfQowLjQgKiAwLjQKYGBgCiQkIFAoWD0yKSA9IDAuMTYwMCAkJApiLgpgYGB7cn0KKDEtMC40KSAqICgxLTAuNCkKYGBgCgokJCBQKFg9MCkgPSAwLjM2MDAgJCQKYy4KYGBge3J9CmNob29zZSgyLDEpKjAuNCooMS0wLjQpICsgY2hvb3NlKDIsMikqMC40KigxLTAuNCkKYGBgCiQkIFAoWFxnZXExKSA9IDAuNzIwMCAkJApkLgokJCBQKDEgXGxlcSBYIFxsZXEgbikgPSAwLjk1ICQkCiQkIFRoZW4gXDsgUChYPTApID0gMSAtIFAoMSBcbGVxIFggXGxlcSBuKSA9IDAuMDUgJCQKCiQkIFAoWD0wKT0wLjRebiA9IDAuMDUgJCQKJCQgVGhlbiBcOyBcbG57MC40Xm59ID0gblxsbnswLjR9ID0gXGxuezAuMDV9ICAkJAokJCBUaGVuIFw7ICBuID0gXGxuezAuMDV9IC8gXGxuezAuNH0gICQkCmBgYHtyfQpsb2coMC4wNSkgLyBsb2coMC40KQpgYGAKJCQgbiA9IDMuMjY5NCBcYXBwcm94IDQgJCQKUTIKClN0ZXAgMTogQ3JlYXRlIGEgc2VyaWVzIG9mIHZlY3RvcnMgdG8gaG9sZCBvdXRwdXQKYGBge3J9Cm5zaW1zID0gMTAwMCAgIyB0aGUgbnVtYmVyIG9mIHNpbXVsYXRpb25zCm91dGNvbWUgPSBudW1lcmljKG5zaW1zKSAjY3JlYXRlIGVtcHR5IHZlY3RvciB0aGF0IHdpbGwgYmUgZmlsbGVkIHdpdGggbnVtZXJpYyBvdXRjb21lcwpgYGAKClN0ZXAgMjogUnVuIHRoZSBTaW11bGF0aW9uCmBgYHtyfQpmb3IoaSBpbiAxOm5zaW1zKXsgI3dlIGFyZSBnb2luZyB0byBwZXJmb3JtIHRoZSBib2R5IG9mIHRoZSBsb29wIDEwMDAgdGltZXMKICBvdXRjb21lW2ldID0gc2FtcGxlKGMoMSwyLDMsNCw1LDYpLCAxLCByZXBsYWNlPUZBTFNFKSAjc3RvcmVzIHRoZSBvdXRjb21lIG9mIHRoZSBpdGggdG9zcyBpbiBwb3NpdGlvbiBpIG9mIG91dGNvbWUKICB9ICAjY2xvc2UgdGhlIGZvci1sb29wCnNpbXJlc3VsdCA9IGRhdGEuZnJhbWUob3V0Y29tZSkgI2NyZWF0ZXMgYSBkYXRhIGZyYW1lIHdpdGggdHdvIGNvbHVtbnMKaGVhZChzaW1yZXN1bHQsMykgICNzaG93cyB0aGUgZmlyc3QgdGhyZWUgcm93cyBvZiB0aGUgZGF0YSBmcmFtZSwgb3V0Y29tZSBvZiBlYWNoIGRpZSB0b3NzIGluIGNvbHVtbiAyCmBgYAoKYGBge3J9CnRhaWwoc2ltcmVzdWx0LDMpICAjc2hvd3MgdGhlIGxhc3QgdGhyZWUgcm93cyBvZiB0aGUgZGF0YSBmcmFtZSwgZGllIHRvc3Mgb3V0Y29tZSBpbiBjb2x1bW4gMgpgYGAKClN0ZXAgMzogVmlzdWFsaXplIHRoZSBTaW11bGF0aW9uIHdpdGggZ2dwbG90MgpgYGB7cn0Kc3VtKHNpbXJlc3VsdCRvdXRjb21lKSAgI2NvbXB1dGVzIHRoZSBzdW0gb2YgdGhlIDEwMDAgdG9zc2VzIGFwcGVhcmluZyBpbiB0aGUgb3V0Y29tZSB2YXJpYWJsZSBvZiBzaW1yZXN1bHQgZGF0YSBmcmFtZQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IHNpbXJlc3VsdCwgYWVzKHggPSBvdXRjb21lLCBmaWxsID0gb3V0Y29tZSkpICsgZ2VvbV9oaXN0b2dyYW0oY29sID0gJ2JsYWNrJywgZmlsbCA9ICJyZWQiLCBiaW53aWR0aCA9IDEpCmBgYApTdGVwIDQ6IFVzaW5nIFNpbXVsYXRpb24gdG8gQ29tcHV0ZSBhIFByb2JhYmlsaXR5CmBgYHtyfQpuc2ltcyA9IDMwMDAgICMgdGhlIG51bWJlciBvZiBzaW11bGF0aW9ucwpvdXRjb21lID0gbnVtZXJpYyhuc2ltcykgI2NyZWF0ZSBlbXB0eSB2ZWN0b3IgdGhhdCB3aWxsIGJlIGZpbGxlZCB3aXRoIG51bWVyaWMgb3V0Y29tZXMKZml2ZXNpeCA9IG51bWVyaWMobnNpbXMpICNjcmVhdGUgZW1wdHkgdmVjdG9yIHRoYXQgd2lsbCBiZSBmaWxsZWQgd2l0aCBvdXRjb21lcyBvZiBmaXZlIG9yIHNpeCAKYGBgCmBgYHtyfQpmb3IoaSBpbiAxOm5zaW1zKXsgI3dlIGFyZSBnb2luZyB0byBwZXJmb3JtIHRoZSBib2R5IG9mIHRoZSBsb29wIDEwMDAgdGltZXMKICBvdXRjb21lW2ldID0gc2FtcGxlKGMoMSwyLDMsNCw1LDYpLCAxLCByZXBsYWNlPUZBTFNFKSAjc3RvcmVzIHRoZSBvdXRjb21lIG9mIHRoZSBpdGggdG9zcyBpbiBwb3NpdGlvbiBpIG9mIG91dGNvbWUKICBmaXZlc2l4W2ldID0gaWYgKG91dGNvbWVbaV0gPT0gNSB8fCBvdXRjb21lW2ldID09IDYpIDEgZWxzZSAwICNzdG9yZXMgdGhlIG91dGNvbWUgb2YgZml2ZSBvciBzaXggCiAgfSAgI2Nsb3NlIHRoZSBmb3ItbG9vcApzaW1yZXN1bHQgPSBkYXRhLmZyYW1lKG91dGNvbWUpICNjcmVhdGVzIGEgZGF0YSBmcmFtZSB3aXRoIHR3byBjb2x1bW5zCmhlYWQoc2ltcmVzdWx0LDMpICAjc2hvd3MgdGhlIGZpcnN0IHRocmVlIHJvd3Mgb2YgdGhlIGRhdGEgZnJhbWUsIG91dGNvbWUgb2YgZWFjaCBkaWUgdG9zcyBpbiBjb2x1bW4gMgpgYGAKYGBge3J9CnNpbXJlc3VsdGZpdmVzaXggPSBkYXRhLmZyYW1lKGZpdmVzaXgpCmhlYWQoc2ltcmVzdWx0Zml2ZXNpeCwgMTApCmBgYApgYGB7cn0KbnNpbXMgPSAzMDAwICAjIHRoZSBudW1iZXIgb2Ygc2ltdWxhdGlvbnMKb3V0Y29tZTEgPSBudW1lcmljKG5zaW1zKSAjY3JlYXRlIGVtcHR5IHZlY3RvciB0aGF0IHdpbGwgYmUgZmlsbGVkIHdpdGggbnVtZXJpYyBvdXRjb21lcyBvZiB0aHJlZSB0b3NzZXMKdG9zczEgPSBudW1lcmljKG5zaW1zKSAjY3JlYXRlIGVtcHR5IHZlY3RvciB0aGF0IHdpbGwgYmUgZmlsbGVkIHdpdGggb3V0Y29tZXMgb2YgdG9zczEKdG9zczIgPSBudW1lcmljKG5zaW1zKSAjY3JlYXRlIGVtcHR5IHZlY3RvciB0aGF0IHdpbGwgYmUgZmlsbGVkIHdpdGggb3V0Y29tZXMgb2YgdG9zczIKdG9zczMgPSBudW1lcmljKG5zaW1zKSAjY3JlYXRlIGVtcHR5IHZlY3RvciB0aGF0IHdpbGwgYmUgZmlsbGVkIHdpdGggb3V0Y29tZXMgb2YgdG9zczMKYGBgCgpgYGB7cn0KZm9yKGkgaW4gMTpuc2ltcyl7ICN3ZSBhcmUgZ29pbmcgdG8gcGVyZm9ybSB0aGUgYm9keSBvZiB0aGUgbG9vcCAxMDAwIHRpbWVzCiAgdG9zczFbaV0gPSBzYW1wbGUoYygxLDIsMyw0LDUsNiksIDEsIHJlcGxhY2U9RkFMU0UpICNzdG9yZXMgdGhlIG91dGNvbWUgb2YgdGhlIGl0aCB0b3NzMSBpbiBwb3NpdGlvbiBpIG9mIG91dGNvbWUKICB0b3NzMltpXSA9IHNhbXBsZShjKDEsMiwzLDQsNSw2KSwgMSwgcmVwbGFjZT1GQUxTRSkgI3N0b3JlcyB0aGUgb3V0Y29tZSBvZiB0aGUgaXRoIHRvc3MyIGluIHBvc2l0aW9uIGkgb2Ygb3V0Y29tZQogIHRvc3MzW2ldID0gc2FtcGxlKGMoMSwyLDMsNCw1LDYpLCAxLCByZXBsYWNlPUZBTFNFKSAjc3RvcmVzIHRoZSBvdXRjb21lIG9mIHRoZSBpdGggdG9zczIgaW4gcG9zaXRpb24gaSBvZiBvdXRjb21lCiAgb3V0Y29tZTFbaV0gPSBpZiAodG9zczFbaV0rdG9zczJbaV0rdG9zczNbaV0gPj0gMTQgKSAxIGVsc2UgMCAjc3RvcmVzIHRoZSBvdXRjb21lIG9mIGZpdmUgb3Igc2l4IAogIH0gICNjbG9zZSB0aGUgZm9yLWxvb3AKYGBgCgpgYGB7cn0Kc2ltcmVzdWx0MSA9IGRhdGEuZnJhbWUob3V0Y29tZTEpICNjcmVhdGVzIGEgZGF0YSBmcmFtZSB3aXRoIHR3byBjb2x1bW5zCmhlYWQoc2ltcmVzdWx0MSwxMCkgICNzaG93cyB0aGUgZmlyc3QgdGhyZWUgcm93cyBvZiB0aGUgZGF0YSBmcmFtZSwgb3V0Y29tZSBvZiBlYWNoIGRpZSB0b3NzIGluIGNvbHVtbiAyCmBgYApgYGB7cn0KdGFpbChzaW1yZXN1bHQxLCAxMCkKYGBgCmBgYHtyfQpzdW0oc2ltcmVzdWx0MSRvdXRjb21lMSkgICNjb21wdXRlcyB0aGUgc3VtIG9mIHRoZSAzMDAwIHRvc3NlcyBhcHBlYXJpbmcgaW4gdGhlIG91dGNvbWUgdmFyaWFibGUgb2Ygc2ltcmVzdWx0MSBkYXRhIGZyYW1lCmBgYApgYGB7cn0KNDk1IC8gMzAwMApgYGAKCiQkIFAoU3VtIFxnZXEgMTQpID0gMC4xNjUgJCQKClEzCgphLiBDb21wdXRlIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHlvdXIgaGFuZCB3aWxsIGhhdmUgbmVpdGhlciDimaBzIG5vciDimaNzLgpgYGB7cn0KKGNob29zZSgxMCwxKSpjaG9vc2UoMTAsNCkgKyBjaG9vc2UoMTAsMikqY2hvb3NlKDEwLDMpICsgY2hvb3NlKDEwLDMpKmNob29zZSgxMCwyKSArIGNob29zZSgxMCw0KSpjaG9vc2UoMTAsMSkgKyBjaG9vc2UoMTAsNSkpIC8gY2hvb3NlKDIwLDUpIApgYGAKCiQkIFAo4pmgcyBcOyBvciBcOyDimaNzKSA9IDAuOTgzNzQ2MSAkJAoKYi4gQ29tcHV0ZSB0aGUgcHJvYmFiaWxpdHkgeW91ciBoYW5kIHdpbGwgY29uc2lzdCBvZiBhIDEwLCBKYWNrLCBRdWVlbiwgS2luZywgYW5kIEFjZSBvZiB0aGUgc2FtZSBzdWl0LiBPbmUgZXhhbXBsZSBvZiBzdWNoIGEgaGFuZCBpczogKDEw4pmhLErimaEsUeKZoSxL4pmhLEFjZeKZoSkuCgpgYGB7cn0KY2hvb3NlKDQsMSkgLyBjaG9vc2UoMjAsNSkgI09ubHkgZm91ciBzdWl0cyBmcm9tIHRob3NlIDIwIGNhcmRzLCBzbyBQKHN1aXRzKSBpcyBjYWxjdWxhdGVkIHRoaXMgd2F5CmBgYAoKJCQgUChzdWl0cykgPSAwLjAwMDI1Nzk5NzkgXGFwcHJveCAwLjAwMDMgJCQKCmMuIENvbXB1dGUgdGhlIHByb2JhYmlsaXR5IHRoYXQgeW91IGdldCBhIHRocmVlLW9mLWEta2luZC4gRm9yIGV4YW1wbGUsICgxMOKZoSwgMTDimaIsIDEw4pmgLCBK4pmjLCBL4pmhKS4KYGBge3J9CmNob29zZSg0LDMpKmNob29zZSgxNiwyKSo1IC8gY2hvb3NlKDIwLDUpICAjY2FsY3VsYXRlIHByb2JhYmlsaXR5IGFsbCB0aHJlZSBvZiBhIGtpbmQgaGFuZHMsIHRpbWVzIDUgYmVjYXVzZSB0aGVyZSBhcmUgMTAsIEphY2ssIFF1ZWVuLCBLaW5nLCBBY2UsIDUga2luZHMKYGBgCiQkIFAodGhyZWUgb2YgYSBraW5kKSA9IDAuMTU0Nzk4OCBcYXBwcm94IDAuMTU0OCAkJAoKZC4gQ29tcHV0ZSBwcm9iYWJpbGl0eSB0aGF0IG9uZSBvYnNlcnZlcyB0d28gQWNlcyBhbmQgdHdvIOKZouKAmXMuCgpgYGB7cn0KY2hvb3NlKDQsMikqY2hvb3NlKDUsMikqY2hvb3NlKDExLDEpIC8gY2hvb3NlKDIwLDUpCmBgYAokJCBQKHR3byBBY2VzIGFuZCB0d28g4pmicykgPSAwLjA0MjU2OTY2IFxhcHByb3ggMC4wNDI2ICQkClE0CgphLiBUaGUgZXhlY3V0aXZlIGhhcyBjYWxsZWQgdGhlIG9mZmljZSBvZiB0aGUgbG9iYnktZ3JvdXAgdG8gc2F5IHRoZXkgaGF2ZSBtaXNzZWQgdGhlaXIgY29ubmVjdGluZyBmbGlnaHQuIENvbXB1dGUgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIGV4ZWN1dGl2ZSBjYWxsZWQgZnJvbSBDaGljYWdvIChvciBpcyBmbHlpbmcgQWlybGluZSBVQSkuCgoKJCQgUChBQSkgPSAwLjE1IFw7XDsgUChVQSkgPSB4IFw7XDsgUChEKSA9IDN4ICQkClAoQUEpICsgUChVQSkgKyBQKEQpID0gMSwgVGhlbiAwLjE1ICsgeCArIDN4ID0gMQpgYGB7cn0KKDEtMC4xNSkgLyA0ICNzb2x2aW5nIHgKYGBgCiQkIFAoVUEpID0gMC4yMTI1ICQkIAoKYGBge3J9CjAuMjEyNSAqIDMgI2RldGVybWluZSBQKEQpCmBgYAokJCBQKEQpID0gMC42Mzc1ICQkIApgYGB7cn0KKDAuMjEyNSowLjMpIC8gKCgwLjIxMjUqMC4zKSArICgwLjE1KjAuMTUpICsgKDAuNjM3NSowLjEpKSAjY2FsY3VsYXRlIFAoQ2hpY2FnbykgCmBgYAoKJCQgUChDaGljYWdvKSA9IDAuNDI1ICQkCmIuIFRoZSBleGVjdXRpdmUgaGFzIG5vdCBtaXNzZWQgYSBjb25uZWN0aW5nIGZsaWdodCBhbmQgbWFkZSBpdCB0byBJQUQuIENvbXB1dGUgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhleSBmbGV3IG9uIGEgRGVsdGEgZmxpZ2h0CmBgYHtyfQooMC42Mzc1KjAuOSkgLyAoKDAuMjEyNSowLjcpICsgKDAuMTUqMC44NSkgKyAoMC42Mzc1KjAuOSkpICNjYWxjdWxhdGUgcHJvYmFiaWxpdHkgb2YgZmlsaW5nIERlbHRhIGZsaWdodCBhbmQgbm90IG1pc3NpbmcgdGhlIGNvbm5lY3RpbmcgZmxpZ2h0IHAoTWlubmVhcG9saXMtU3QuUGF1bCkKYGBgCgokJCBQKE1pbm5lYXBvbGlzLVN0LlBhdWwpID0gMC42NzUgJCQKYy4gUHJvdmlkZSBhIHN0YXRlbWVudCB0aGF0IGludGVycHJldHMgdGhlIG1lYW5pbmcgb2YgdGhlIHByb2JhYmlsaXR5IGNvbXB1dGVkIGluIChiKSBpbiB0aGUgY29udGV4dCBvZiB0aGVzZSBkYXRhLgoKQW5zOiBUaGUgZXhlY3V0aXZlIHdpbGwgbW9zdCBsaWtleSBmbHlpbmcgd2l0aCBEZXRhbCBhaXJsaW5lIGJlY2F1c2UgdGhlIHByb2JhYmlsaXR5IGlzIG92ZXIgNTAlIGFuZCBEZXRhbCBhaXJsaW5lIGhhcyB0aGUgYmVzdCBjaGFuY2Ugb2YgZ2V0dGluZyBvbiB0aGUgY29ubmVjdGluZyBmbGlnaHQgYW5kIGFycml2aW5nIGluIElBRC4KClE1LgoKYS5Vc2luZyBSIFN0dWRpbywgY3JlYXRlIGEgZGlzcGxheSB0aGF0IHNob3dzIHRoZSBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24gb2YgdGhpcyBwYXJ0aWN1bGFyIHJhbmRvbSB2YXJpYWJsZSBYLiBSZWZlciB0byB0aGUgdmFyaW91cyBjb2RlIHByb3ZpZGVkIGZvciBleGFtcGxlcyBhcHBlYXJpbmcgaW4gYm90aCBQcm9iYWJpbGl0eSBNb2R1bGUgNCBhbmQgUmV2aWV3IEV4ZXJjaXNlIDUgZnJvbSBUaHVyc2RheSwgU2VwdGVtYmVyIDEwdGguIEZvciB2YWx1ZXMgb2YgeCwgdXNlIHh2YWx1ZXMgPSAwOjE1LgpgYGB7cn0KcGRmMSA8LSBmdW5jdGlvbih4KSAjIGNyZWF0ZSBhIHByb2JhYmxpdHkgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uIG9mIDIgLyAzXih4KzEpCnsKICAyIC8gKDNeKHgrMSkpCn0KYGBgCgpgYGB7cn0KY3VydmUocGRmMSwgMCwgMTUsIHhsYWI9IlZhbHVlcyBvZiBYIiwgeWxhYj0iVmFsdWVzIG9mIHBkZjEoeCkiLCBtYWluPSJEaXN0cmlidXRpb24gb2YgWCIsIGNvbD0ncmVkJykKYGBgCgpiLiBDb21wdXRlIFAoWD4zKQpgYGB7cn0KaW50ZWdyYXRlKHBkZjEsIGxvd2VyPTMsIHVwcGVyPTE1KSR2YWx1ZQpgYGAKCiQkIFAoWD4zKSA9IDAuMDIyNDc1ICQkCmMuIENvbXB1dGUgdGhlIG1lYW4gb3IgZXhwZWN0ZWQgdmFsdWUgb2YgWCwgRShYKSBvciDOvFguIChIaW50OiBJbiBjb21wdXRpbmcgRShYKSwgY2hhbmdlIHRoZSB1cHBlciBsaW1pdCBvbiB4dmFsdWVzIGZyb20gMTUgdG8gNTDigKYpCgpgYGB7cn0KcGRmMW1lYW4gPC0gZnVuY3Rpb24oeCkgI2NyZWF0ZSBhIGZ1bmljdGlvbiBvZiB4KnBkZjEoeCkgc28gdGhhdCBpdCBjYW4gYmUgaW50ZWdyYXRlZCB1c2luZyBpbnRlZ3JhdGUgY29tbWFuZGUgd2l0aCBsb3dlcj0wIGFuZCB1cHBlcj01MAp7CiAgeCpwZGYxKHgpCn0KYGBgCmBgYHtyfQppbnRlZ3JhdGUocGRmMW1lYW4sIGxvd2VyPTAsIHVwcGVyPTUwKSR2YWx1ZQpgYGAKJCQgRShYKSBcOyBvciBcOyBcbXV7eH0gPSAwLjU1MjM1NyAkJApkLiBDb21wdXRlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgWCwgU0QoWCkgb3Igz4NYLiAodXNlIHRoZSBzYW1lIHZhbHVlcyBvZiB4IGFzIHlvdSBkaWQgaW4gcGFydCAoYykpCmBgYHtyfQpwZGYxc2QgPC0gZnVuY3Rpb24oeCkgI2NyZWF0ZSBhIGZ1bmN0aW9uIG9mIHheMiAqIHBkZjEoeCkgc28gdGhhdCBpdCBjYW4gYmUgaW50ZWdyYXRlZCB1c2luZyBpbnRlZ3JhdGUgY29tbWFuZGUgd2l0aCBsb3dlcj0wIGFuZCB1cHBlcj01MAp7CiAgeCpwZGYxbWVhbih4KQp9CmBgYApgYGB7cn0Kc3FydChpbnRlZ3JhdGUocGRmMXNkLCBsb3dlcj0wLCB1cHBlcj01MCkkdmFsdWUgLSAoaW50ZWdyYXRlKHBkZjFtZWFuLCBsb3dlcj0wLCB1cHBlcj01MCkkdmFsdWUpXjIpCmBgYAoKJCQgU0QoWCkgXDsgPSAgXDsgMC44MzY5MzIzICQkCgplLkNvbnNpZGVyIHRoZSBpbnRlcnZhbCAozrx44oiSz4N4LCDOvHgrz4N4KS4gQ29tcHV0ZSBQKM68eOKIks+DeCA8WDwgzrx4K8+DeCkKCmBgYHtyfQowLjU1MjM1NyAtIDAuODM2OTMyMwpgYGAKJCQgXG11e3h9IC0gz4N4ID0gIC0wLjI4NDU3NTMgJCQKYGBge3J9CmludGVncmF0ZShwZGYxLCBsb3dlcj0oMCksIHVwcGVyPSgwLjU1MjM1NyswLjgzNjkzMjMpKSR2YWx1ZSAjYmVjYXVzZSDOvHjiiJLPg3ggaXMgbGVzcyB0aGFuIHplcm8sIGFuZCB4ID0wLDEsMi4uLiBzbyBsb3dlciBsaW1pdCBpcyB6ZXJvCmBgYAoKUTYuCgphLgpgYGB7cn0KcGRmMiA8LSBmdW5jdGlvbihuLHgpICNjcmVhdGUgdGhlIGZ1bmN0aW9uIGZvciB0aGUgcHJvYmFiaWxpdHkgb2YgbnVtYmVyIG9mIGNhbmFkaWFucyBkaXNhZ3JlZSB3aXRoIGludGVybmV0IGNvbXBhbmllcyAKewogIGNob29zZShuLHgpKigwLjZeeCkqKDAuNF4obi14KSkKfQpgYGAKCgpgYGB7cn0KcGRmMig0MCwzMCkgI2NhbGN1bGF0ZSBleGFjdGx5IDMwIHdpbGwgZGlzYWdyZWUgd2l0aCBpbnRlcm5ldCBjb21wYW5pZXMgaGFuZGluZyBvdmVyIHByaXZhdGUgaW5mb3JtYXRpb24gdG8gYXV0aG9yaXRpZXMKYGBgCgpiLgpgYGB7cn0KcDI4MzUgPSAwICAgICAgICAgICAjZGVmaW5lIGEgdmFyaWFibGUgc3RvcmVzIFAoMjggPTwgeCA8PSAzNSkKZm9yIChpIGluIDI4OjM1KSAgICAjZm9yIGxvb3AgdG8gY2FsY3VsYXRlIFAoeCA9IDI4KSwgUCh4ID0gMjkpLi4uUCh4ID0gMzUpIGFuZCBzdW0gdGhlbSB1cAp7CiAgcDI4MzUgPSBwMjgzNSArIHBkZjIoNDAsaSkgI3N1bSB1cCBQKHggPSAyOCksIFAoeCA9IDI5KS4uLlAoeCA9IDM1KSBhbmQgc3RvcmVzIHRoZSB0b3RhbCBpbiBwMjgzNQp9CnAyODM1CmBgYAoKYy4KCgpgYGB7cn0KcDE1ID0gMApmb3IgKGkgaW4gMTU6MjUpICAgIAp7CiAgcDE1ID0gcDE1ICsgcGRmMihpLDE1KSAKfQpwMTUKYGBgCiQkIFAoMTV0aCBcOyBwZXJzb24gXDsgZGlzYWdyZWUpID0gMC44Njg4NTMgJCQKCjcuIApgYGB7cn0KT2RkUGVyc29uT3V0IDwtIGZ1bmN0aW9uKHgpCnsKICAwLjY4NzVeKHgtMSkqMC4zMTI1Cn0KYGBgCgpgYGB7cn0KT2RkUGVyc29uT3V0KDEwKQpgYGAKCiQkIFAoeD0xMCkgPSAwLjAxMDcyMjcgJCQKYGBge3J9Ck9kZFBlcnNvbk91dE1lYW4gPC0gZnVuY3Rpb24oeCkgI2NyZWF0ZSBhIGZ1bmNpdG9uIG9mIHgqcCh4KSBzbyB0aGF0IHdlIGNhbiBpbnRlZ3JhdGUgaXQgdG8gZGV0ZXJtaW5lIGV4cGVjdGVkIHZhbHVlCnsKICB4ICogT2RkUGVyc29uT3V0KHgpCn0KCmludGVncmF0ZShPZGRQZXJzb25PdXRNZWFuLCBsb3dlcj0xLCB1cHBlcj01MCkkdmFsdWUgI2RldGVybWluZSBleHBlY3RlZCB2YWx1ZS4gCmBgYAokJCBFKFgpID0gMy4wNTk4NzUgXDsgdHJpYWxzICQkCgpBbnM6IHdoZW4geCA+PTUwLCBleHBlY3RlZCB0cmFpbHMgdG8gb2JlcnN2ZSAib2RkIHBlcnNvbiBvdXQiIGNvbnZlcmdlcyB0byAzLjA1OTg3NSwgdGhlbiB5ZXMsIDEwIHRyYWlscyBpcyBtb3JlIHRoYW4gZXhwZWN0ZWQgdG8gb2JzZXJ2ZSAiT2RkIHBlcnNvbiBvdXQiCgpROC4KCmEuCmBgYHtyfQpwbm9ybSgxLjkxLCAxLjg5LCAwLjA1KSAtIHBub3JtKDEuODMsIDEuODksIDAuMDUpICNjYWxjdWxhdGUgUCgxLjgzIDw9IHggPD0gMS45MSkKYGBgCgokJCBQKDEuODMgXGxlcSB4IFxsZXEgMS45MSkgPSAwLjU0MDM1MjEgJCQKCmIuCmBgYHtyfQpxbm9ybSgwLjksIDEuODksIDAuMDUpCmBgYAoKSW50ZXJwcmV0YXRpb246IDkwJSBvZiAyLWxpdGVyIGJvdHRsZXMgaGF2ZSAxLjk1NDA3OCBsaXRlciBvciBsZXNzIHNvZnQgZHJpbmsgZmlsbGVkLiAKCmMuCmBgYHtyfQoxIC0gcG5vcm0oMiwgMS44OSwgMC4wNSkgI2NhbGN1bGF0ZSB0aGUgcHJvYmFiaWxpdHkgb2YgMi1saXRlciBib3R0ZXJzIGJlaW5nIG92ZXJmaWxsZWQKYGBgCiQkIFAoeCA+IDIpID0gMC4wMTM5MDM0NSAkJAoKZC4KYGBge3J9CnBub3JtKDEuODUsIDEuODksIDAuMDUpICNjYWxjdWxhdGUgdGhlIHByb2JhYmlsaXR5IG9mIGEgMi1saXRlciBib3R0bGUgaGFzIGxlc3MgdGhhbiAxLjg1IGxpdGVycyBvZiBzb2Z0LWRyaW5rIGZpbGxlZApgYGAKCmBgYHtyfQoxIC0gcG5vcm0oMS44NSwgMS44OSwgMC4wNSkgI2NhbGN1bGF0ZSB0aGUgcHJvYmFiaWxpdHkgb2YgYSAyLWxpdGVyIGJvdHRsZSBoYXMgbW9yZSB0aGFuIDEuODUgbGl0ZXJzIG9mIHNvZnQtZHJpbmsgZmlsbGVkCmBgYAoKYGBge3J9ClA1MTAgPSAwIApmb3IgKGkgaW4gNToxMCkKewogIFA1MTAgPSBQNTEwICsgY2hvb3NlKDUwLGkpKigwLjIxMTg1NTReaSkqKDAuNzg4MTQ0Nl4oNTAtaSkpCn0KUDUxMApgYGAKCiQkIFAoIEJldHdlZW4gXDsgNSBcOyBhbmQgXDsgMTAgIFw7IGJvdHRsZXMgXDsgaGF2ZSBcOyBsZXNzIFw7IDEuODUgXDsgbGl0ZXJzIFw7IG9mIFw7IHNvZnQgXDsgZHJpbmspID0gMC40ODkyNDg5ICQkCgpROS4KCmBgYHtyfQpnc3MgPSByZWFkLmNzdigiaHR0cDovL3Blb3BsZS51Y2FsZ2FyeS5jYS9+amJzdGFsbC9EYXRhRmlsZXMvR1NTMjAwMi5jc3YiKQpgYGAKYGBge3J9CmhlYWQoZ3NzLCA0KQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YT1nc3MsIGFlcyh4ID0gUmVsaWdpb24sIGZpbGw9UmVsaWdpb24pKSArIGdlb21fYmFyKHBvc2l0aW9uPSJkb2RnZSIsIG5hLnJtPVRSVUUpICsgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSkKYGBgCmBgYHtyfQpjb3VudHM9YXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKGdzcyRSZWxpZ2lvbikpKQpoZWFkKGNvdW50cywgNCkKYGBgCgphLgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBnc3MsIGFlcyh4ID0gRWR1Y2F0aW9uLCBmaWxsID0gUmFjZSkpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBuYS5ybSA9IFRSVUUpICNjcmVhdGUgdGhlIGRpc3RyaWJ1dGlvbiBvZiByYWNlIHdpdGhpbiBlYWNoIGVkdWNhdGlvbi4gCmBgYAoKSW50ZXJwcmV0YXRpb246IFdoaXRlIHBlb3BsZSBhcmUgbWFqb3JpdHkgcG9wdWxhdGlvbiBpbiBlYWNoIGVkdWNhdGlvbiBsZXZlbCwgdGhlbiBmb2xsb3dlZCBieSBibGFjayBwZW9wbGUuCgpiLgpgYGB7cn0KZ2dwbG90KGRhdGE9Z3NzLCBhZXMoeCA9IE1hcml0YWwsIGZpbGwgPSBFZHVjYXRpb24pKSArIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgbmEucm09VFJVRSkgCmBgYApUaGUgcGxvdCBhYm92ZSBzaG93cyB0aGF0IGVhY2ggbWFyaXRhbCBjYXRlZ29yeSBoYXMgc2ltaWxhciBkaXN0cmlidXRpb24gaW4gZWFjaCBlZHVjYXRpb24gbGV2ZWwuIE1ham9yaXR5IG9mIHBvcHVsYXRpb24gaGFzIEhTLCB0aGVuIEJhY2hlbG9ycywgTGVmdCBIUywgR3JhZHVhdGUsLi4uLCBvbmx5IGV4Y2VwdGlvbiBpcyBXaWRvd2VkLCBpdCBoYXMgTGVmdCBIUyBjb21lIGluIGFzIHNlY29uZC4KCgpgYGB7cn0KZ2dwbG90KGRhdGE9Z3NzLCBhZXMoeCA9IEVkdWNhdGlvbiwgZmlsbCA9IE1hcml0YWwpKSArIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgbmEucm09VFJVRSkKYGBgClNlY29uZCBwbG90IHNob3dzIGVhY2ggZWR1Y2F0aW9uIGxldmVsIGhhcyBzaW1pbGFyIGRpc3RyaWJ1dGlvbiBpbiBlYWNoIG1hcml0YWwgY2F0ZWdvcnkuIE1ham9yaXR5IHBlb3BsZSBpbiBlYWNoIGVkdWNhdGlvbiBsZXZlbCBhcmUgbWFycmllZCBhbmQgZm9sbG93ZWQgYnkgTmV2ZXIgTWFycmllZCwgRGl2b3JjZWQsIFdpZG93ZWQsIGV0Yy4KCgoKCmMuCgpgYGB7cn0KZ2dwbG90KGRhdGE9Z3NzLCBhZXMoeCA9IEdlbmRlciwgZmlsbD1Qb2xpdGljcykpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBuYS5ybT1UUlVFKSAKYGBgCkl0IHNlZW1zIGxpa2UgRmVtYWxlIGFuZCBNYWxlIGhhcyBzaW1pbGFyIGRpc3RyaWJ1dGlvbiBhY3Jvc3MgZGlmZmVyZW50IHBvbGl0aWNzLiBNYWpvcml0eSBvZiB0aGVtIGFyZSBNb2RlcmF0ZSwgYW5kIGZvbGxvd2VkIGJ5IENvbnNlcnZhdGl2ZSwgU2xpZ2h0bHkgY29uc2VydmF0aXZlLCBTbGlnaHRseSBsaWJlcmFsLiBXZW1vbiBoYXMgaGlnaGVyIHByb2JhYmlsaXR5IHRoYW4gbWVuIHRvIGJlIGNvbnNlcnZhdGl2ZShpbmNsdWRpbmcgRXh0cmVtZWx5IGNvbnNlcnZhdGl2ZSwgQ29uc2VydmF0aXZlLCBzbGlnaHRseSBjb25zZXJ2YXRpdmUpCgoKMTAuIApgYGB7cn0KbGlicmFyeShJU0xSKQpoZWFkKERlZmF1bHQsIDQpICNzaG93cyB0aGUgZmlyc3QgZm91ciBsaW5lcyBvZiB0aGUgRGVmYXVsdCBkYXRhIHNldApgYGAKCmEuCgpgYGB7cn0KZ2dwbG90KGRhdGE9RGVmYXVsdCwgYWVzKHggPSBiYWxhbmNlLCB5ID0gaW5jb21lLCBjb2xvciA9IHN0dWRlbnQpKSArIGdlb21fcG9pbnQoc2l6ZSA9IDIsIHBvc2l0aW9uID0gImppdHRlciIpICsgeGxhYigiQmFsYW5jZSIpICsgeWxhYigiSW5jb21lIikgKyBnZ3RpdGxlKCJNb250aGx5IEluY29tZSB2cyBNb250aGx5IENyZWRpdCBDYXJkIEJhbGFuY2UiKQpgYGAKCmIuCmBgYHtyfQpnZ3Bsb3QoZGF0YT1EZWZhdWx0LCBhZXMoeD0gc3R1ZGVudCwgeT1iYWxhbmNlLCBjb2xvciA9IHN0dWRlbnQpKSArIGdlb21fYm94cGxvdChuYS5ybT1UUlVFKSArIHhsYWIoIlN0dWRlbnQgU3RhdHVzIikgKyB5bGFiKCJNb250aGx5IEJhbGFuY2UiKQpgYGAKCmMuCmBgYHtyfQptZWFuKH5iYWxhbmNlLCBkYXRhPURlZmF1bHQsIG5hLnJtPVRSVUUpICAgI2NhbGN1bGF0ZSB0aGUgbWVhbiBvZiBiYWxhbmNlcyBmcm9tIHRoZSBkYXRhIGZyYW1lIERlZmF1bHQKYGBgCgpgYGB7cn0KbWVkaWFuKH5iYWxhbmNlLCBkYXRhPURlZmF1bHQsIG5hLnJtPVRSVUUpICAjY2FsY3VsYXRlIHRoZSBtZWFuIG9mIGJhbGFuY2VzIGZyb20gdGhlIGRhdGEgZnJhbWUgRGVmYXVsdApgYGAKCgpgYGB7cn0Kc2QofmJhbGFuY2UsIGRhdGE9RGVmYXVsdCwgbmEucm09VFJVRSkgICAjY2FsY3VsYXRlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYmFsYW5jZXMgZnJvbSB0aGUgZGF0YSBmcmFtZSBEZWZhdWx0CmBgYAoKYGBge3J9CmJhbGFuY2VkYXRhID0gYyhEZWZhdWx0JGJhbGFuY2UpICAjY3JlYXRlIGEgdmVjdG9yIHRoYXQgc3RvcmVzIGFsbCBiYWxhbmNlcyBmcm9tIGRhdGEgZnJhbWUgRGVmYXVsdApxdWFudGlsZShiYWxhbmNlZGF0YSwgMC4wNSkgICAjY2FsY3VsYXRlIDV0aCBwZXJjZW50aWxlcyBvZiBhbGwgYmFsYW5jZXMKYGBgCgpgYGB7cn0KcXVhbnRpbGUoYmFsYW5jZWRhdGEsIDAuOTUpICAgICNjYWxjdWxhdGUgOTV0aCBwZXJjZW50aWxlcyBvZiBhbGwgYmFsYW5jZXMKYGBgCgpRMTEuCmBgYHtyfQpjb3VyaWVyIDwtIHJlYWQuY3N2KCdEYXRhNjAyQXNzaWdubWVudDFRdWVzdGlvbjExLmNzdicsIGhlYWRlciA9IFRSVUUpCmNvdXJpZXIgPSBjb3VyaWVyICU+JSBtdXRhdGUoQ291cmllciA9ICJMb2NhbCBDb3VyaWVyIikKY291cmllcgpgYGAKCmEuIAoKYGBge3J9CmdncGxvdChkYXRhID0gY291cmllciwgYWVzKHggPSBDb3VyaWVyICwgeSA9IERlbGl2ZXJ5X3RpbWUpKSArIGdlb21fdmlvbGluKGNvbCA9ICJibHVlIiwgZmlsbCA9ICJyZWQiLCBuYS5ybSA9IFRSVUUpICsgeGxhYigiQ291cmllciIpICsgeWxhYigiRGVsaXZlcnkgdGltZSIpICsgZ2d0aXRsZSgiVm9pbGluIHBsb3Qgb2YgdGhpcyBjb3VyaWVyIGRlbGl2ZXJ5IHRpbWUiKQpgYGAKCmIuCmBgYHtyfQptZWFuKH5EZWxpdmVyeV90aW1lLCBkYXRhID0gY291cmllciwgbmEucm0gPSBUUlVFKQpgYGAKCmBgYHtyfQptZWRpYW4ofkRlbGl2ZXJ5X3RpbWUsIGRhdGEgPSBjb3VyaWVyLCBuYS5ybSA9IFRSVUUpCmBgYAoKYGBge3J9CnNkKH5EZWxpdmVyeV90aW1lLCBkYXRhID0gY291cmllciwgbmEucm0gPSBUUlVFKQpgYGAKCmBgYHtyfQpxZGF0YSh+RGVsaXZlcnlfdGltZSwgYygwLjI1LCAwLjc1KSwgZGF0YSA9IGNvdXJpZXIpCmBgYApgYGB7cn0KcWRhdGEofkRlbGl2ZXJ5X3RpbWUsIDAuOTksIGRhdGEgPSBjb3VyaWVyKQpgYGAKCmMuCmBgYHtyfQpxbm9ybSgwLjk5LCA1LCAxLjUpCmBgYAoKQmVjYXVzZSB0aGUgYW1vdW50IG9mIGRlbGl2ZXJ5IHRpbWUgY2FuIGJlIG1vZGVsZWQgYnkgdGhlIE5vcm1hbCBkaXN0cmlidXRpb24gd2l0aCBhIG1lYW4gZGVsaXZlcnkgdGltZSBvZiA1IGhvdXJzIGFuZCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAxLjIgaG91cnMsIHNvIDk5dGggcGVyY2VudGlsZSBpcyA4LjQ4OTUyMiBob3Vycywgd2hpY2ggbWVhbnMgYWxsIDk5JSBvZiBwYWNrYWdlcyB3aWxsIGJlIGRlbGl2ZXJlZCB3aXRoaW4gOC40ODk1MjIgaG91cnMgb3IgbGVzcy4gQW55dGhpbmcgaXMgb3ZlciB0aGlzIGRlbGl2ZXJ5IHRpbWUgd2lsbCBiZSByZWZ1bmRlZC4g