Bisection Method
The bisection method is another approach to finding the root of a continuous function \(f(x)\) on an interval \([a,b]\). The method takes advantage of a corollary of the intermediate value theorem called Bolzano’s theorem which states that if the values of \(f(a)\) and \(f(b)\) have opposite signs, the interval must contain at least one root. The iteration steps of the bisection method are relatively straightforward, however; convergence towards a solution is slow compared to other root-finding methods.
The Bisection Algorithm
For a given function f(x),the Bisection Method algorithm works as follows:
- Two values a and b are chosen for which \(f(a)>0\) and \(f(b)<0\) (or the other way around)
- Interval halving: A midpoint \(c\) is calculated as the arithmetic mean between \(a\) and \(b\),\(c=(a+b)/2\)
- The function \(f\) is evaluated for the value of \(c\)
- If \(f(c)=0\) means that we found the root of the function, which is \(c\)
- If \(f(c)\neq 0\) we check the sign of \(f(c)\):
- if \(f(c)\) has the same sign as \(f(a)\), we replace \(a\) with \(c\) and we keep the same value for \(b\).
- if \(f(c)\) has the same sign as \(f(b)\), we replace \(b\) with \(c\) and we keep the same value for \(a\)
- We go back to step 2. and recalculate \(c\) with the new value either it is value of \(a\) or \(b\)
The algorithm ends when the values of \(f(c)\) is less than a defined tolerance (e.g. 0.001). In this case we say that \(c\) is close enough to be the root of the function for which \(f(c) ~= 0\).
In order to avoid too many iterations, we can set a maximum number of iterations (e.g. 1000) and even if we are above the defined tolerance, we keep the last value of c as the root of our function.

Bisection Algorithm in R
Suppose we want to find the root of the function \(x^3−2x−5\). It is often valuable to plot the function to find an interval containing the root.
Visualize the function

As we can see from the visualization above, we know that the root appears to lie close in 2. Next, we will use the interval [2,3] in Bisection Method.
Use NLRoot packages
On of the most usefull package for the Bisection Method in R is the NLRoot package, here you will apply BFfzero() to find the solution, as you can see below:
## [1] 1
## [1] 2.094553
## [1] 1.262094e-05
## [1] "finding root is successful"
The output of the function shows the root is located at \(x=2.094553\), which matches the results found in previous examples on other root finding methods such as the Newton-Raphson method and Secant method.
Write Function
We can also write a function that implements the bisection method using the iteration steps detailed at the beginning of the post.
Bakti_Bisection <- function(f, a, b, n = 1000, tol = 1e-7) {
# If the signs of the function at the evaluated points, a and b, stop the function and return message.
if (!(f(a) < 0) && (f(b) > 0)) {
stop('signs of f(a) and f(b) differ')
} else if ((f(a) > 0) && (f(b) < 0)) {
stop('signs of f(a) and f(b) differ')
}
for (i in 1:n) {
c <- (a + b) / 2 # Calculate midpoint
# If the function equals 0 at the midpoint or the midpoint is below the desired tolerance, stop the
# function and return the root.
if ((f(c) == 0) || ((b - a) / 2) < tol) {
return(c)
}
# If another iteration is required,
# check the signs of the function at the points c and a and reassign
# a or b accordingly as the midpoint to be used in the next iteration.
ifelse(sign(f(c)) == sign(f(a)),
a <- c,
b <- c)
}
# If the max number of iterations is reached and no root has been found,
# return message and end function.
print('Too many iterations')
}
Now, we can apply our function find the root of the function \(x^3−2x−5\) as we have done above by using NLRoot packages.
## [1] 2.094552
Your Own Function

## [1] 1
## [1] 2.462045
## [1] 8.100567e-06
## [1] "finding root is successful"
## [1] 2.462045
Newton’s Method
The Newton-Raphson method is a method for approximating the roots of polynomial equations of any order. In fact the method works for any equation, polynomial or not, as long as the function is differentiable in a desired interval. ’s often become increasingly better approximations of the function’s root. Newton’s method usually use for solving equations is another numerical method for solving an equation \(f(x)=0\). It is based on the geometry of a curve, using the tangent lines to a curve. As such, it requires calculus, in particular differentiation. Roughly, the idea of Newton’s method is as follows.
The Newton’s Algorithm
- Find points \(a\) and \(b\) such that \(a < b\) and \(f(a).f(b) < 0\).
- Take the interval \([a,b]\) and find next value \(x_0=\frac{(a+b)}{2}\)
- Find \(f(x_0)\) and \(f'(x_0)\), \(x_1=x_0-\frac{f(x0)}{f'(x_0)}\)
- If \(f(x_1)=0\) then \(x_1\) is an extract root, else \(x_0=x_1\).
- Repeat steps 2 to 4 until \(f(x_i)=0\) or \(|f(x_i)|\leq Accuracy\).

Newton’s Method in R
Suppose we want to find the root of the function \(f(x)=x^2−9 \text{ for, } x>0\). We assume that \(f\) is smooth (differentiable). Our goal is to find a root of \(f\) i.e a \(x\) value for which \(f(x)=0\). We illustrate the method with a simple example for which you know the root.
Visualize the function
## x f
## 1 0.100 -8.990000
## 2 0.199 -8.960399
## 3 0.298 -8.911196
## 4 0.397 -8.842391
## 5 0.496 -8.753984
## 6 0.595 -8.645975
# create the base layer of ggplot with geom_Line
plot_f <- ggplot(plot_data, aes(x = x, y = f)) +
geom_line(color = "red", size = 1.0) +
labs(x = "x", y = "f(x) = x^2 - 9")
# beautify : Increase font size in axes
plot_f + theme(axis.text.x =
element_text(face = "bold",size = 12),
axis.text.y =
element_text(face = "bold", size = 12),
axis.line = element_line(colour = "black",
size = 1, linetype = "solid"))
By considering the visualization above, it’s looks like the function is 0 around 3. How do we know that exactly correct, let’s try zoom the visualization.

Next, let us visualize this to find the root of our function \(f(x)=x^2−9.\) First we need to create a function that returns the tangent line to the function f at some point a.
Then, plot the tangent line to the initial value \(f\) at \(x(0)=4\) which will be our first guess of the root.
# add the tangent line at 4 to our data frame
plot_data$f.tan <- sapply(plot_data$x, f_tangent, f = function(x) x^2 - 9, df = function(x) 2*x, a = 4)
# create the base layer of ggplot with geom_Line
plot_tangent_line <- ggplot(plot_data, aes(x = x)) +
geom_line(aes(y = f), color = "red", size = 0.95) +
geom_line(aes(y = f.tan), color = "blue", size = 0.95) +
labs(x = "x", y = "f(x) and tangent line at 4")
plot_tangent_line

Next, let us zoom in on \(2≤x≤4\) and try to see where the tangent line is equal to 0.

By considering the visualization above, looks like the tangent line is 0 around 3.1. This will be our updated guess at the root. Understand the rationale behind this. If f is approximately equal to its tangent line at 4, then the root of \(f\) is approximately equal to the root of the tangent line. Can you see this in the plot above?
The exact value when the tangent line is 0 is given by
\[ x^{(1)}=4−{f(4) \over f′(4)} =3.125\]
Then, add the tangent line at 3.125 to our data frame
plot_data$f.tan <- sapply(plot_data$x, f_tangent, f = function(x) x^2 - 9, df = function(x) 2*x, a = 3.125)
# create the base layer of ggplot with geom_Line
plot_tangent_line <- ggplot(plot_data, aes(x = x)) +
geom_line(aes(y = f), color = "red", size = 0.95) +
geom_line(aes(y = f.tan), color = "blue", size = 0.95) +
labs(x = "x", y = "f(x) and tangent line at 4")
plot_tangent_line

Now let us zoom in on around 3 and try to see where the tangent line is equal to 0.

Looks like the tangent line is 0 around 3. In just two steps we are very close. This will be our updated guess at the root. The exact value when the tangent line is 0 is given by
\[ x^{(2)}=x^{(1)}−{f(x^{(1)}) \over f′(x^{(1)})}\] \[ x^{(2)}=3.125−{f(3.125) \over f′(3.125)} = 3.0025\]
We can continue until our guesses keep getting smaller and smaller.
Use NLRoot packages
The same packages as we use to the Bisection Method, this packages also available for Newton’s method.
## [1] 3
## [1] 1.081801e-12
## [1] "finding root is successful"
In this lesson we will construct two functions that you will need for this course and begin to explore the R programming language. Run through the Chapter 1 of the book which talks about model building for a one-variable optimization problem. Example 1.1 (Meerschaert) A pig weighing 200 lbs gains 5 lbs per day and costs 45 cents per day to keep (feed and board). The market price for pigs is 65 cents per pound, but is falling 1 cent per day. When should the pig be sold?
Modeling the Problem
- Variables:
- \(t\) = time (days)
- \(w\) = weight of the pig(lbs)
- \(p\) = price for pigs ($/lb)
- \(C\) = cost of keeping pig t days ($)
- \(R\) = revenue obtained by selling pig ($)
- \(P\) = profit from selling pig ($)
- Assumptions:
- \(w=200+5t\)
- \(p=0.65−0.01t\)
- \(C=0.45t\)
- \(R=p⋅w\)
- \(P=R−C\)
- \(t \geq 0\)
Objective: Maximize profits from the sell of the pig
Let \(x\) be the time to sell the pig and develop the profit function using x as the independent variable. In the case of an optimization, the variable on which you will make a decision on is generally called a decision
Profit Function = Objective function. Given the description and mathematical explanation of the variables, lets write out the profit function:

Let’s use R to “see” what the profit function looks like over the next 20 days.

## [1] 133.2
As you can see, there is a good and bad day to sell the pig if our assumptions remain the same over the next 20 days. Although we could use this graph in order to select the “winner”, we want to be able to use this tool (R programming language) to assist us in ensuring that we have all of the information needed to make a decision. That means that we need to get our hands dirty and figure out how to use our tools (in this case, R).
Build the functions that we need to solve the problem
We will create two functions that will be able to solve for an optimal point in R using mathematics / programming that we already know how to do.
Using this simple formula, let’s build a derivative of the profit function that we defined above. Notice how our function fprime(f,x) will work for ANY function that we assign to it.

Root-Finding Solver
Although we could use the graph above to find the solution for this particular problem, it is more appropriate to use math to make our solution automatic. There are many root-finding algorithms out there and feel free to use another, but we will use a simple algorithm known as the bisection method. This method only requires that you select two points that have opposite signs: if \(f(a)=−\) then \(f(b)=+\).
Bisection Algorithm for finding the root of an equation.
The simple idea of the bisection method is that you start with an interval [a,b] that has a positive and negative value for the function \(f(a)\) and \(f(b)\) - it does not matter which one is positive. You cut the interval in half and proceed with the interval that keeps one side positive and the other negative. In Figure 1, we start on the interval [2,9] which works because \(f(2)\) is positive and \(f(9)\) is negative. The first step cuts the interval in half and the decision must be made to continue with [2,5.5] or [5.5,9]. It should be pretty obvous from the picture that [2,5.5] is the right answer (we want to keep a root in the interval), but from an algorithm perspective, we simply test f(5.5) and find out that it is negative which causes us to replace 9 (\(f[9]\) was negative) with 5.5. We would continue this algorithm until we are satisfied that the width of the interval is small enough to make a conclusion about the value of the root.

bisection = function(f,a,b,tol=0.0001){
if (f(a)*f(b) > 0){
return ("Boundary Conditions Not Met")
}
else{
middle = a
while (abs(f(middle))>tol){
middle = (a+b)/2
if (f(middle)*f(a)>0) (a = middle)
else (b = middle)
x=middle
y=f(middle)
## if you want to "see" what happens at every step, take off the # of the next line ##
#cat(sprintf("x-Val: %.4f ; f(x-val): %.4f\n",x,y))
}
return (middle)
}
}
#Example of a finding a root of a function
f = function (x){x^3-5} #sinlge line function definition
zero=bisection (f,-10,20)
x=seq(-1,2,0.01)
plot(x,f(x),"l")
abline(h=0,col="red")
abline(v=zero,col="purple")

## [1] 1.709967
Sensitivity Analysis: Price of the Pig
Let’s go back and examine more closely one of our original assumptions that may or may not hold to see how our solution is afftected by a different assumption. Does the optimal day to sell change if we assume some different price of the pig. Here we let the pig price drop to recreate the numbers in the book, but we are able to do so much more which will be demonstrated in the next analysis.
## [1] 15.000000 11.110840 8.000488 5.454102 3.332520

Sensitivity Analysis: Growth Rate of the Pig
Since we are also concerned about the growth rate of the pig, let’s conduct see how the days to sell are affected by the growth rate. The weight (w) is calculated using the assumption that the pig will grow 5lbs per day so that: \[w=200+gt\] where \[g=5\]. Let’s see what happens if g is between 3 and 7. Remember the bisection method needs two boundary points that have the opposite values and if the growth rate is too small, think about what that does to the profit. Experiment with large and small growth rates and the profit function to figure it out for yourself if you don’t see it. We needed to make the starting point of the bisection method to the left (negative number) in order for it to find the zero for 3lbs and 3.5 lbs per day.
## [1] -90.002441 -49.169922 -28.749084 -16.499329 -8.332825 -2.500916
## [7] 1.875305 5.278778 8.000183 10.227203 12.083435 13.653564
## [13] 14.999390 16.166687 17.187500 18.088150 18.889236 19.605637
## [19] 20.249939 20.833588 21.363449 21.847534 22.291565

LS0tDQp0aXRsZTogIkxhYjQ6IFNvbHZpbmcgTm9ubGluZWFyIEVxdWF0aW9ucyINCmF1dGhvcjogIkltZWxkYSBTaWFudHVyaSINCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGhpZ2hsaWdodDogbW9ub2Nocm9tZQ0KICAgIHRoZW1lOiBzcGFjZWxhYg0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KLS0tDQoNCmBgYHtyIExvZ28sIGVjaG89RkFMU0UsZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnNDAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL2dpdGh1Yi5jb20vQmFrdGktU2lyZWdhci9pbWFnZXMvYmxvYi9tYXN0ZXIvbG9nby5wbmc/cmF3PXRydWUiKQ0KYGBgDQoNCiMgQmlzZWN0aW9uIE1ldGhvZA0KDQpUaGUgYmlzZWN0aW9uIG1ldGhvZCBpcyBhbm90aGVyIGFwcHJvYWNoIHRvIGZpbmRpbmcgdGhlIHJvb3Qgb2YgYSBjb250aW51b3VzIGZ1bmN0aW9uICRmKHgpJCBvbiBhbiBpbnRlcnZhbCAkW2EsYl0kLiBUaGUgbWV0aG9kIHRha2VzIGFkdmFudGFnZSBvZiBhIGNvcm9sbGFyeSBvZiB0aGUgaW50ZXJtZWRpYXRlIHZhbHVlIHRoZW9yZW0gY2FsbGVkIEJvbHphbm/igJlzIHRoZW9yZW0gd2hpY2ggc3RhdGVzIHRoYXQgaWYgdGhlIHZhbHVlcyBvZiAkZihhKSQgYW5kICRmKGIpJCBoYXZlIG9wcG9zaXRlIHNpZ25zLCB0aGUgaW50ZXJ2YWwgbXVzdCBjb250YWluIGF0IGxlYXN0IG9uZSByb290LiBUaGUgaXRlcmF0aW9uIHN0ZXBzIG9mIHRoZSBiaXNlY3Rpb24gbWV0aG9kIGFyZSByZWxhdGl2ZWx5IHN0cmFpZ2h0Zm9yd2FyZCwgaG93ZXZlcjsgY29udmVyZ2VuY2UgdG93YXJkcyBhIHNvbHV0aW9uIGlzIHNsb3cgY29tcGFyZWQgdG8gb3RoZXIgcm9vdC1maW5kaW5nIG1ldGhvZHMuDQoNCg0KIyMgTWF0ZW1hdGljYWwgRm9ybXVsYQ0KDQpUaGUgSW50ZXJ2YWwgaXMgZGl2aWRlZCBpbnRvIGhhbGYuDQoNCiQkYz1cZnJhY3soYStiKX17Mn0kJA0KDQoqIFRoZSBmdW5jdGlvbiBpcyBldmFsdWF0ZWQgYXQgJGMkDQoNCiogTG9jYXRpb24gb2YgdGhlIHJvb3QgaXMgZGV0ZXJtaW5lZCBhcyBseWluZyB3aXRoaW4gdGhlIHN1YmludGVydmFsIGZvciB0aGUgbmV4dCBpdGVyYXRpb24gKCRjJCBpcyByZXBsYWNlZCBlaXRoZXIgYnkgJGEkIG9yICRiJCkuDQoNCiogVGhpcyBwcm9jZXNzIGlzIHJlcGVhdGVkIHVudGlsIHRoZSBkZXNpcmVkIHByZWNpc2lvbi4NCg0KIyMgVGhlIEJpc2VjdGlvbiBBbGdvcml0aG0NCg0KRm9yIGEgZ2l2ZW4gZnVuY3Rpb24gZih4KSx0aGUgQmlzZWN0aW9uIE1ldGhvZCBhbGdvcml0aG0gd29ya3MgYXMgZm9sbG93czoNCg0KMS4gVHdvIHZhbHVlcyBhIGFuZCBiIGFyZSBjaG9zZW4gZm9yIHdoaWNoICRmKGEpPjAkIGFuZCAkZihiKTwwJCAob3IgdGhlIG90aGVyIHdheSBhcm91bmQpDQoyLiBJbnRlcnZhbCBoYWx2aW5nOiBBIG1pZHBvaW50ICRjJCBpcyBjYWxjdWxhdGVkIGFzIHRoZSBhcml0aG1ldGljIG1lYW4gYmV0d2VlbiAkYSQgYW5kICRiJCwkYz0oYStiKS8yJA0KMy4gVGhlIGZ1bmN0aW9uICRmJCBpcyBldmFsdWF0ZWQgZm9yIHRoZSB2YWx1ZSBvZiAkYyQNCjQuIElmICRmKGMpPTAkIG1lYW5zIHRoYXQgd2UgZm91bmQgdGhlIHJvb3Qgb2YgdGhlIGZ1bmN0aW9uLCB3aGljaCBpcyAkYyQNCjUuIElmICRmKGMpXG5lcSAwJCB3ZSBjaGVjayB0aGUgc2lnbiBvZiAkZihjKSQ6DQogICAgICogaWYgJGYoYykkIGhhcyB0aGUgc2FtZSBzaWduIGFzICRmKGEpJCwgd2UgcmVwbGFjZSAkYSQgd2l0aCAkYyQgYW5kIHdlIGtlZXAgdGhlIHNhbWUgdmFsdWUgZm9yICRiJC4NCiAgICAgKiBpZiAkZihjKSQgaGFzIHRoZSBzYW1lIHNpZ24gYXMgJGYoYikkLCB3ZSByZXBsYWNlICRiJCB3aXRoICRjJCBhbmQgd2Uga2VlcCB0aGUgc2FtZSB2YWx1ZSBmb3IgJGEkDQo2LiBXZSBnbyBiYWNrIHRvIHN0ZXAgMi4gYW5kIHJlY2FsY3VsYXRlICRjJCB3aXRoIHRoZSBuZXcgdmFsdWUgZWl0aGVyIGl0IGlzIHZhbHVlIG9mICRhJCBvciAkYiQNCg0KVGhlIGFsZ29yaXRobSBlbmRzIHdoZW4gdGhlIHZhbHVlcyBvZiAkZihjKSQgaXMgbGVzcyB0aGFuIGEgZGVmaW5lZCB0b2xlcmFuY2UgKGUuZy4gMC4wMDEpLiBJbiB0aGlzIGNhc2Ugd2Ugc2F5IHRoYXQgJGMkIGlzIGNsb3NlIGVub3VnaCB0byBiZSB0aGUgcm9vdCBvZiB0aGUgZnVuY3Rpb24gZm9yIHdoaWNoICRmKGMpIH49IDAkLg0KDQpJbiBvcmRlciB0byBhdm9pZCB0b28gbWFueSBpdGVyYXRpb25zLCB3ZSBjYW4gc2V0IGEgbWF4aW11bSBudW1iZXIgb2YgaXRlcmF0aW9ucyAoZS5nLiAxMDAwKSBhbmQgZXZlbiBpZiB3ZSBhcmUgYWJvdmUgdGhlIGRlZmluZWQgdG9sZXJhbmNlLCB3ZSBrZWVwIHRoZSBsYXN0IHZhbHVlIG9mIGMgYXMgdGhlIHJvb3Qgb2Ygb3VyIGZ1bmN0aW9uLg0KDQohW10oQzpcVXNlcnNcSU1FTERBIFNJQU5UVVJJXERvd25sb2Fkc1xEaWFncmFtbS5wbmcpDQoNCiMjIEJpc2VjdGlvbiBBbGdvcml0aG0gaW4gUg0KDQpTdXBwb3NlIHdlIHdhbnQgdG8gZmluZCB0aGUgcm9vdCBvZiB0aGUgZnVuY3Rpb24gJHheM+KIkjJ44oiSNSQuIEl0IGlzIG9mdGVuIHZhbHVhYmxlIHRvIHBsb3QgdGhlIGZ1bmN0aW9uIHRvIGZpbmQgYW4gaW50ZXJ2YWwgY29udGFpbmluZyB0aGUgcm9vdC4NCg0KIyMjIFZpc3VhbGl6ZSB0aGUgZnVuY3Rpb24NCg0KYGBge3J9DQpmdW5jIDwtIGZ1bmN0aW9uKHgpIHsNCiAgeF4zIC0gMiAqIHggLSA1DQp9DQoNCmN1cnZlKGZ1bmMsIHhsaW09YygtMywzKSwgY29sPSdibHVlJywgbHdkPTEuNSwgbHR5PTIpDQphYmxpbmUoaD0wKQ0KYWJsaW5lKHY9MCkNCmBgYA0KDQpBcyB3ZSBjYW4gc2VlIGZyb20gdGhlIHZpc3VhbGl6YXRpb24gYWJvdmUsIHdlIGtub3cgdGhhdCB0aGUgcm9vdCBhcHBlYXJzIHRvIGxpZSBjbG9zZSBpbiAyLiBOZXh0LCB3ZSB3aWxsIHVzZSB0aGUgaW50ZXJ2YWwgWzIsM10gaW4gQmlzZWN0aW9uIE1ldGhvZC4NCg0KIyMjIFVzZSBgTkxSb290YCBwYWNrYWdlcw0KDQpPbiBvZiB0aGUgbW9zdCB1c2VmdWxsIHBhY2thZ2UgZm9yIHRoZSBCaXNlY3Rpb24gTWV0aG9kIGluIFIgaXMgdGhlIGBOTFJvb3RgIHBhY2thZ2UsIGhlcmUgeW91IHdpbGwgYXBwbHkgYEJGZnplcm8oKWAgdG8gZmluZCB0aGUgc29sdXRpb24sIGFzIHlvdSBjYW4gc2VlIGJlbG93Og0KDQpgYGB7cn0NCmxpYnJhcnkoTkxSb290KSAgICAgICAgICAgICAgIyBsb2FkaW5nIHRoZSBwYWNrYWdlIA0KQkZmemVybyhmdW5jLCAyLCAzKSAgICAgICAgICAjIHRvIGZpbmQgdGhlIHNvbHV0aW9uIChqdXN0IGFzIHNpbXBsZSBsaWtlIHRoaXMpDQpgYGANCg0KVGhlIG91dHB1dCBvZiB0aGUgZnVuY3Rpb24gc2hvd3MgdGhlIHJvb3QgaXMgbG9jYXRlZCBhdCAkeD0yLjA5NDU1MyQsIHdoaWNoIG1hdGNoZXMgdGhlIHJlc3VsdHMgZm91bmQgaW4gcHJldmlvdXMgZXhhbXBsZXMgb24gb3RoZXIgcm9vdCBmaW5kaW5nIG1ldGhvZHMgc3VjaCBhcyB0aGUgTmV3dG9uLVJhcGhzb24gbWV0aG9kIGFuZCBTZWNhbnQgbWV0aG9kLg0KDQoNCiMjIyBXcml0ZSBGdW5jdGlvbg0KDQpXZSBjYW4gYWxzbyB3cml0ZSBhIGZ1bmN0aW9uIHRoYXQgaW1wbGVtZW50cyB0aGUgYmlzZWN0aW9uIG1ldGhvZCB1c2luZyB0aGUgaXRlcmF0aW9uIHN0ZXBzIGRldGFpbGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHBvc3QuDQoNCmBgYHtyfQ0KQmFrdGlfQmlzZWN0aW9uIDwtIGZ1bmN0aW9uKGYsIGEsIGIsIG4gPSAxMDAwLCB0b2wgPSAxZS03KSB7DQogICMgSWYgdGhlIHNpZ25zIG9mIHRoZSBmdW5jdGlvbiBhdCB0aGUgZXZhbHVhdGVkIHBvaW50cywgYSBhbmQgYiwgc3RvcCB0aGUgZnVuY3Rpb24gYW5kIHJldHVybiBtZXNzYWdlLg0KICBpZiAoIShmKGEpIDwgMCkgJiYgKGYoYikgPiAwKSkgew0KICAgIHN0b3AoJ3NpZ25zIG9mIGYoYSkgYW5kIGYoYikgZGlmZmVyJykNCiAgfSBlbHNlIGlmICgoZihhKSA+IDApICYmIChmKGIpIDwgMCkpIHsNCiAgICBzdG9wKCdzaWducyBvZiBmKGEpIGFuZCBmKGIpIGRpZmZlcicpDQogIH0NCiAgDQogIGZvciAoaSBpbiAxOm4pIHsNCiAgICBjIDwtIChhICsgYikgLyAyICMgQ2FsY3VsYXRlIG1pZHBvaW50DQogICAgDQogICAgIyBJZiB0aGUgZnVuY3Rpb24gZXF1YWxzIDAgYXQgdGhlIG1pZHBvaW50IG9yIHRoZSBtaWRwb2ludCBpcyBiZWxvdyB0aGUgZGVzaXJlZCB0b2xlcmFuY2UsIHN0b3AgdGhlIA0KICAgICMgZnVuY3Rpb24gYW5kIHJldHVybiB0aGUgcm9vdC4NCiAgICBpZiAoKGYoYykgPT0gMCkgfHwgKChiIC0gYSkgLyAyKSA8IHRvbCkgew0KICAgICAgcmV0dXJuKGMpDQogICAgfQ0KICAgIA0KICAgICMgSWYgYW5vdGhlciBpdGVyYXRpb24gaXMgcmVxdWlyZWQsIA0KICAgICMgY2hlY2sgdGhlIHNpZ25zIG9mIHRoZSBmdW5jdGlvbiBhdCB0aGUgcG9pbnRzIGMgYW5kIGEgYW5kIHJlYXNzaWduDQogICAgIyBhIG9yIGIgYWNjb3JkaW5nbHkgYXMgdGhlIG1pZHBvaW50IHRvIGJlIHVzZWQgaW4gdGhlIG5leHQgaXRlcmF0aW9uLg0KICAgIGlmZWxzZShzaWduKGYoYykpID09IHNpZ24oZihhKSksIA0KICAgICAgICAgICBhIDwtIGMsDQogICAgICAgICAgIGIgPC0gYykNCiAgfQ0KICAjIElmIHRoZSBtYXggbnVtYmVyIG9mIGl0ZXJhdGlvbnMgaXMgcmVhY2hlZCBhbmQgbm8gcm9vdCBoYXMgYmVlbiBmb3VuZCwgDQogICMgcmV0dXJuIG1lc3NhZ2UgYW5kIGVuZCBmdW5jdGlvbi4NCiAgcHJpbnQoJ1RvbyBtYW55IGl0ZXJhdGlvbnMnKQ0KfQ0KYGBgDQoNCk5vdywgd2UgY2FuIGFwcGx5IG91ciBmdW5jdGlvbiBmaW5kIHRoZSByb290IG9mIHRoZSBmdW5jdGlvbiAkeF4z4oiSMnjiiJI1JCBhcyB3ZSBoYXZlIGRvbmUgYWJvdmUgYnkgdXNpbmcgYE5MUm9vdGAgcGFja2FnZXMuIA0KDQpgYGB7cn0NCkJha3RpX0Jpc2VjdGlvbihmdW5jLCAyLCAzKQ0KYGBgDQojIyMgWW91ciBPd24gRnVuY3Rpb24NCg0KYGBge3J9DQpmdW5jIDwtIGZ1bmN0aW9uKHgpIHsNCiAgeF4zIC0gMiAqIHggLSAxMA0KfQ0KDQpjdXJ2ZShmdW5jLCB4bGltPWMoLTMsMyksIGNvbD0nZ3JlZW4nLCBsd2Q9MS41LCBsdHk9MikNCmFibGluZShoPTApDQphYmxpbmUodj0wKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShOTFJvb3QpICAgICAgICAgICAgICAjIGxvYWRpbmcgdGhlIHBhY2thZ2UgDQpCRmZ6ZXJvKGZ1bmMsIDIsIDMpDQpgYGANCg0KYGBge3J9DQoNCkltZWxkYV9CaXNlY3Rpb24gPC0gZnVuY3Rpb24oZiwgYSwgYiwgbiA9IDEwMDAsIHRvbCA9IDFlLTkpIHsNCg0KICBpZiAoIShmKGEpIDwgMCkgJiYgKGYoYikgPiAwKSkgew0KICAgIHN0b3AoJ3NpZ25zIG9mIGYoYSkgYW5kIGYoYikgZGlmZmVyJykNCiAgfSBlbHNlIGlmICgoZihhKSA+IDApICYmIChmKGIpIDwgMCkpIHsNCiAgICBzdG9wKCdzaWducyBvZiBmKGEpIGFuZCBmKGIpIGRpZmZlcicpDQogIH0NCiAgDQogIGZvciAoaSBpbiAxOm4pIHsNCiAgICBjIDwtIChhICsgYikgLyAyIA0KICAgIA0KICAgIGlmICgoZihjKSA9PSAwKSB8fCAoKGIgLSBhKSAvIDIpIDwgdG9sKSB7DQogICAgICByZXR1cm4oYykNCiAgICB9DQogICAgDQogICAgDQogICAgaWZlbHNlKHNpZ24oZihjKSkgPT0gc2lnbihmKGEpKSwgDQogICAgICAgICAgIGEgPC0gYywNCiAgICAgICAgICAgYiA8LSBjKQ0KICB9DQogIA0KICBwcmludCgnVG9vIG1hbnkgaXRlcmF0aW9ucycpDQp9DQoNCkltZWxkYV9CaXNlY3Rpb24oZnVuYywgMiwgMykNCmBgYA0KDQoNCiMgTmV3dG9u4oCZcyBNZXRob2QNCg0KVGhlIE5ld3Rvbi1SYXBoc29uIG1ldGhvZCBpcyBhIG1ldGhvZCBmb3IgYXBwcm94aW1hdGluZyB0aGUgcm9vdHMgb2YgcG9seW5vbWlhbCBlcXVhdGlvbnMgb2YgYW55IG9yZGVyLiBJbiBmYWN0IHRoZSBtZXRob2Qgd29ya3MgZm9yIGFueSBlcXVhdGlvbiwgcG9seW5vbWlhbCBvciBub3QsIGFzIGxvbmcgYXMgdGhlIGZ1bmN0aW9uIGlzIGRpZmZlcmVudGlhYmxlIGluIGEgZGVzaXJlZCBpbnRlcnZhbC4gJ3Mgb2Z0ZW4gYmVjb21lIGluY3JlYXNpbmdseSBiZXR0ZXIgYXBwcm94aW1hdGlvbnMgb2YgdGhlIGZ1bmN0aW9uJ3Mgcm9vdC4gTmV3dG9uJ3MgbWV0aG9kIHVzdWFsbHkgdXNlIGZvciBzb2x2aW5nIGVxdWF0aW9ucyBpcyBhbm90aGVyIG51bWVyaWNhbCBtZXRob2QgZm9yIHNvbHZpbmcgYW4gZXF1YXRpb24gJGYoeCk9MCQuIEl0IGlzIGJhc2VkIG9uIHRoZSBnZW9tZXRyeSBvZiBhIGN1cnZlLCB1c2luZyB0aGUgdGFuZ2VudCBsaW5lcyB0byBhIGN1cnZlLiBBcyBzdWNoLCBpdCByZXF1aXJlcyBbY2FsY3VsdXNdKGh0dHBzOi8vdHV0b3JpYWwubWF0aC5sYW1hci5lZHUvY2xhc3Nlcy9jYWxjaS9uZXd0b25zbWV0aG9kLmFzcHgpLCBpbiBwYXJ0aWN1bGFyIGRpZmZlcmVudGlhdGlvbi4gUm91Z2hseSwgdGhlIGlkZWEgb2YgTmV3dG9uJ3MgbWV0aG9kIGlzIGFzIGZvbGxvd3MuDQoNCiMjIE1hdGVtYXRpY2FsIEZvcm11bGENCg0KSWYgJHhfbiQgaXMgYW4gYXBwcm94aW1hdGlvbiBhIHNvbHV0aW9uIG9mICRmKHgpPTAkIGFuZCBpZiAkZicoeF9uKVxuZXEgMCQgdGhlIG5leHQgYXBwcm94aW1hdGlvbiBpcyBnaXZlbiBieSwNCg0KJCR4X3tuKzF9PXhfbi1cZnJhY3tmKHhfbil9e2YnKHhfbil9JCQNCg0KIyMgVGhlIE5ld3RvbuKAmXMgQWxnb3JpdGhtDQoNCjEuIEZpbmQgcG9pbnRzICRhJCBhbmQgJGIkIHN1Y2ggdGhhdCAkYSA8IGIkIGFuZCAkZihhKS5mKGIpIDwgMCQuDQoyLiBUYWtlIHRoZSBpbnRlcnZhbCAkW2EsYl0kIGFuZCBmaW5kIG5leHQgdmFsdWUgJHhfMD1cZnJhY3soYStiKX17Mn0kDQozLiBGaW5kICRmKHhfMCkkIGFuZCAkZicoeF8wKSQsICR4XzE9eF8wLVxmcmFje2YoeDApfXtmJyh4XzApfSQNCjQuIElmICRmKHhfMSk9MCQgdGhlbiAkeF8xJCBpcyBhbiBleHRyYWN0IHJvb3QsIGVsc2UgJHhfMD14XzEkLg0KNS4gUmVwZWF0IHN0ZXBzIDIgdG8gNCB1bnRpbCAkZih4X2kpPTAkIG9yICR8Zih4X2kpfFxsZXEgQWNjdXJhY3kkLg0KDQohW10oQzpcVXNlcnNcSU1FTERBIFNJQU5UVVJJXERvd25sb2Fkc1xmbG93Y2hhcnQucG5nKQ0KDQojIyBOZXd0b27igJlzIE1ldGhvZCBpbiBSDQoNClN1cHBvc2Ugd2Ugd2FudCB0byBmaW5kIHRoZSByb290IG9mIHRoZSBmdW5jdGlvbiAkZih4KT14XjLiiJI5IFx0ZXh0eyBmb3IsICB9IHg+MCQuIFdlIGFzc3VtZSB0aGF0ICRmJCBpcyBzbW9vdGggKGRpZmZlcmVudGlhYmxlKS4gT3VyIGdvYWwgaXMgdG8gZmluZCBhIHJvb3Qgb2YgJGYkIGkuZSBhICR4JCB2YWx1ZSBmb3Igd2hpY2ggJGYoeCk9MCQuIFdlIGlsbHVzdHJhdGUgdGhlIG1ldGhvZCB3aXRoIGEgc2ltcGxlIGV4YW1wbGUgZm9yIHdoaWNoIHlvdSBrbm93IHRoZSByb290Lg0KDQojIyMgVmlzdWFsaXplIHRoZSBmdW5jdGlvbg0KDQpgYGB7cn0NCiMgZmlyc3QgZ2VuZXJhdGUgdGhlIHNlcXVlbmNlDQp4LnNlcSA8LSBzZXEoZnJvbSA9IDAuMSwgdG8gPSAxMCwgbGVuZ3RoLm91dCA9IDEwMSkNCmYgPC0gc2FwcGx5KHguc2VxLCBmdW5jdGlvbih4KSB4XjIgLSA5KQ0KYGBgDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQojIHB1dCB0aGUgeCBhbmQgeSB2YWx1ZXMgaW4gYSBkYXRhIGZyYW1lDQpwbG90X2RhdGEgPC0gZGF0YS5mcmFtZSgieCIgPSB4LnNlcSwgImYiID0gZikNCmhlYWQocGxvdF9kYXRhKQ0KYGBgDQpgYGB7cn0NCiMgY3JlYXRlIHRoZSBiYXNlIGxheWVyIG9mIGdncGxvdCB3aXRoIGdlb21fTGluZQ0KcGxvdF9mIDwtIGdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0geCwgeSA9IGYpKSArIA0KICBnZW9tX2xpbmUoY29sb3IgPSAicmVkIiwgc2l6ZSA9IDEuMCkgKyANCiAgbGFicyh4ID0gIngiLCB5ID0gImYoeCkgPSB4XjIgLSA5IikNCiMgYmVhdXRpZnkgOiBJbmNyZWFzZSBmb250IHNpemUgaW4gYXhlcyANCnBsb3RfZiArIHRoZW1lKGF4aXMudGV4dC54ID0gDQogICAgICAgICAgICAgICAgIGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLHNpemUgPSAxMiksDQogICAgICAgICAgICAgICBheGlzLnRleHQueSA9IA0KICAgICAgICAgICAgICAgICBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDEyKSwNCiAgICAgICAgICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMSwgbGluZXR5cGUgPSAic29saWQiKSkNCmBgYA0KQnkgY29uc2lkZXJpbmcgdGhlIHZpc3VhbGl6YXRpb24gYWJvdmUsIGl0J3MgbG9va3MgbGlrZSB0aGUgZnVuY3Rpb24gaXMgMCBhcm91bmQgMy4gSG93IGRvIHdlIGtub3cgdGhhdCBleGFjdGx5IGNvcnJlY3QsIGxldCdzIHRyeSB6b29tIHRoZSB2aXN1YWxpemF0aW9uLg0KDQpgYGB7cn0NCnBsb3RfZiArIA0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjAwLCBjb2xvciA9ICJncmVlbiIsIHNpemUgPSAxKSArDQogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygyLDQpLCB5bGltID0gYygtMSwgMykpDQpgYGANCg0KTmV4dCwgbGV0IHVzIHZpc3VhbGl6ZSB0aGlzIHRvIGZpbmQgdGhlIHJvb3Qgb2Ygb3VyIGZ1bmN0aW9uICRmKHgpPXheMuKIkjkuJCBGaXJzdCB3ZSBuZWVkIHRvIGNyZWF0ZSBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgdGFuZ2VudCBsaW5lIHRvIHRoZSBmdW5jdGlvbiBmIGF0IHNvbWUgcG9pbnQgYS4NCg0KYGBge3J9DQojIExldCB1cyBjcmVhdGUgb3VyIHRhbmdlbnQgbGluZSBmdW5jdGlvbiBhdCBzb21lIHBvaW50IGENCmZfdGFuZ2VudCA8LSBmdW5jdGlvbih4LCBmLCBkZiwgYSl7DQogICMgV2UgbmVlZCB0aGUgZnVuY3Rpb24gYW5kIGl0cyBkZXJpdmF0aXZlIGRmDQogICMgYSBpcyB0aGUgcG9pbnQgd2hlcmUgd2UgY3JlYXRlIHRoZSB0YW5nZW50IHRvIHRoZSBmdW5jdGlvbg0KICAjIHJldHVybnMgdGhlIHRhbmdlbnQgbGluZSANCiAgZGYoYSkqKHggLSBhKSArIGYoYSkNCn0NCmBgYA0KDQpUaGVuLCBwbG90IHRoZSB0YW5nZW50IGxpbmUgdG8gdGhlIGluaXRpYWwgdmFsdWUgJGYkICBhdCAkeCgwKT00JCAgd2hpY2ggd2lsbCBiZSBvdXIgZmlyc3QgZ3Vlc3Mgb2YgdGhlIHJvb3QuDQoNCmBgYHtyfQ0KIyBhZGQgdGhlIHRhbmdlbnQgbGluZSBhdCA0IHRvIG91ciBkYXRhIGZyYW1lDQpwbG90X2RhdGEkZi50YW4gPC0gc2FwcGx5KHBsb3RfZGF0YSR4LCBmX3RhbmdlbnQsIGYgPSBmdW5jdGlvbih4KSB4XjIgLSA5LCBkZiA9IGZ1bmN0aW9uKHgpIDIqeCwgYSA9IDQpDQoNCiMgY3JlYXRlIHRoZSBiYXNlIGxheWVyIG9mIGdncGxvdCB3aXRoIGdlb21fTGluZQ0KcGxvdF90YW5nZW50X2xpbmUgPC0gZ2dwbG90KHBsb3RfZGF0YSwgYWVzKHggPSB4KSkgKyANCiAgZ2VvbV9saW5lKGFlcyh5ID0gZiksIGNvbG9yID0gInJlZCIsIHNpemUgPSAwLjk1KSArDQogIGdlb21fbGluZShhZXMoeSA9IGYudGFuKSwgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAwLjk1KSArDQogIGxhYnMoeCA9ICJ4IiwgeSA9ICJmKHgpIGFuZCB0YW5nZW50IGxpbmUgYXQgNCIpIA0KcGxvdF90YW5nZW50X2xpbmUNCmBgYA0KDQpOZXh0LCBsZXQgdXMgem9vbSBpbiBvbiAkMuKJpHjiiaQ0JCBhbmQgdHJ5IHRvIHNlZSB3aGVyZSB0aGUgdGFuZ2VudCBsaW5lIGlzIGVxdWFsIHRvIDAuDQoNCmBgYHtyfQ0KIyB6b29tIGluIGJldHdlZW4gMyBhbmQgNA0KcGxvdF90YW5nZW50X2xpbmUgKyANCiAgIyBhZGQgYSBob3Jpem9udGFsIGxpbmUgYXQgMA0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjAwLCBjb2xvciA9ICJncmVlbiIsIHNpemUgPSAxKSArDQogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygyLDQpLCB5bGltID0gYygtNSwgMTApKQ0KYGBgDQoNCkJ5IGNvbnNpZGVyaW5nIHRoZSB2aXN1YWxpemF0aW9uIGFib3ZlLCBsb29rcyBsaWtlIHRoZSB0YW5nZW50IGxpbmUgaXMgMCBhcm91bmQgMy4xLiBUaGlzIHdpbGwgYmUgb3VyIHVwZGF0ZWQgZ3Vlc3MgYXQgdGhlIHJvb3QuIFVuZGVyc3RhbmQgdGhlIHJhdGlvbmFsZSBiZWhpbmQgdGhpcy4gSWYgZiBpcyBhcHByb3hpbWF0ZWx5IGVxdWFsIHRvIGl0cyB0YW5nZW50IGxpbmUgYXQgNCwgdGhlbiB0aGUgcm9vdCBvZiAkZiQgaXMgYXBwcm94aW1hdGVseSBlcXVhbCB0byB0aGUgcm9vdCBvZiB0aGUgdGFuZ2VudCBsaW5lLiBDYW4geW91IHNlZSB0aGlzIGluIHRoZSBwbG90IGFib3ZlPw0KDQpUaGUgZXhhY3QgdmFsdWUgd2hlbiB0aGUgdGFuZ2VudCBsaW5lIGlzIDAgaXMgZ2l2ZW4gYnkNCg0KJCQgeF57KDEpfT004oiSe2YoNCkgXG92ZXIgZuKAsig0KX0gPTMuMTI1JCQNCg0KVGhlbiwgYWRkIHRoZSB0YW5nZW50IGxpbmUgYXQgMy4xMjUgdG8gb3VyIGRhdGEgZnJhbWUNCg0KYGBge3J9DQpwbG90X2RhdGEkZi50YW4gPC0gc2FwcGx5KHBsb3RfZGF0YSR4LCBmX3RhbmdlbnQsIGYgPSBmdW5jdGlvbih4KSB4XjIgLSA5LCBkZiA9IGZ1bmN0aW9uKHgpIDIqeCwgYSA9IDMuMTI1KQ0KDQojIGNyZWF0ZSB0aGUgYmFzZSBsYXllciBvZiBnZ3Bsb3Qgd2l0aCBnZW9tX0xpbmUNCnBsb3RfdGFuZ2VudF9saW5lIDwtIGdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0geCkpICsgDQogIGdlb21fbGluZShhZXMoeSA9IGYpLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMC45NSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBmLnRhbiksIGNvbG9yID0gImJsdWUiLCBzaXplID0gMC45NSkgKw0KICBsYWJzKHggPSAieCIsIHkgPSAiZih4KSBhbmQgdGFuZ2VudCBsaW5lIGF0IDQiKSANCnBsb3RfdGFuZ2VudF9saW5lDQpgYGANCg0KTm93IGxldCB1cyB6b29tIGluIG9uIGFyb3VuZCAzIGFuZCB0cnkgdG8gc2VlIHdoZXJlIHRoZSB0YW5nZW50IGxpbmUgaXMgZXF1YWwgdG8gMC4NCg0KYGBge3J9DQojIHpvb20gaW4gYmV0d2VlbiAyLjkgYW5kIDMuMQ0KcGxvdF90YW5nZW50X2xpbmUgKyANCiAgIyBhZGQgYSBob3Jpem9udGFsIGxpbmUgYXQgMA0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjAwLCBjb2xvciA9ICJncmVlbiIsIHNpemUgPSAxKSArDQogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygyLjksMy4xKSwgeWxpbSA9IGMoLTIuNSwgMi41KSkNCmBgYA0KDQpMb29rcyBsaWtlIHRoZSB0YW5nZW50IGxpbmUgaXMgMCBhcm91bmQgMy4gSW4ganVzdCB0d28gc3RlcHMgd2UgYXJlIHZlcnkgY2xvc2UuIFRoaXMgd2lsbCBiZSBvdXIgdXBkYXRlZCBndWVzcyBhdCB0aGUgcm9vdC4gVGhlIGV4YWN0IHZhbHVlIHdoZW4gdGhlIHRhbmdlbnQgbGluZSBpcyAwIGlzIGdpdmVuIGJ5DQoNCiQkIHheeygyKX09eF57KDEpfeKIkntmKHheeygxKX0pIFxvdmVyIGbigLIoeF57KDEpfSl9JCQNCiQkIHheeygyKX09My4xMjXiiJJ7ZigzLjEyNSkgXG92ZXIgZuKAsigzLjEyNSl9ID0gMy4wMDI1JCQNCg0KV2UgY2FuIGNvbnRpbnVlIHVudGlsIG91ciBndWVzc2VzIGtlZXAgZ2V0dGluZyBzbWFsbGVyIGFuZCBzbWFsbGVyLg0KDQojIyMgVXNlIGBOTFJvb3RgIHBhY2thZ2VzDQoNClRoZSBzYW1lIHBhY2thZ2VzIGFzIHdlIHVzZSB0byB0aGUgQmlzZWN0aW9uIE1ldGhvZCwgdGhpcyBwYWNrYWdlcyBhbHNvIGF2YWlsYWJsZSBmb3IgTmV3dG9uJ3MgbWV0aG9kLiANCg0KYGBge3J9DQpsaWJyYXJ5KE5MUm9vdCkNCiMgZmlyc3QgYXJndW1lbnQgaXMgdGhlIGZ1bmN0aW9uIHdob3NlIHJvb3Qgd2UgbmVlZCB0byBmaW5kDQojIHNlY29uZCBhcmd1bWVudCBpcyB0aGUgdGhlIGRlcml2YXRpdmUgb2YgdGhlIGZ1bmN0aW9uIHdob3NlIA0KIyByb290IHdlIG5lZWQgdG8gZmluZC4NCiMgdGhpcmQgYXJndW1lbnQgaXMgYW4gaW5pdGlhbCBndWVzcw0KTklNZnplcm8oZnVuY3Rpb24oeCkgeF4yLTksIGZ1bmN0aW9uKHgpIDIqeCwgeDAgPSA0KQ0KYGBgDQoNCg0KIyBbQ2FzZSBTdHVkeV0oaHR0cHM6Ly9ycHVicy5jb20val9sYXBvcnRlLzU2NDI4MCkgDQoNCkluIHRoaXMgbGVzc29uIHdlIHdpbGwgY29uc3RydWN0IHR3byBmdW5jdGlvbnMgdGhhdCB5b3Ugd2lsbCBuZWVkIGZvciB0aGlzIGNvdXJzZSBhbmQgYmVnaW4gdG8gZXhwbG9yZSB0aGUgUiBwcm9ncmFtbWluZyBsYW5ndWFnZS4gUnVuIHRocm91Z2ggdGhlIENoYXB0ZXIgMSBvZiB0aGUgYm9vayB3aGljaCB0YWxrcyBhYm91dCBtb2RlbCBidWlsZGluZyBmb3IgYSBvbmUtdmFyaWFibGUgb3B0aW1pemF0aW9uIHByb2JsZW0uIEV4YW1wbGUgMS4xIChNZWVyc2NoYWVydCkgQSBwaWcgd2VpZ2hpbmcgMjAwIGxicyBnYWlucyA1IGxicyBwZXIgZGF5IGFuZCBjb3N0cyA0NSBjZW50cyBwZXIgZGF5IHRvIGtlZXAgKGZlZWQgYW5kIGJvYXJkKS4gVGhlIG1hcmtldCBwcmljZSBmb3IgcGlncyBpcyA2NSBjZW50cyBwZXIgcG91bmQsIGJ1dCBpcyBmYWxsaW5nIDEgY2VudCBwZXIgZGF5LiBXaGVuIHNob3VsZCB0aGUgcGlnIGJlIHNvbGQ/DQoNCioqTW9kZWxpbmcgdGhlIFByb2JsZW0qKg0KDQoxLiBWYXJpYWJsZXM6DQorICR0JCA9IHRpbWUgKGRheXMpDQorICR3JCA9IHdlaWdodCBvZiB0aGUgcGlnKGxicykNCisgJHAkID0gcHJpY2UgZm9yIHBpZ3MgKCQvbGIpDQorICRDJCA9IGNvc3Qgb2Yga2VlcGluZyBwaWcgdCBkYXlzICgkKQ0KKyAkUiQgPSByZXZlbnVlIG9idGFpbmVkIGJ5IHNlbGxpbmcgcGlnICgkKQ0KKyAkUCQgPSBwcm9maXQgZnJvbSBzZWxsaW5nIHBpZyAoJCkNCg0KMi4gQXNzdW1wdGlvbnM6DQoqICR3PTIwMCs1dCQNCiogJHA9MC42NeKIkjAuMDF0JA0KKiAkQz0wLjQ1dCQNCiogJFI9cOKLhXckDQoqICRQPVLiiJJDJA0KKiAkdCBcZ2VxIDAkDQoNCioqT2JqZWN0aXZlOiBNYXhpbWl6ZSBwcm9maXRzIGZyb20gdGhlIHNlbGwgb2YgdGhlIHBpZyoqDQoNCkxldCAkeCQgYmUgdGhlIHRpbWUgdG8gc2VsbCB0aGUgcGlnIGFuZCBkZXZlbG9wIHRoZSBwcm9maXQgZnVuY3Rpb24gdXNpbmcgeCBhcyB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUuIEluIHRoZSBjYXNlIG9mIGFuIG9wdGltaXphdGlvbiwgdGhlIHZhcmlhYmxlIG9uIHdoaWNoIHlvdSB3aWxsIG1ha2UgYSBkZWNpc2lvbiBvbiBpcyBnZW5lcmFsbHkgY2FsbGVkIGEgZGVjaXNpb24gDQoNClByb2ZpdCBGdW5jdGlvbiA9IE9iamVjdGl2ZSBmdW5jdGlvbi4NCkdpdmVuIHRoZSBkZXNjcmlwdGlvbiBhbmQgbWF0aGVtYXRpY2FsIGV4cGxhbmF0aW9uIG9mIHRoZSB2YXJpYWJsZXMsIGxldHMgd3JpdGUgb3V0IHRoZSBwcm9maXQgZnVuY3Rpb246DQoNCiFbXShDOlxVc2Vyc1xJTUVMREEgU0lBTlRVUklcRG93bmxvYWRzXGNhc2UucG5nKQ0KDQpMZXQncyB1c2UgUiB0byDigJxzZWXigJ0gd2hhdCB0aGUgcHJvZml0IGZ1bmN0aW9uIGxvb2tzIGxpa2Ugb3ZlciB0aGUgbmV4dCAyMCBkYXlzLg0KDQpgYGB7cn0NCnByb2ZpdCA9IGZ1bmN0aW9uICh4KXsNCiAgcmV0dXJuKCgwLjY1LTAuMDEqeCkqKDIwMCs1KngpLS40NSp4KQ0KfQ0KeCA9IHNlcSgwLDIwLDEpDQpwbG90KHgscHJvZml0KHgpLHR5cGU9Im8iKQ0KcHJpbnQocHJvZml0KDgpKQ0KYGBgDQoNCkFzIHlvdSBjYW4gc2VlLCB0aGVyZSBpcyBhIGdvb2QgYW5kIGJhZCBkYXkgdG8gc2VsbCB0aGUgcGlnIGlmIG91ciBhc3N1bXB0aW9ucyByZW1haW4gdGhlIHNhbWUgb3ZlciB0aGUgbmV4dCAyMCBkYXlzLiBBbHRob3VnaCB3ZSBjb3VsZCB1c2UgdGhpcyBncmFwaCBpbiBvcmRlciB0byBzZWxlY3QgdGhlIOKAnHdpbm5lcuKAnSwgd2Ugd2FudCB0byBiZSBhYmxlIHRvIHVzZSB0aGlzIHRvb2wgKFIgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UpIHRvIGFzc2lzdCB1cyBpbiBlbnN1cmluZyB0aGF0IHdlIGhhdmUgYWxsIG9mIHRoZSBpbmZvcm1hdGlvbiBuZWVkZWQgdG8gbWFrZSBhIGRlY2lzaW9uLiBUaGF0IG1lYW5zIHRoYXQgd2UgbmVlZCB0byBnZXQgb3VyIGhhbmRzIGRpcnR5IGFuZCBmaWd1cmUgb3V0IGhvdyB0byB1c2Ugb3VyIHRvb2xzIChpbiB0aGlzIGNhc2UsIFIpLg0KDQojIyBCdWlsZCB0aGUgZnVuY3Rpb25zIHRoYXQgd2UgbmVlZCB0byBzb2x2ZSB0aGUgcHJvYmxlbQ0KDQpXZSB3aWxsIGNyZWF0ZSB0d28gZnVuY3Rpb25zIHRoYXQgd2lsbCBiZSBhYmxlIHRvIHNvbHZlIGZvciBhbiBvcHRpbWFsIHBvaW50IGluIFIgdXNpbmcgbWF0aGVtYXRpY3MgLyBwcm9ncmFtbWluZyB0aGF0IHdlIGFscmVhZHkga25vdyBob3cgdG8gZG8uIA0KDQpVc2luZyB0aGlzIHNpbXBsZSBmb3JtdWxhLCBsZXTigJlzIGJ1aWxkIGEgZGVyaXZhdGl2ZSBvZiB0aGUgcHJvZml0IGZ1bmN0aW9uIHRoYXQgd2UgZGVmaW5lZCBhYm92ZS4gTm90aWNlIGhvdyBvdXIgZnVuY3Rpb24gZnByaW1lKGYseCkgd2lsbCB3b3JrIGZvciBBTlkgZnVuY3Rpb24gdGhhdCB3ZSBhc3NpZ24gdG8gaXQuDQoNCmBgYHtyfQ0KeD1zZXEoMCwyMCkNCmZwcmltZSA9IGZ1bmN0aW9uIChmLGEsaD0wLjAwMDEpeyhmKGEraCktZihhLWgpKS8oMipoKX0NCnBsb3QoeCxmcHJpbWUocHJvZml0LHgpKQ0KYGBgDQoNCiMjIFJvb3QtRmluZGluZyBTb2x2ZXINCg0KQWx0aG91Z2ggd2UgY291bGQgdXNlIHRoZSBncmFwaCBhYm92ZSB0byBmaW5kIHRoZSBzb2x1dGlvbiBmb3IgdGhpcyBwYXJ0aWN1bGFyIHByb2JsZW0sIGl0IGlzIG1vcmUgYXBwcm9wcmlhdGUgdG8gdXNlIG1hdGggdG8gbWFrZSBvdXIgc29sdXRpb24gYXV0b21hdGljLiBUaGVyZSBhcmUgbWFueSByb290LWZpbmRpbmcgYWxnb3JpdGhtcyBvdXQgdGhlcmUgYW5kIGZlZWwgZnJlZSB0byB1c2UgYW5vdGhlciwgYnV0IHdlIHdpbGwgdXNlIGEgc2ltcGxlIGFsZ29yaXRobSBrbm93biBhcyB0aGUgYmlzZWN0aW9uIG1ldGhvZC4gVGhpcyBtZXRob2Qgb25seSByZXF1aXJlcyB0aGF0IHlvdSBzZWxlY3QgdHdvIHBvaW50cyB0aGF0IGhhdmUgb3Bwb3NpdGUgc2lnbnM6IGlmICRmKGEpPeKIkiQgdGhlbiAkZihiKT0rJC4NCg0KIyMgQmlzZWN0aW9uIEFsZ29yaXRobSBmb3IgZmluZGluZyB0aGUgcm9vdCBvZiBhbiBlcXVhdGlvbi4NCg0KVGhlIHNpbXBsZSBpZGVhIG9mIHRoZSBiaXNlY3Rpb24gbWV0aG9kIGlzIHRoYXQgeW91IHN0YXJ0IHdpdGggYW4gaW50ZXJ2YWwgW2EsYl0gdGhhdCBoYXMgYSBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgdmFsdWUgZm9yIHRoZSBmdW5jdGlvbiAkZihhKSQgYW5kICRmKGIpJCAtIGl0IGRvZXMgbm90IG1hdHRlciB3aGljaCBvbmUgaXMgcG9zaXRpdmUuIFlvdSBjdXQgdGhlIGludGVydmFsIGluIGhhbGYgYW5kIHByb2NlZWQgd2l0aCB0aGUgaW50ZXJ2YWwgdGhhdCBrZWVwcyBvbmUgc2lkZSBwb3NpdGl2ZSBhbmQgdGhlIG90aGVyIG5lZ2F0aXZlLiBJbiBGaWd1cmUgMSwgd2Ugc3RhcnQgb24gdGhlIGludGVydmFsIFsyLDldIHdoaWNoIHdvcmtzIGJlY2F1c2UgJGYoMikkIGlzIHBvc2l0aXZlIGFuZCAkZig5KSQgaXMgbmVnYXRpdmUuIFRoZSBmaXJzdCBzdGVwIGN1dHMgdGhlIGludGVydmFsIGluIGhhbGYgYW5kIHRoZSBkZWNpc2lvbiBtdXN0IGJlIG1hZGUgdG8gY29udGludWUgd2l0aCBbMiw1LjVdIG9yIFs1LjUsOV0uIEl0IHNob3VsZCBiZSBwcmV0dHkgb2J2b3VzIGZyb20gdGhlIHBpY3R1cmUgdGhhdCBbMiw1LjVdIGlzIHRoZSByaWdodCBhbnN3ZXIgKHdlIHdhbnQgdG8ga2VlcCBhIHJvb3QgaW4gdGhlIGludGVydmFsKSwgYnV0IGZyb20gYW4gYWxnb3JpdGhtIHBlcnNwZWN0aXZlLCB3ZSBzaW1wbHkgdGVzdCBmKDUuNSkgYW5kIGZpbmQgb3V0IHRoYXQgaXQgaXMgbmVnYXRpdmUgd2hpY2ggY2F1c2VzIHVzIHRvIHJlcGxhY2UgOSAoJGZbOV0kIHdhcyBuZWdhdGl2ZSkgd2l0aCA1LjUuIFdlIHdvdWxkIGNvbnRpbnVlIHRoaXMgYWxnb3JpdGhtIHVudGlsIHdlIGFyZSBzYXRpc2ZpZWQgdGhhdCB0aGUgd2lkdGggb2YgdGhlIGludGVydmFsIGlzIHNtYWxsIGVub3VnaCB0byBtYWtlIGEgY29uY2x1c2lvbiBhYm91dCB0aGUgdmFsdWUgb2YgdGhlIHJvb3QuDQoNCiFbXShDOlxVc2Vyc1xJTUVMREEgU0lBTlRVUklcRG93bmxvYWRzXGJpc2VjdGlvbi5wbmcpDQoNCmBgYHtyfQ0KYmlzZWN0aW9uID0gZnVuY3Rpb24oZixhLGIsdG9sPTAuMDAwMSl7DQogIGlmIChmKGEpKmYoYikgPiAwKXsNCiAgICByZXR1cm4gKCJCb3VuZGFyeSBDb25kaXRpb25zIE5vdCBNZXQiKQ0KICB9DQogIGVsc2V7DQogICAgbWlkZGxlID0gYQ0KICAgIHdoaWxlIChhYnMoZihtaWRkbGUpKT50b2wpew0KICAgICAgbWlkZGxlID0gKGErYikvMg0KICAgICAgaWYgKGYobWlkZGxlKSpmKGEpPjApIChhID0gbWlkZGxlKQ0KICAgICAgZWxzZSAoYiA9IG1pZGRsZSkNCiAgICAgIHg9bWlkZGxlDQogICAgICB5PWYobWlkZGxlKQ0KICAgICAgIyMgaWYgeW91IHdhbnQgdG8gInNlZSIgd2hhdCBoYXBwZW5zIGF0IGV2ZXJ5IHN0ZXAsIHRha2Ugb2ZmIHRoZSAjIG9mIHRoZSBuZXh0IGxpbmUgIyMNCiAgICAgICNjYXQoc3ByaW50ZigieC1WYWw6ICUuNGYgOyBmKHgtdmFsKTogJS40ZlxuIix4LHkpKQ0KICAgIH0NCiAgICByZXR1cm4gKG1pZGRsZSkNCiAgfQ0KfQ0KI0V4YW1wbGUgb2YgYSBmaW5kaW5nIGEgcm9vdCBvZiBhIGZ1bmN0aW9uDQpmID0gZnVuY3Rpb24gKHgpe3heMy01fSAjc2lubGdlIGxpbmUgZnVuY3Rpb24gZGVmaW5pdGlvbg0KemVybz1iaXNlY3Rpb24gKGYsLTEwLDIwKQ0KeD1zZXEoLTEsMiwwLjAxKQ0KcGxvdCh4LGYoeCksImwiKQ0KYWJsaW5lKGg9MCxjb2w9InJlZCIpDQphYmxpbmUodj16ZXJvLGNvbD0icHVycGxlIikNCg0KcHJpbnQoemVybykNCmBgYA0KIyMgVXNlIG91ciB0b29sIHRvIHNvbHZlIHRoZSBwaWcgcHJvYmxlbQ0KVXNlIHRoZSB0b29scyBhdCB5b3VyIGRpc3Bvc2FsIHRvIHNvbHZlIHRoZSBwcm9ibGVtLiBCZSBhYmxlIHRvIG1ha2Ugc2V2ZXJhbCBhbHRlcm5hdGl2ZXMgdG8gdGhlIHByb3Bvc2VkIG1vZGVsIGFuZCBpbnZlc3RpZ2F0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbXVsdGlwbGUgdmFyaWFibGVzLiBXaGVuIGRvIHdlIHNlbGwgdGhlIHBpZz8NCg0KYGBge3J9DQpkUHJvZml0ID0gZnVuY3Rpb24oeCl7ZnByaW1lKHByb2ZpdCx4KX0gI2Rlcml2YXRpdmUgb2YgcHJvZml0IGZ1bmN0aW9uDQpiaXNlY3Rpb24oZFByb2ZpdCwwLDIwKQ0KYGBgDQoNCkFzIHlvdSBjYW4gc2VlLCB3ZSBnb3QgYXBwcm94aW1hdGVseSB0aGUgc2FtZSBhbnN3ZXIgYXMgdGhlIGJvb2suIFRoZSBkaWZmZXJlbmNlIGlzIHRoYXQgb3VyIHNvbHV0aW9uIHVzZXMgYW4gZXN0aW1hdGlvbiBvZiB0aGUgZGVyaXZhdGl2ZSBpbnN0ZWFkIG9mIHRoZSBjbG9zZWQtZm9ybSBzb2x1dGlvbiBhcyB3ZWxsIGFzIGEgc29sdmVyIGZvciBmaW5kaW5nIHRoZSBkYXkgeCB3aGVyZSB0aGUgcHJvZml0IGlzIG1heGltaXplZCAocHJvZml0IGZ1bmN0aW9uIGRlcml2YXRpdmUgPSAwKS4gSW4gdGhlIGNhc2Ugb2YgbW9zdCBwcm9ibGVtcywgeW91IHdpbGwgdXNlIG51bWVyaWNhbCBtZXRob2RzIChsaWtlIHdlIGRpZCkgYmVjYXVzZSByZWFsIHdvcmxkIHByb2JsZW1zIGRvIG5vdCB1c3VzYWxseSBoYXZlIGEgZWFzeSBhbnN3ZXIuIFRvIGJlY29tZSBhIGdvb2QgcHJvYmxlbSBzb2x2ZXIsIHlvdSBhcmUgZ29pbmcgdG8gbmVlZCB0byBpbnZlc3QgaW4geW91ciBjb2RpbmcgYWJpbGl0aWVzIGJlY2F1c2UgeW91IHdpbGwgdXN1YWxseSBuZWVkIHRvIGRldmVsb3Agc29tZSBvcmlnaW5hbCBjb2RlIHRvIGhlbHAgeW91IHNvbHZlIGEgcGFydGljdWxhciBwcm9ibGVtLg0KDQojIyBTZW5zaXRpdml0eSBBbmFseXNpczogUHJpY2Ugb2YgdGhlIFBpZw0KDQpMZXTigJlzIGdvIGJhY2sgYW5kIGV4YW1pbmUgbW9yZSBjbG9zZWx5IG9uZSBvZiBvdXIgb3JpZ2luYWwgYXNzdW1wdGlvbnMgdGhhdCBtYXkgb3IgbWF5IG5vdCBob2xkIHRvIHNlZSBob3cgb3VyIHNvbHV0aW9uIGlzIGFmZnRlY3RlZCBieSBhIGRpZmZlcmVudCBhc3N1bXB0aW9uLiBEb2VzIHRoZSBvcHRpbWFsIGRheSB0byBzZWxsIGNoYW5nZSBpZiB3ZSBhc3N1bWUgc29tZSBkaWZmZXJlbnQgcHJpY2Ugb2YgdGhlIHBpZy4gSGVyZSB3ZSBsZXQgdGhlIHBpZyBwcmljZSBkcm9wIHRvIHJlY3JlYXRlIHRoZSBudW1iZXJzIGluIHRoZSBib29rLCBidXQgd2UgYXJlIGFibGUgdG8gZG8gc28gbXVjaCBtb3JlIHdoaWNoIHdpbGwgYmUgZGVtb25zdHJhdGVkIGluIHRoZSBuZXh0IGFuYWx5c2lzLg0KDQpgYGB7cn0NCiNQcmljZSBmYWxsaW5nIHBlciBkYXkgPSBwIA0KcCA9IHNlcSgwLjAwOCwwLjAxMiwwLjAwMSkNCmFucyA9IGFycmF5KDAsbGVuZ3RoKHApKQ0KZm9yIChpIGluIDE6bGVuZ3RoKHApKXsNCiAgICBwcm9maXQgPSBmdW5jdGlvbiAoeCl7DQogICAgICByZXR1cm4oKDAuNjUtcFtpXSp4KSooMjAwKzUqeCktLjQ1KngpDQogICAgfQ0KICAgIGRQcm9maXQgPSBmdW5jdGlvbih4KXtmcHJpbWUocHJvZml0LHgsKX0NCiAgICBhbnNbaV0gPSBiaXNlY3Rpb24oZFByb2ZpdCwwLDIwLDAuMDAwMSkNCn0NCnByaW50KGFucykNCnBsb3QocCxhbnMsIm8iLHhsYWI9InAoJC9kYXkpIix5bGFiPSJ4KERheXMgdG8gU2VsbCkiKQ0KdGl0bGUoIlNlbnNpdGl2aXR5IG9mIEZhbGxpbmcgUHJpY2Ugb2YgUGlnIikNCmBgYA0KDQojIyBTZW5zaXRpdml0eSBBbmFseXNpczogR3Jvd3RoIFJhdGUgb2YgdGhlIFBpZw0KDQpTaW5jZSB3ZSBhcmUgYWxzbyBjb25jZXJuZWQgYWJvdXQgdGhlIGdyb3d0aCByYXRlIG9mIHRoZSBwaWcsIGxldOKAmXMgY29uZHVjdCBzZWUgaG93IHRoZSBkYXlzIHRvIHNlbGwgYXJlIGFmZmVjdGVkIGJ5IHRoZSBncm93dGggcmF0ZS4gVGhlIHdlaWdodCAodykgaXMgY2FsY3VsYXRlZCB1c2luZyB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSBwaWcgd2lsbCBncm93IDVsYnMgcGVyIGRheSBzbyB0aGF0OiAkJHc9MjAwK2d0JCQgd2hlcmUgJCRnPTUkJC4gTGV04oCZcyBzZWUgd2hhdCBoYXBwZW5zIGlmIGcgaXMgYmV0d2VlbiAzIGFuZCA3LiBSZW1lbWJlciB0aGUgYmlzZWN0aW9uIG1ldGhvZCBuZWVkcyB0d28gYm91bmRhcnkgcG9pbnRzIHRoYXQgaGF2ZSB0aGUgb3Bwb3NpdGUgdmFsdWVzIGFuZCBpZiB0aGUgZ3Jvd3RoIHJhdGUgaXMgdG9vIHNtYWxsLCB0aGluayBhYm91dCB3aGF0IHRoYXQgZG9lcyB0byB0aGUgcHJvZml0LiBFeHBlcmltZW50IHdpdGggbGFyZ2UgYW5kIHNtYWxsIGdyb3d0aCByYXRlcyBhbmQgdGhlIHByb2ZpdCBmdW5jdGlvbiB0byBmaWd1cmUgaXQgb3V0IGZvciB5b3Vyc2VsZiBpZiB5b3UgZG9u4oCZdCBzZWUgaXQuIFdlIG5lZWRlZCB0byBtYWtlIHRoZSBzdGFydGluZyBwb2ludCBvZiB0aGUgYmlzZWN0aW9uIG1ldGhvZCB0byB0aGUgbGVmdCAobmVnYXRpdmUgbnVtYmVyKSBpbiBvcmRlciBmb3IgaXQgdG8gZmluZCB0aGUgemVybyBmb3IgM2xicyBhbmQgMy41IGxicyBwZXIgZGF5Lg0KDQpgYGB7cn0NCiNHcm93dGggcmF0ZSBvZiB0aGUgcGlnID0gZw0KZyA9IHNlcSgxLDEyLDAuNSkNCmFucyA9IGFycmF5KDAsbGVuZ3RoKGcpKQ0KZm9yIChpIGluIDE6bGVuZ3RoKGcpKXsNCiAgICBwcm9maXQgPSBmdW5jdGlvbiAoeCl7DQogICAgICByZXR1cm4oKDAuNjUtMC4wMSp4KSooMjAwK2dbaV0qeCktLjQ1KngpDQogICAgfQ0KICAgIGRQcm9maXQgPSBmdW5jdGlvbih4KXtmcHJpbWUocHJvZml0LHgsKX0NCiAgICBhbnNbaV0gPSBiaXNlY3Rpb24oZFByb2ZpdCwtMTAwLDUwLDAuMDAwMSkNCn0NCnByaW50KGFucykNCnBsb3QoZyxhbnMsIm8iLHhsYWI9ImcoZ3Jvd3RoL2RheSkiLHlsYWI9IngoRGF5cyB0byBTZWxsKSIpDQp0aXRsZSgiU2Vuc2l0aXZpdHkgb2YgR3Jvd3RoIFJhdGUgb2YgUGlnIikNCmBgYA0K