Hello! Welcome to the first of the advanced R workshops on the
LIFE4138 module. Our learning objectives for this session are:
- Learn some advanced programming skills in R, and understand that the
language can be used as a “strict” programming language similar to
Python etc.
- Think about control flow - we’ll introduce the concepts of control
flow, including
for loops, if and
else statements, and the ifelse()
function.
- We will learn to write our own functions, a vital tool when we are
building scripts. We will discuss the usability of custom functions to
avoid replication in your code.
- Finally, we will begin to have a look at our 4th data structure in R
- lists.
What do we mean by “advanced”?
So, the previous sessions have all been designed to give you an
overall grounding of the way that R works, and to try and understand the
different approaches that R users take to the language (baseR versus the
tidyverse approach for e.g.). For most R users, this is enough to get
by. You’ll be able to do the majority of the stuff that you need to
using only the skills that we’ve been through so far.
That being said, there are times, particularly when undertaking
bioinformatic analysis, when perhaps you might like to have a script
that will run independently without your input. Situations such as this
really highlight the importance of the advanced techniques that we’re
about to learn!
Taking it to the next step
The below will begin to give you a greater flexibilty and versatility
with your R coding, and allow you to begin to make R work for you in
exactly the way that you want it to. for loops for example
are a great principle to learn in general with your code, and learning
both the loops themselves as well as the alternatives available in R
will be incredibly useful to you.
Another nice thing about moving on to more advanced coding principles
in R is that they will help to deepen your understanding of how the
basics work. For example, the way that we handle and access vectors will
become clearer as we use more advanced techniques to work through
them.
But how do I become an “advanced” R user?!
Just following tutorials such as this will not make you into an
advanced R user. These tutorials can only go so far - I can introduce
you to a concept, but really what will deepen and strengthen your
understanding is by using the techniques with real-world data, beyond
the structured format of this tutorial.
The best way to learn R (or any programming language), is by
doing, playing, and experimenting.
Critically, you also need to learn how and where to access help.
Don’t be afraid to use google, stack overflow, or to ask your friends or
colleagues for advice. A fresh pair of eyes is much more likely to spot
a rogue comma than you are after you’ve been staring at your screen for
hours. This might seem a little basic for an advanced R tutorial, but
looking for answers online is a great way to see other examples, look at
other peoples coding styles, get help, and importantly, learn to avoid
future mistakes. There are loads of wonderful R resources out there for
you to use, and they are getting increasingly better with time.
Another thing you should develop as you become a more advanced R
user, is your own coding philosophy. My approach is to do what works.
This sounds daft at first, but there are several people whos philosophy
it is to achieve and end result using as few lines of code as possible.
I like to do what works for me, whilst retaining an open mind to new
solutions. It is very easy to get stuck in a coding rut with R, and
continue to use a solution that might quickly become out of date or
impractical/uneccesarily difficult (think about the introduction of the
tidyverse in the 2010s for example!).
The above abilities and ideas will open up your coding abilities, and
allow you to really get to grips with R as both a language and a tool
for data wrangling, plotting, and downstream analysis.
Finally, the importance of your coding environment (I mean physical
environment, not your R environment) cannot be understated. Find a way
to get “in the zone”, and allow yourself to concentrate solely on what
it is that you’re trying to achieve. Focus is important with code, it’s
so easy to make mistakes and end up with analyses that hasn’t done what
you think it has. For me, I make a giant cup of tea, grab some biscuits,
get comfy with a warm jumper, and pop my headphones on. I listen to a
playlist that I have personally curated for a mixture of concentration,
positivity, and motivation. It sounds daft, but I promise, it works. If
I really don’t want to be disturbed, I shut my office door, cover the
window in the door, and turn the lights off (and put my lamp on - I’m
aiming for ambient lighting rather than pitch black!).
I know I just said finally, but actually properly finally, don’t
forget to take a break. If you’re tearing your hair out to debug a piece
of code, or if you’re really stuck and just can’t make something work,
put it down. Walk away, make yourself a cup of tea, have some cake, go
for a run, do whatever you need to for some mental space. Even sleep on
it if you have to. When you come back to it, often the answer will
present itself. If it doesn’t everything will at least feel a little
easier than it did before. Coding can be frustrating, but learning to
manage and harness that frustration is a real skill!
Right. Let’s get to the meat of it.
Control flow
The first concept that we’ll cover today is control flow. You may
well have come across control flow in your forrays with Python and Unix,
and the basic idea of how it works is largely similar in R. Control flow
is a fundemental part of the way that any programming language works,
not just R. It essentially provides a way to control the order that a
set of functions are performed on your dataset.
There are several examples of control flow functions, but the ones we
will concentrate on today are for loops, if
and else statements, and the ifelse()
function. ifelse() isn’t strictly a control flow statement,
but a function from the baseR set of functions.
Before we get started, the way that control flows work are as
follows. Say, for example, you have a condition. You ask whether that
condition is true or false. If the condition is true, you perform a
function.

If it is false, you perform another function. This is easier to
understand with an analogy. We can use if else
statements to write a function to make ourselves a cup of tea. First, we
perform the boil kettle function. Then, we periodically check to see if
the water has boiled. If the outcome of “Has the water boiled” is
FALSE, we perform the wait a bit longer function. We check
again. If the outcome is TRUE, we perform the pour water
function, which then allows us to perform the drink tea function.
Admittedly, this analogy is flawed - it’s missing some vital steps
including adding a tea bag, adding any milk, waiting for the tea to
cool, and cutting yourself a slice of cake! That being said, it
demonstrates the basic concept of control flow nicely.

A note on brackets
Before we go any further, you may have noticed that we often use
different types of brackets for various purposes in R. This is vitally
important to the language, and your code will not function in the way
that you expect it to if you get this wrong.
() - rounded brackets are used exclusively to perform
functions, or denote the order of mathematical calculations
[] - square brackets are used for indexing and subsetting
{} - curly brackets are used to define blocks of code in
functions and statements. What I mean by this will become increasingly
apparent as we work through the below.
For loops
Despite if else statements being perhaps easier to wrap
our heads around, we’re going to start with for loops.
Essentially, a for loop is a way of iterating through a set
of values, performing a function on each in turn. These loops are
relatively straightforward and intuitive in R, once you get used to
using them.
The syntax is, of course, slightly different to Python, but the basic
concept is the same. Typically, for loops in R are a little
slow. There’s a much quicker way of performing these functions, but we
wont go into that here - it’s important to understand how the loops work
first.
Let’s try one. We want to create a basic for loop which
will print all of the numbers from 1 to 10. We could of course do this
without a loop, by assigning an individual value to x, and printing them
in turn:
x <- 1
print(x)
[1] 1
x <- 2
print(x)
[1] 2
x <- 3
print(x)
[1] 3
What if we wanted to automate this? Let’s build that basic
for loop…
for (x in 1:10){
print(x)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
Brilliant, but let’s go through just how that works.
for - we start with the for statement. If
you are using an IDE, you might notice that this statment changes colour
to denote that it is one of R’s protected control statements.
x in 1:10 - we know that 1:10 produces a vector of all
of the numbers in sequence from 1 to 10. the x in bit just
means “for every value in the vector of”. The x could be anything you
want it to be. e.g. for numbers in 1:10 would yeild the
name result. Note here that different programming languages follow
different conventions- in python you’ll often see for loops
written as for i in 1:10.
{} - the curly brackets contain the body of the loop.
What that means is that all of the values we have just specified above
will have the contents of the {} performed on them. Here,
we’ve used the print() function, which just prints our
values to the console.
So, this loop assigns x a value of 1 - 10 in a sequence, and prints
it to the console.
This is an example of a super simple and straightforward control
statement. We could replace the 1:10 with anything we liked, and the
loop would cycle through the values presented it in turn until it
reached the final one.
Now, printing the numbers 1 to 10 doesn’t seem overly useful. What if
we want to perform a mathematical operation on all of the numbers in a
sequence quickly? Let’s expand our for loop so that it adds
10 to every number in the sequence, and prints the result to the
console:
for (x in 1:10){
print(x + 10)
}
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20
Easy as that. Again, this is a really basic example of a
for loop, just so you can get to grips with the principle
of how they work in R.
We can also create for loops with vectors consisting of
character strings - let’s create one with 4 components:
years <- c("2019", "2020", "2021", "2022")
Remember what when we create character string vectors, we have to
include the c() function
Let’s pop these in a loop that will print the sentence “The year is”
followed by each of the levels of the vector in turn
years <- c("2019", "2020", "2021", "2022")
for (x in years){
y <- paste("The year is", x)
print(y)
}
[1] "The year is 2019"
[1] "The year is 2020"
[1] "The year is 2021"
[1] "The year is 2022"
This loops through the four years we have given in the vector, and
uses the paste() function to stick two character strings
together, printing each of the vector elements in turn. Notice that
we’ve created a new object within the loop, y - if you look
in your R environment window, or try and print y to the console with
print(y), you’ll see that y is stored as “The year is
2022”, which is the final iteration of the loop. It’s important to note
that the other iterations are not stored in the wider R environment, as
the loop overwrites itself every time it performs an iteration.
Just to recap,a for loop runs through values in a vector
(and is quick in these small toy examples!), and does some work for you
inside the statement. Curly brackets {} denote the body of
the loop, which is where we tell R what we want it to do with our input.
Whilst for loops are great, every example that we’ve just run through
can actually be acheived with simpler, and more computationally
efficient code (sorry). Remember to think about your code, and consider
whether there might be easier solutions to a problem!
Vectorisation as a more efficient mechanism?
For our first example, printing 1 - 10 to the screen with a loop, we
could save a lot of time by explicitly popping x into it’s own vector
(rather than adding this to the conditions of a for loop),
and dealing with it that way:
x <- 1:10
print(x)
[1] 1 2 3 4 5 6 7 8 9 10
As you can see, this ultimately yields the same result, with
considerably less faffing. In these small toy examples, there isn’t a
whole lot of difference in computation time, but in much larger
datasets, this is certainly something worth considering. Generally,
vectorisation is much speedier than for loops.
For the example where we added 10 to x, we can use the same
vectorisation principle. This is where R differs in it’s fundemental dev
makeup to, for example, bash, where you would have to
do a for loop to perform the following:
x <- 1:10 # recreate our 1:10 vector
print(x + 10)
[1] 11 12 13 14 15 16 17 18 19 20
Here, you don’t even need the print() function, just
typing x + 10 would be sufficient!
You don’t even really need to use loops on character vectors in R!
Let’s go back to our “the year is” example. We can avoid a loop by using
the paste() function on the vector explicitly, rather than
having to force it through a loop:
years <- c("2019", "2020", "2021", "2022")
paste("The year is", years)
[1] "The year is 2019" "The year is 2020" "The year is 2021" "The year is 2022"
So why bother with for loops in the first place?
All of this is not to say that for loops are rubbish and
useless in R - in fact there will likely be times where they are
unavoidable, and a vector based solution just won’t cut it. It is
however worth hammering home the point that they are really worth
thinking about quite carefully. There will often be a better way to do
whatever you’re trying to do - slow down when you’re coding. Stop and
think about what it is you’re trying to achieve. Beginners in particular
tend to learn how to create for loops, and then use them
for everything, when often, a vector based solution would be much
quicker and simpler!
If statements
Now, on to if statements. These are another control flow
coding mechanism you can use in R and further afield to customise the
order that commands are run in, depending on conditions of your data.
Think about the kettle example - IF your water boiled,
then you perform the task. if statements ask whether a
condition has been met, before they perform a function. The best way to
explain this is, as always, with an example:
z <- 1
if (z < 10){
print("z is less than 10")
}
We can see that because we’ve given z the value of 1,
which is less than 10, we get an output telling us so (R is performing
the function!). What happens if we change the assignment of
z and try again?
z <- 45
if (z < 10){
print("z is less than 10")
}
We don’t get an output. Because the condition was not met, no
function was performed on our data.
The way that this is coded in R is that the provided condition (in
()) is run, to give a logical output. If that output is
TRUE, the body of the function (in {}) is run.
If the output is FALSE, nothing will happen.
else statements
It isn’t a huge leap to ask whether we could take the above and
perform a different function if the condition was not met, and the
logical output was FALSE. We can achieve this by pairing
our if statement with an else statement. The
syntax of this can take a little getting used to, because it pairs two
sets of {} separated by an else statement.
Let’s demonstrate:
z <- 1
if (z < 10){
print("z is less than 10")
} else {
print("z is more than 10")
}
[1] "z is less than 10"
With an input of 1, we get a printed message telling us that z is
less than 10. What if we change z to be greater than 10?
z <- 20
if (z < 10){
print("z is less than 10")
} else {
print("z is more than 10")
}
[1] "z is more than 10"
As expected, R tells us that z is more than 10. This combination of
if and else statements runs a control flow
that takes an input, and if a condition is met, runs function a. If the
condition is not met, it runs function b. This basic principle allows
you to perform slightly more complex functions or analyses, based on the
input that you give.
The ifelse() function
There is an alternative to if and else
control flow functions in R - the ifelse() function. This
doesn’t always perform in quite the way that you might expect, but it’s
certainly an option to consider. The syntax is perhaps a little more
familiar than the control flow statements… Let’s perform the same thing
we just did, but this time using an ifelse() function:
z <- 1
ifelse(z < 10, "less than 10", "more than 10")
[1] "less than 10"
z <- 20
ifelse(z < 10, "less than 10", "more than 10")
[1] "more than 10"
Great. All works the same so far! The ifelse() function
takes an input, evaluates it against a condition (here that it is <
10). If the condition is TRUE, it performs the first
option, if FALSE, does the 2nd.
Helpfully, we can also perform the ifelse() functions on
a vector. Let’s create a numeric vector from 1 - 60 in steps of 6 and
run our function again
z <- seq(from = 1, to = 60, by = 6)
ifelse(z < 10, "less than 10", "more than 10")
[1] "less than 10" "less than 10" "more than 10" "more than 10" "more than 10" "more than 10" "more than 10"
[8] "more than 10" "more than 10" "more than 10"
We end up with 10 outputs, each telling us whether a result is less
or more than 10!
z <- seq(from = 1, to = 60, by = 6)
if (z < 10){
print("z is less than 10")
} else {
print("z is more than 10")
}
Error in if (z < 10) { : the condition has length > 1
You can see from the error above, that you can’t perform
if else statements on a vector - the condition
is only expecting something with a length of 1, rather than, in this
case, 10.
We can use ifelse() on character vectors too. Let’s
create one and try it out:
countries <- c("UK", "USA", "France", "Spain")
ifelse(countries == "UK", "UK", "Elsewhere")
[1] "UK" "Elsewhere" "Elsewhere" "Elsewhere"
The function is evaluating to see if the input matches the string
“UK”, and if it does, will print “UK”, otherwise, prints “Elsewhere”.
Fairly straightforward stuff!
Writing your own functions:
Writing your own functions is an important part of programming. It
keeps code simple and readable, and allows you to perform a set of tasks
multiple times without loads of duplication in your code. If you wanted
to develop your own package, custom function creation would be a huge
part of this - a package is essentially just a collection of
functions!
The process of creating functions is quite straightforward - I do it
loads to make my life quick and easy. Let’s start by creating a simple
function that adds 10 to any numeric input:
add_ten <- function(x){
y <- x + 10
return(y)
}
add_ten(1)
[1] 11
So, here, we’ve created and tested a basic function. Let’s dissect it
a little:
add_ten - first, we have to give our new function a
name. I’ve imaginatively called this one add_ten.
- Then, we assign the rest of the code to the new function name with
our assignment arrow
<-
- Next up, we have the
function function. This tells R
that we want to turn our function name into a new function
function(x) - this tells R that we are creating a
function with a single argument (or input), x.
{} this denotes the body of the function - whatever
code is in here is what will be applied to an input
y <- x + 10 - this bits obvious - add 10 to our
input of x and assign it a new name, y.
return(y) - give us an output! Without this, R wouldn’t
automatically tell us what the output of whatever we’ve just asked it to
do is!
Notice here that the new y object is treated a little
differently in functions than loops. If we remove y from
our environment and run the function again, you’ll notice that it does
not re-appear. Whatever objects you create within the body of the
function exist only within that function - they are not callable to the
wider R environment.
Functions can also take a vector input - let’s run our
add_ten() function with a vector and see what happens
add_ten <- function(x){
y <- x + 10
return(y)
}
z <- 1:10
add_ten(z)
[1] 11 12 13 14 15 16 17 18 19 20
Of course, we could perform this function manually, as it is a really
straightforward example. I’d be unlikely to bother creating a function
to do this in practice, but it’s a useful demonstration.
The anatomy of a function
Let’s quickly recap the anatomy of how a function works
function(x) declares a function. It creates the function
within the R environment, and defines the arguments that the function
requires. In our example above, whenever you run add_ten,
you must have an x argument, otherwise the function will not
run.
{} define the block of code within which the work that
the function does takes place. Here, y is only defined
within the function.
return(y) tells R to give us an output, and display what
the function has done.
Functions with multiple arguments
We can extend our functions to take multiple arguments, or inputs,
using the basics that we’ve just learned. Functions that we have used
throughout the course so far have taken multiple arguments, so let’s try
and also create one. We’ll write a function that multiplies two numbers
together:
multiply <- function(x, y){
z <- x * y
return(z)
}
multiply(3,2)
[1] 6
In our R environment window, we can see a new section has been
created called ‘Functions’. Within that, we can see both our
add_ten and our multiply functions, and the
number of arguments that each takes.
Functions with default arguments
You’ll find often that several arguments in functions that you’re
running in R have default settngs that you do not have to explicitly
code in order for R to perform them. For example, in the
sum() and mean() functions, the default for
the na.rm argument is FALSE. We can edit our
multiply() function to have a default y value
of 10:
multiply <- function(x, y = 10){
z <- x * y
return(z)
}
multiply(3)
[1] 30
multiply(3, 2)
[1] 6
Here, we can see that if we include only 1 argument to the function
now, it will run and use the default of y = 10. If we include two
arguments ourselves, we override the default and the function performs
on both of the arguments that we have specified. You can hopefully see
how writing functions with multiple arguments and defaults isn’t too
much of a stretch from writing a function with a single argument, and
see how useful that might be in your coding!
Combining functions and conditionals:
Now, we can combine all of the skills that we’ve learned today and
create complex functions with some control flow statements inside of
them. Let’s start by wtiting a function that evaluates whether a
numerical input is greater than or less than 10.
eval10 <- function(x){
y <- ifelse(x < 10, "less than 10", "greater than 10")
return(y)
}
eval10(1)
[1] "less than 10"
eval10(15)
[1] "greater than 10"
We’ve included a simple ifelse function within our eval10 function,
which takes a new object, y, and performs an ifelse() function upon it,
and returns the output. We could do the same with the explicit
if and else control flow statements
eval10_2 <- function(x){
y <- if (x < 10){
print("less than 10")
} else {
print("greater than 10")
}
}
eval10_2(1)
[1] "less than 10"
eval10_2(15)
[1] "greater than 10"
Whilst this is a simple example, we could build up to creating some
incredibly complex functions with custom control flows to efficiently
handle our data and downstream analysis in R. It may well be useful for
things such as looking at data to see if it contains headers before
removing them, or assessing the length of a data set before performing a
function on it.
Lists in R
Now, we’ve had a whistle stop tour of functions, obviously this is
not the full extent of their functionality, but it’s time to move on to
lists. We’ve not really mentioned lists so far, other than very briefly
in some of the beginner sessions. To recap, there are 4 main data
structures in R - vectors, matricies, data.frames, and lists.
A list is a special form of data structure which allows you to
contain objects of different lengths within it. They are a little more
complicated than the other data structures we covered before - partly
because a data.frame is both a special type of list, and can be
contained within a list! In a data.frame, each component part (or
column) must be the same length - this is not true of a list.
They are quite complicated on first glance, and often are not taught
at all in R courses - I was never formally taught what a list was or how
on earth to use one, and I had to try and work it out for myself. Lists
are probably the form od data structure that I use the least in R,
simply because I never got into the habit of using them. Now, let’s make
a list and see how they work, and figure out how to access stuff within
them. First, we’ll create three vectors (one character, one numeric, and
one logical), and combine them with the list()
function.
nintendo <- c("Mario", "Luigi", "Peach")
numbers <- 1:100
logic <- c(TRUE, FALSE, FALSE, TRUE)
my_list <- list(nintendo, numbers, logic)
Now, we have our list. We can print it to the screen by typing the
name of our list, and it’ll print everything out.
my_list
[[1]]
[1] "Mario" "Luigi" "Peach"
[[2]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
[27] 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
[53] 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
[79] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
[[3]]
[1] TRUE FALSE FALSE TRUE
From this, we can clearly see that the objects contained within the
list are of different lengths - nintendo has a length of 3, numbers has
a length of 100, and logic has a length of 4.
So, how do we access the list? It can seem complicated, but actually
printing it to the screen has given us lots of information. We can use
square brackets [] to choose objects. We can also access
elements with their names, provided we have given them names, but we
will come back to that.
Let’s try and select the first vector element of our list. We might
try and access it with:
my_list[1]
[[1]]
[1] "Mario" "Luigi" "Peach"
Whilst this does return what we want it to, this actually isn’t in
the vector class that we created the list with. We can check with the
class() function:
class(my_list[1])
[1] "list"
We can see here that the object has retained it’s list class, and has
taken the first part of the list, but not the vector itself. We can
access the vector within the list with double square brackets
[[]], the clue is in the display of the list!
my_list[[1]]
[1] "Mario" "Luigi" "Peach"
class(my_list[[1]])
[1] "character"
When we verify what we’re doing with class(), we can see
that we’re getting the original character vector stored within the list.
This is a bit complex and hand-wavy, but basically remember that
[[]] allows you to access the element from within the list
in its native form, whereas [] gives you the element of the
list, whilst retaining it’s list class.
Be aware that the way we access lists with [] is
different than vectors. For example, if we were to type
my_list[1:2] we get the first two elements of the list, but
my_list[[1:2]] gives you the second element of the first
bit of the list:
my_list[1:2]
[[1]]
[1] "Mario" "Luigi" "Peach"
[[2]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
[27] 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
[53] 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
[79] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
my_list[[1:2]]
[1] "Luigi"
You can access bits of lists as above, or perhaps more intuitively
and less confusingly, by combining double and single square brackets
my_list[[1]][2] # This accesses the 2nd item of the 1st list element.
You can also use names to access list elements in a way that is
equivalent to how a dataframe would work. In order to do this, however,
you must specify the names when you’re creating the list, like this:
my_list <- list(nintendo = nintendo, numbers = numbers, logic = logic)
If we print the list again, you’ll see that the [[1]], [[2]], and
[[3]] have been replaced by $nintendo, $numbers, and $logic:
my_list
$nintendo
[1] "Mario" "Luigi" "Peach"
$numbers
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
[27] 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
[53] 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
[79] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
$logic
[1] TRUE FALSE FALSE TRUE
Now you can access your list using the names, but note that just like
a dataframe, my_list[[1]] will still work
my_list$nintendo
[1] "Mario" "Luigi" "Peach"
my_list[[1]]
[1] "Mario" "Luigi" "Peach"
Why are lists important?
It perhaps isn’t immediately obvious why lists are important, but we
will talk more about this in the next session. It’s useful for you to
know how to use them, as they will make R more useful to you.
Briefly, lists can be helpful if you are working on lots of
dataframes/tibbles at the same time, as you can store them within a
list. The versatility of this will become clearer next time when we’re
talking about the apply family of functions, sapply(),
lapply(), and apply().
Summary
So, today we have learned about control flow with for,
if, else, and ifelse(), and how
these are used to control the flow of data through a set of functions,
depending on whether conditions are met.
We’ve learned how to write our own functions, including with multiple
arguments and defaults, and have combined this with our new knowledge of
control flow.
Finally, we touched on lists which feeds nicely into the apply set of
functions that we’ll look at in more detail on Thursday. We can use
sapply(), lapply() and apply() to
efficiently process vectors in R, and we’ll learn more about the
principles of proper scripting.
LS0tCnRpdGxlOiAiTElGRTQxMzggLSBBZHZhbmNlZCBSIHdvcmtzaG9wIDEiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCkhlbGxvISBXZWxjb21lIHRvIHRoZSBmaXJzdCBvZiB0aGUgYWR2YW5jZWQgUiB3b3Jrc2hvcHMgb24gdGhlIExJRkU0MTM4IG1vZHVsZS4gT3VyIGxlYXJuaW5nIG9iamVjdGl2ZXMgZm9yIHRoaXMgc2Vzc2lvbiBhcmU6CgoqIExlYXJuIHNvbWUgYWR2YW5jZWQgcHJvZ3JhbW1pbmcgc2tpbGxzIGluIFIsIGFuZCB1bmRlcnN0YW5kIHRoYXQgdGhlIGxhbmd1YWdlIGNhbiBiZSB1c2VkIGFzIGEgInN0cmljdCIgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2Ugc2ltaWxhciB0byBQeXRob24gZXRjLgoqIFRoaW5rIGFib3V0IGNvbnRyb2wgZmxvdyAtIHdlJ2xsIGludHJvZHVjZSB0aGUgY29uY2VwdHMgb2YgY29udHJvbCBmbG93LCBpbmNsdWRpbmcgYGZvcmAgbG9vcHMsIGBpZmAgYW5kIGBlbHNlYCBzdGF0ZW1lbnRzLCBhbmQgdGhlIGBpZmVsc2UoKWAgZnVuY3Rpb24uCiogV2Ugd2lsbCBsZWFybiB0byB3cml0ZSBvdXIgb3duIGZ1bmN0aW9ucywgYSB2aXRhbCB0b29sIHdoZW4gd2UgYXJlIGJ1aWxkaW5nIHNjcmlwdHMuIFdlIHdpbGwgZGlzY3VzcyB0aGUgdXNhYmlsaXR5IG9mIGN1c3RvbSBmdW5jdGlvbnMgdG8gYXZvaWQgcmVwbGljYXRpb24gaW4geW91ciBjb2RlLgoqIEZpbmFsbHksIHdlIHdpbGwgYmVnaW4gdG8gaGF2ZSBhIGxvb2sgYXQgb3VyIDR0aCBkYXRhIHN0cnVjdHVyZSBpbiBSIC0gbGlzdHMuCgojIFdoYXQgZG8gd2UgbWVhbiBieSAiYWR2YW5jZWQiPwoKU28sIHRoZSBwcmV2aW91cyBzZXNzaW9ucyBoYXZlIGFsbCBiZWVuIGRlc2lnbmVkIHRvIGdpdmUgeW91IGFuIG92ZXJhbGwgZ3JvdW5kaW5nIG9mIHRoZSB3YXkgdGhhdCBSIHdvcmtzLCBhbmQgdG8gdHJ5IGFuZCB1bmRlcnN0YW5kIHRoZSBkaWZmZXJlbnQgYXBwcm9hY2hlcyB0aGF0IFIgdXNlcnMgdGFrZSB0byB0aGUgbGFuZ3VhZ2UgKGJhc2VSIHZlcnN1cyB0aGUgdGlkeXZlcnNlIGFwcHJvYWNoIGZvciBlLmcuKS4gRm9yIG1vc3QgUiB1c2VycywgdGhpcyBpcyBlbm91Z2ggdG8gZ2V0IGJ5LiBZb3UnbGwgYmUgYWJsZSB0byBkbyB0aGUgbWFqb3JpdHkgb2YgdGhlIHN0dWZmIHRoYXQgeW91IG5lZWQgdG8gdXNpbmcgb25seSB0aGUgc2tpbGxzIHRoYXQgd2UndmUgYmVlbiB0aHJvdWdoIHNvIGZhci4KClRoYXQgYmVpbmcgc2FpZCwgdGhlcmUgYXJlIHRpbWVzLCBwYXJ0aWN1bGFybHkgd2hlbiB1bmRlcnRha2luZyBiaW9pbmZvcm1hdGljIGFuYWx5c2lzLCB3aGVuIHBlcmhhcHMgeW91IG1pZ2h0IGxpa2UgdG8gaGF2ZSBhIHNjcmlwdCB0aGF0IHdpbGwgcnVuIGluZGVwZW5kZW50bHkgd2l0aG91dCB5b3VyIGlucHV0LiBTaXR1YXRpb25zIHN1Y2ggYXMgdGhpcyByZWFsbHkgaGlnaGxpZ2h0IHRoZSBpbXBvcnRhbmNlIG9mIHRoZSBhZHZhbmNlZCB0ZWNobmlxdWVzIHRoYXQgd2UncmUgYWJvdXQgdG8gbGVhcm4hCgojIFRha2luZyBpdCB0byB0aGUgbmV4dCBzdGVwCgpUaGUgYmVsb3cgd2lsbCBiZWdpbiB0byBnaXZlIHlvdSBhIGdyZWF0ZXIgZmxleGliaWx0eSBhbmQgdmVyc2F0aWxpdHkgd2l0aCB5b3VyIFIgY29kaW5nLCBhbmQgYWxsb3cgeW91IHRvIGJlZ2luIHRvIG1ha2UgUiB3b3JrIGZvciB5b3UgaW4gZXhhY3RseSB0aGUgd2F5IHRoYXQgeW91IHdhbnQgaXQgdG8uIGBmb3JgIGxvb3BzIGZvciBleGFtcGxlIGFyZSBhIGdyZWF0IHByaW5jaXBsZSB0byBsZWFybiBpbiBnZW5lcmFsIHdpdGggeW91ciBjb2RlLCBhbmQgbGVhcm5pbmcgYm90aCB0aGUgbG9vcHMgdGhlbXNlbHZlcyBhcyB3ZWxsIGFzIHRoZSBhbHRlcm5hdGl2ZXMgYXZhaWxhYmxlIGluIFIgd2lsbCBiZSBpbmNyZWRpYmx5IHVzZWZ1bCB0byB5b3UuIAoKQW5vdGhlciBuaWNlIHRoaW5nIGFib3V0IG1vdmluZyBvbiB0byBtb3JlIGFkdmFuY2VkIGNvZGluZyBwcmluY2lwbGVzIGluIFIgaXMgdGhhdCB0aGV5IHdpbGwgaGVscCB0byBkZWVwZW4geW91ciB1bmRlcnN0YW5kaW5nIG9mIGhvdyB0aGUgYmFzaWNzIHdvcmsuICBGb3IgZXhhbXBsZSwgdGhlIHdheSB0aGF0IHdlIGhhbmRsZSBhbmQgYWNjZXNzIHZlY3RvcnMgd2lsbCBiZWNvbWUgY2xlYXJlciBhcyB3ZSB1c2UgbW9yZSBhZHZhbmNlZCB0ZWNobmlxdWVzIHRvIHdvcmsgdGhyb3VnaCB0aGVtLgoKIyBCdXQgaG93IGRvIEkgYmVjb21lIGFuICJhZHZhbmNlZCIgUiB1c2VyPyEKCiogSnVzdCBmb2xsb3dpbmcgdHV0b3JpYWxzIHN1Y2ggYXMgdGhpcyB3aWxsIG5vdCBtYWtlIHlvdSBpbnRvIGFuIGFkdmFuY2VkIFIgdXNlci4gVGhlc2UgdHV0b3JpYWxzIGNhbiBvbmx5IGdvIHNvIGZhciAtIEkgY2FuIGludHJvZHVjZSB5b3UgdG8gYSBjb25jZXB0LCBidXQgcmVhbGx5IHdoYXQgd2lsbCBkZWVwZW4gYW5kIHN0cmVuZ3RoZW4geW91ciB1bmRlcnN0YW5kaW5nIGlzIGJ5IHVzaW5nIHRoZSB0ZWNobmlxdWVzIHdpdGggcmVhbC13b3JsZCBkYXRhLCBiZXlvbmQgdGhlIHN0cnVjdHVyZWQgZm9ybWF0IG9mIHRoaXMgdHV0b3JpYWwuCgoqIFRoZSBiZXN0IHdheSB0byBsZWFybiBSIChvciBhbnkgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UpLCBpcyBieSBkb2luZywgcGxheWluZywgYW5kIGV4cGVyaW1lbnRpbmcuCgoqIENyaXRpY2FsbHksIHlvdSBhbHNvIG5lZWQgdG8gbGVhcm4gaG93IGFuZCB3aGVyZSB0byBhY2Nlc3MgaGVscC4gRG9uJ3QgYmUgYWZyYWlkIHRvIHVzZSBnb29nbGUsIHN0YWNrIG92ZXJmbG93LCBvciB0byBhc2sgeW91ciBmcmllbmRzIG9yIGNvbGxlYWd1ZXMgZm9yIGFkdmljZS4gQSBmcmVzaCBwYWlyIG9mIGV5ZXMgaXMgbXVjaCBtb3JlIGxpa2VseSB0byBzcG90IGEgcm9ndWUgY29tbWEgdGhhbiB5b3UgYXJlIGFmdGVyIHlvdSd2ZSBiZWVuIHN0YXJpbmcgYXQgeW91ciBzY3JlZW4gZm9yIGhvdXJzLiBUaGlzIG1pZ2h0IHNlZW0gYSBsaXR0bGUgYmFzaWMgZm9yIGFuIGFkdmFuY2VkIFIgdHV0b3JpYWwsIGJ1dCBsb29raW5nIGZvciBhbnN3ZXJzIG9ubGluZSBpcyBhIGdyZWF0IHdheSB0byBzZWUgb3RoZXIgZXhhbXBsZXMsIGxvb2sgYXQgb3RoZXIgcGVvcGxlcyBjb2Rpbmcgc3R5bGVzLCBnZXQgaGVscCwgYW5kIGltcG9ydGFudGx5LCBsZWFybiB0byBhdm9pZCBmdXR1cmUgbWlzdGFrZXMuIFRoZXJlIGFyZSBsb2FkcyBvZiB3b25kZXJmdWwgUiByZXNvdXJjZXMgb3V0IHRoZXJlIGZvciB5b3UgdG8gdXNlLCBhbmQgdGhleSBhcmUgZ2V0dGluZyBpbmNyZWFzaW5nbHkgYmV0dGVyIHdpdGggdGltZS4KCiogQW5vdGhlciB0aGluZyB5b3Ugc2hvdWxkIGRldmVsb3AgYXMgeW91IGJlY29tZSBhIG1vcmUgYWR2YW5jZWQgUiB1c2VyLCBpcyB5b3VyIG93biBjb2RpbmcgcGhpbG9zb3BoeS4gTXkgYXBwcm9hY2ggaXMgdG8gZG8gd2hhdCB3b3Jrcy4gVGhpcyBzb3VuZHMgZGFmdCBhdCBmaXJzdCwgYnV0IHRoZXJlIGFyZSBzZXZlcmFsIHBlb3BsZSB3aG9zIHBoaWxvc29waHkgaXQgaXMgdG8gYWNoaWV2ZSBhbmQgZW5kIHJlc3VsdCB1c2luZyBhcyBmZXcgbGluZXMgb2YgY29kZSBhcyBwb3NzaWJsZS4gSSBsaWtlIHRvIGRvIHdoYXQgd29ya3MgZm9yIG1lLCB3aGlsc3QgcmV0YWluaW5nIGFuIG9wZW4gbWluZCB0byBuZXcgc29sdXRpb25zLiBJdCBpcyB2ZXJ5IGVhc3kgdG8gZ2V0IHN0dWNrIGluIGEgY29kaW5nIHJ1dCB3aXRoIFIsIGFuZCBjb250aW51ZSB0byB1c2UgYSBzb2x1dGlvbiB0aGF0IG1pZ2h0IHF1aWNrbHkgYmVjb21lIG91dCBvZiBkYXRlIG9yIGltcHJhY3RpY2FsL3VuZWNjZXNhcmlseSBkaWZmaWN1bHQgKHRoaW5rIGFib3V0IHRoZSBpbnRyb2R1Y3Rpb24gb2YgdGhlIHRpZHl2ZXJzZSBpbiB0aGUgMjAxMHMgZm9yIGV4YW1wbGUhKS4gCgpUaGUgYWJvdmUgYWJpbGl0aWVzIGFuZCBpZGVhcyB3aWxsIG9wZW4gdXAgeW91ciBjb2RpbmcgYWJpbGl0aWVzLCBhbmQgYWxsb3cgeW91IHRvIHJlYWxseSBnZXQgdG8gZ3JpcHMgd2l0aCBSIGFzIGJvdGggYSBsYW5ndWFnZSBhbmQgYSB0b29sIGZvciBkYXRhIHdyYW5nbGluZywgcGxvdHRpbmcsIGFuZCBkb3duc3RyZWFtIGFuYWx5c2lzLiAKCkZpbmFsbHksIHRoZSBpbXBvcnRhbmNlIG9mIHlvdXIgY29kaW5nIGVudmlyb25tZW50IChJIG1lYW4gcGh5c2ljYWwgZW52aXJvbm1lbnQsIG5vdCB5b3VyIFIgZW52aXJvbm1lbnQpIGNhbm5vdCBiZSB1bmRlcnN0YXRlZC4gRmluZCBhIHdheSB0byBnZXQgImluIHRoZSB6b25lIiwgYW5kIGFsbG93IHlvdXJzZWxmIHRvIGNvbmNlbnRyYXRlIHNvbGVseSBvbiB3aGF0IGl0IGlzIHRoYXQgeW91J3JlIHRyeWluZyB0byBhY2hpZXZlLiBGb2N1cyBpcyBpbXBvcnRhbnQgd2l0aCBjb2RlLCBpdCdzIHNvIGVhc3kgdG8gbWFrZSBtaXN0YWtlcyBhbmQgZW5kIHVwIHdpdGggYW5hbHlzZXMgdGhhdCBoYXNuJ3QgZG9uZSB3aGF0IHlvdSB0aGluayBpdCBoYXMuIEZvciBtZSwgSSBtYWtlIGEgZ2lhbnQgY3VwIG9mIHRlYSwgZ3JhYiBzb21lIGJpc2N1aXRzLCBnZXQgY29tZnkgd2l0aCBhIHdhcm0ganVtcGVyLCBhbmQgcG9wIG15IGhlYWRwaG9uZXMgb24uIEkgbGlzdGVuIHRvIGEgcGxheWxpc3QgdGhhdCBJIGhhdmUgcGVyc29uYWxseSBjdXJhdGVkIGZvciBhIG1peHR1cmUgb2YgY29uY2VudHJhdGlvbiwgcG9zaXRpdml0eSwgYW5kIG1vdGl2YXRpb24uIEl0IHNvdW5kcyBkYWZ0LCBidXQgSSBwcm9taXNlLCBpdCB3b3Jrcy4gSWYgSSByZWFsbHkgZG9uJ3Qgd2FudCB0byBiZSBkaXN0dXJiZWQsIEkgc2h1dCBteSBvZmZpY2UgZG9vciwgY292ZXIgdGhlIHdpbmRvdyBpbiB0aGUgZG9vciwgYW5kIHR1cm4gdGhlIGxpZ2h0cyBvZmYgKGFuZCBwdXQgbXkgbGFtcCBvbiAtIEknbSBhaW1pbmcgZm9yIGFtYmllbnQgbGlnaHRpbmcgcmF0aGVyIHRoYW4gcGl0Y2ggYmxhY2shKS4KCkkga25vdyBJIGp1c3Qgc2FpZCBmaW5hbGx5LCBidXQgYWN0dWFsbHkgcHJvcGVybHkgZmluYWxseSwgZG9uJ3QgZm9yZ2V0IHRvIHRha2UgYSBicmVhay4gSWYgeW91J3JlIHRlYXJpbmcgeW91ciBoYWlyIG91dCB0byBkZWJ1ZyBhIHBpZWNlIG9mIGNvZGUsIG9yIGlmIHlvdSdyZSByZWFsbHkgc3R1Y2sgYW5kIGp1c3QgY2FuJ3QgbWFrZSBzb21ldGhpbmcgd29yaywgcHV0IGl0IGRvd24uIFdhbGsgYXdheSwgbWFrZSB5b3Vyc2VsZiBhIGN1cCBvZiB0ZWEsIGhhdmUgc29tZSBjYWtlLCBnbyBmb3IgYSBydW4sIGRvIHdoYXRldmVyIHlvdSBuZWVkIHRvIGZvciBzb21lIG1lbnRhbCBzcGFjZS4gRXZlbiBzbGVlcCBvbiBpdCBpZiB5b3UgaGF2ZSB0by4gV2hlbiB5b3UgY29tZSBiYWNrIHRvIGl0LCBvZnRlbiB0aGUgYW5zd2VyIHdpbGwgcHJlc2VudCBpdHNlbGYuIElmIGl0IGRvZXNuJ3QgZXZlcnl0aGluZyB3aWxsIGF0IGxlYXN0IGZlZWwgYSBsaXR0bGUgZWFzaWVyIHRoYW4gaXQgZGlkIGJlZm9yZS4gQ29kaW5nIGNhbiBiZSBmcnVzdHJhdGluZywgYnV0IGxlYXJuaW5nIHRvIG1hbmFnZSBhbmQgaGFybmVzcyB0aGF0IGZydXN0cmF0aW9uIGlzIGEgcmVhbCBza2lsbCEKClJpZ2h0LiBMZXQncyBnZXQgdG8gdGhlIG1lYXQgb2YgaXQuCgojIENvbnRyb2wgZmxvdwoKVGhlIGZpcnN0IGNvbmNlcHQgdGhhdCB3ZSdsbCBjb3ZlciB0b2RheSBpcyBjb250cm9sIGZsb3cuIFlvdSBtYXkgd2VsbCBoYXZlIGNvbWUgYWNyb3NzIGNvbnRyb2wgZmxvdyBpbiB5b3VyIGZvcnJheXMgd2l0aCBQeXRob24gYW5kIFVuaXgsIGFuZCB0aGUgYmFzaWMgaWRlYSBvZiBob3cgaXQgd29ya3MgaXMgbGFyZ2VseSBzaW1pbGFyIGluIFIuIENvbnRyb2wgZmxvdyBpcyBhIGZ1bmRlbWVudGFsIHBhcnQgb2YgdGhlIHdheSB0aGF0IGFueSBwcm9ncmFtbWluZyBsYW5ndWFnZSB3b3Jrcywgbm90IGp1c3QgUi4gSXQgZXNzZW50aWFsbHkgcHJvdmlkZXMgYSB3YXkgdG8gY29udHJvbCB0aGUgb3JkZXIgdGhhdCBhIHNldCBvZiBmdW5jdGlvbnMgYXJlIHBlcmZvcm1lZCBvbiB5b3VyIGRhdGFzZXQuCgpUaGVyZSBhcmUgc2V2ZXJhbCBleGFtcGxlcyBvZiBjb250cm9sIGZsb3cgZnVuY3Rpb25zLCBidXQgdGhlIG9uZXMgd2Ugd2lsbCBjb25jZW50cmF0ZSBvbiB0b2RheSBhcmUgYGZvcmAgbG9vcHMsIGBpZmAgYW5kIGBlbHNlYCBzdGF0ZW1lbnRzLCBhbmQgdGhlIGBpZmVsc2UoKWAgZnVuY3Rpb24uIGBpZmVsc2UoKWAgaXNuJ3Qgc3RyaWN0bHkgYSBjb250cm9sIGZsb3cgc3RhdGVtZW50LCBidXQgYSBmdW5jdGlvbiBmcm9tIHRoZSBiYXNlUiBzZXQgb2YgZnVuY3Rpb25zLgoKQmVmb3JlIHdlIGdldCBzdGFydGVkLCB0aGUgd2F5IHRoYXQgY29udHJvbCBmbG93cyB3b3JrIGFyZSBhcyBmb2xsb3dzLiBTYXksIGZvciBleGFtcGxlLCB5b3UgaGF2ZSBhIGNvbmRpdGlvbi4gWW91IGFzayB3aGV0aGVyIHRoYXQgY29uZGl0aW9uIGlzIHRydWUgb3IgZmFsc2UuIElmIHRoZSBjb25kaXRpb24gaXMgdHJ1ZSwgeW91IHBlcmZvcm0gYSBmdW5jdGlvbi4gCgohW10oY29udHJvbF9mbG93LnBuZykKCklmIGl0IGlzIGZhbHNlLCB5b3UgcGVyZm9ybSBhbm90aGVyIGZ1bmN0aW9uLiBUaGlzIGlzIGVhc2llciB0byB1bmRlcnN0YW5kIHdpdGggYW4gYW5hbG9neS4gV2UgY2FuIHVzZSBgaWZgIGBlbHNlYCBzdGF0ZW1lbnRzIHRvIHdyaXRlIGEgZnVuY3Rpb24gdG8gbWFrZSBvdXJzZWx2ZXMgYSBjdXAgb2YgdGVhLiBGaXJzdCwgd2UgcGVyZm9ybSB0aGUgYm9pbCBrZXR0bGUgZnVuY3Rpb24uIFRoZW4sIHdlIHBlcmlvZGljYWxseSBjaGVjayB0byBzZWUgaWYgdGhlIHdhdGVyIGhhcyBib2lsZWQuIElmIHRoZSBvdXRjb21lIG9mICJIYXMgdGhlIHdhdGVyIGJvaWxlZCIgaXMgYEZBTFNFYCwgd2UgcGVyZm9ybSB0aGUgd2FpdCBhIGJpdCBsb25nZXIgZnVuY3Rpb24uIFdlIGNoZWNrIGFnYWluLiBJZiB0aGUgb3V0Y29tZSBpcyBgVFJVRWAsIHdlIHBlcmZvcm0gdGhlIHBvdXIgd2F0ZXIgZnVuY3Rpb24sIHdoaWNoIHRoZW4gYWxsb3dzIHVzIHRvIHBlcmZvcm0gdGhlIGRyaW5rIHRlYSBmdW5jdGlvbi4gQWRtaXR0ZWRseSwgdGhpcyBhbmFsb2d5IGlzIGZsYXdlZCAtIGl0J3MgbWlzc2luZyBzb21lIHZpdGFsIHN0ZXBzIGluY2x1ZGluZyBhZGRpbmcgYSB0ZWEgYmFnLCBhZGRpbmcgYW55IG1pbGssIHdhaXRpbmcgZm9yIHRoZSB0ZWEgdG8gY29vbCwgYW5kIGN1dHRpbmcgeW91cnNlbGYgYSBzbGljZSBvZiBjYWtlISBUaGF0IGJlaW5nIHNhaWQsIGl0IGRlbW9uc3RyYXRlcyB0aGUgYmFzaWMgY29uY2VwdCBvZiBjb250cm9sIGZsb3cgbmljZWx5LgoKIVtdKGNvbnRyb2xfZmxvdzIucG5nKQoKIyMgQSBub3RlIG9uIGJyYWNrZXRzCgpCZWZvcmUgd2UgZ28gYW55IGZ1cnRoZXIsIHlvdSBtYXkgaGF2ZSBub3RpY2VkIHRoYXQgd2Ugb2Z0ZW4gdXNlIGRpZmZlcmVudCB0eXBlcyBvZiBicmFja2V0cyBmb3IgdmFyaW91cyBwdXJwb3NlcyBpbiBSLiBUaGlzIGlzIHZpdGFsbHkgaW1wb3J0YW50IHRvIHRoZSBsYW5ndWFnZSwgYW5kIHlvdXIgY29kZSB3aWxsIG5vdCBmdW5jdGlvbiBpbiB0aGUgd2F5IHRoYXQgeW91IGV4cGVjdCBpdCB0byBpZiB5b3UgZ2V0IHRoaXMgd3JvbmcuCgpgKClgIC0gcm91bmRlZCBicmFja2V0cyBhcmUgdXNlZCBleGNsdXNpdmVseSB0byBwZXJmb3JtIGZ1bmN0aW9ucywgb3IgZGVub3RlIHRoZSBvcmRlciBvZiBtYXRoZW1hdGljYWwgY2FsY3VsYXRpb25zCmBbXWAgLSBzcXVhcmUgYnJhY2tldHMgYXJlIHVzZWQgZm9yIGluZGV4aW5nIGFuZCBzdWJzZXR0aW5nCmB7fWAgLSBjdXJseSBicmFja2V0cyBhcmUgdXNlZCB0byBkZWZpbmUgYmxvY2tzIG9mIGNvZGUgaW4gZnVuY3Rpb25zIGFuZCBzdGF0ZW1lbnRzLiBXaGF0IEkgbWVhbiBieSB0aGlzIHdpbGwgYmVjb21lIGluY3JlYXNpbmdseSBhcHBhcmVudCBhcyB3ZSB3b3JrIHRocm91Z2ggdGhlIGJlbG93LgoKCiMjIEZvciBsb29wcwoKRGVzcGl0ZSBgaWYgZWxzZWAgc3RhdGVtZW50cyBiZWluZyBwZXJoYXBzIGVhc2llciB0byB3cmFwIG91ciBoZWFkcyBhcm91bmQsIHdlJ3JlIGdvaW5nIHRvIHN0YXJ0IHdpdGggYGZvcmAgbG9vcHMuIEVzc2VudGlhbGx5LCBhIGBmb3JgIGxvb3AgaXMgYSB3YXkgb2YgaXRlcmF0aW5nIHRocm91Z2ggYSBzZXQgb2YgdmFsdWVzLCBwZXJmb3JtaW5nIGEgZnVuY3Rpb24gb24gZWFjaCBpbiB0dXJuLiBUaGVzZSBsb29wcyBhcmUgcmVsYXRpdmVseSBzdHJhaWdodGZvcndhcmQgYW5kIGludHVpdGl2ZSBpbiBSLCBvbmNlIHlvdSBnZXQgdXNlZCB0byB1c2luZyB0aGVtLiAKClRoZSBzeW50YXggaXMsIG9mIGNvdXJzZSwgc2xpZ2h0bHkgZGlmZmVyZW50IHRvIFB5dGhvbiwgYnV0IHRoZSBiYXNpYyBjb25jZXB0IGlzIHRoZSBzYW1lLiBUeXBpY2FsbHksIGBmb3JgIGxvb3BzIGluIFIgYXJlIGEgbGl0dGxlIHNsb3cuIFRoZXJlJ3MgYSBtdWNoIHF1aWNrZXIgd2F5IG9mIHBlcmZvcm1pbmcgdGhlc2UgZnVuY3Rpb25zLCBidXQgd2Ugd29udCBnbyBpbnRvIHRoYXQgaGVyZSAtIGl0J3MgaW1wb3J0YW50IHRvIHVuZGVyc3RhbmQgaG93IHRoZSBsb29wcyB3b3JrIGZpcnN0LiAKCkxldCdzIHRyeSBvbmUuIFdlIHdhbnQgdG8gY3JlYXRlIGEgYmFzaWMgYGZvcmAgbG9vcCB3aGljaCB3aWxsIHByaW50IGFsbCBvZiB0aGUgbnVtYmVycyBmcm9tIDEgdG8gMTAuIFdlIGNvdWxkIG9mIGNvdXJzZSBkbyB0aGlzIHdpdGhvdXQgYSBsb29wLCBieSBhc3NpZ25pbmcgYW4gaW5kaXZpZHVhbCB2YWx1ZSB0byB4LCBhbmQgcHJpbnRpbmcgdGhlbSBpbiB0dXJuOgoKYGBge3J9CnggPC0gMQpwcmludCh4KQoKeCA8LSAyCnByaW50KHgpCgp4IDwtIDMKcHJpbnQoeCkKCiMgYW5kIHNvIG9uLi4uCmBgYAoKV2hhdCBpZiB3ZSB3YW50ZWQgdG8gYXV0b21hdGUgdGhpcz8gTGV0J3MgYnVpbGQgdGhhdCBiYXNpYyBgZm9yYCBsb29wLi4uCgpgYGB7cn0KZm9yICh4IGluIDE6MTApewogIHByaW50KHgpCn0KYGBgCgpCcmlsbGlhbnQsIGJ1dCBsZXQncyBnbyB0aHJvdWdoIGp1c3QgaG93IHRoYXQgd29ya3MuCgoqIGBmb3JgIC0gd2Ugc3RhcnQgd2l0aCB0aGUgYGZvcmAgc3RhdGVtZW50LiBJZiB5b3UgYXJlIHVzaW5nIGFuIElERSwgeW91IG1pZ2h0IG5vdGljZSB0aGF0IHRoaXMgc3RhdG1lbnQgY2hhbmdlcyBjb2xvdXIgdG8gZGVub3RlIHRoYXQgaXQgaXMgb25lIG9mIFIncyBwcm90ZWN0ZWQgY29udHJvbCBzdGF0ZW1lbnRzLgoqIGB4IGluIDE6MTBgIC0gd2Uga25vdyB0aGF0IDE6MTAgcHJvZHVjZXMgYSB2ZWN0b3Igb2YgYWxsIG9mIHRoZSBudW1iZXJzIGluIHNlcXVlbmNlIGZyb20gMSB0byAxMC4gdGhlIGB4IGluYCBiaXQganVzdCBtZWFucyAiZm9yIGV2ZXJ5IHZhbHVlIGluIHRoZSB2ZWN0b3Igb2YiLiBUaGUgeCBjb3VsZCBiZSBhbnl0aGluZyB5b3Ugd2FudCBpdCB0byBiZS4gZS5nLiBgZm9yIG51bWJlcnMgaW4gMToxMGAgd291bGQgeWVpbGQgdGhlIG5hbWUgcmVzdWx0LiBOb3RlIGhlcmUgdGhhdCBkaWZmZXJlbnQgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGZvbGxvdyBkaWZmZXJlbnQgY29udmVudGlvbnMtIGluIHB5dGhvbiB5b3UnbGwgb2Z0ZW4gc2VlIGBmb3JgIGxvb3BzIHdyaXR0ZW4gYXMgYGZvciBpIGluIDE6MTBgLiAKKiBge31gIC0gdGhlIGN1cmx5IGJyYWNrZXRzIGNvbnRhaW4gdGhlIGJvZHkgb2YgdGhlIGxvb3AuIFdoYXQgdGhhdCBtZWFucyBpcyB0aGF0IGFsbCBvZiB0aGUgdmFsdWVzIHdlIGhhdmUganVzdCBzcGVjaWZpZWQgYWJvdmUgd2lsbCBoYXZlIHRoZSBjb250ZW50cyBvZiB0aGUgYHt9YCBwZXJmb3JtZWQgb24gdGhlbS4gSGVyZSwgd2UndmUgdXNlZCB0aGUgYHByaW50KClgIGZ1bmN0aW9uLCB3aGljaCBqdXN0IHByaW50cyBvdXIgdmFsdWVzIHRvIHRoZSBjb25zb2xlLgoKU28sIHRoaXMgbG9vcCBhc3NpZ25zIHggYSB2YWx1ZSBvZiAxIC0gMTAgaW4gYSBzZXF1ZW5jZSwgYW5kIHByaW50cyBpdCB0byB0aGUgY29uc29sZS4KClRoaXMgaXMgYW4gZXhhbXBsZSBvZiBhIHN1cGVyIHNpbXBsZSBhbmQgc3RyYWlnaHRmb3J3YXJkIGNvbnRyb2wgc3RhdGVtZW50LiBXZSBjb3VsZCByZXBsYWNlIHRoZSAxOjEwIHdpdGggYW55dGhpbmcgd2UgbGlrZWQsIGFuZCB0aGUgbG9vcCB3b3VsZCBjeWNsZSB0aHJvdWdoIHRoZSB2YWx1ZXMgcHJlc2VudGVkIGl0IGluIHR1cm4gdW50aWwgaXQgcmVhY2hlZCB0aGUgZmluYWwgb25lLgoKTm93LCBwcmludGluZyB0aGUgbnVtYmVycyAxIHRvIDEwIGRvZXNuJ3Qgc2VlbSBvdmVybHkgdXNlZnVsLiBXaGF0IGlmIHdlIHdhbnQgdG8gcGVyZm9ybSBhIG1hdGhlbWF0aWNhbCBvcGVyYXRpb24gb24gYWxsIG9mIHRoZSBudW1iZXJzIGluIGEgc2VxdWVuY2UgcXVpY2tseT8gTGV0J3MgZXhwYW5kIG91ciBgZm9yYCBsb29wIHNvIHRoYXQgaXQgYWRkcyAxMCB0byBldmVyeSBudW1iZXIgaW4gdGhlIHNlcXVlbmNlLCBhbmQgcHJpbnRzIHRoZSByZXN1bHQgdG8gdGhlIGNvbnNvbGU6CgpgYGB7cn0KZm9yICh4IGluIDE6MTApewogIHByaW50KHggKyAxMCkKfQpgYGAKCkVhc3kgYXMgdGhhdC4gQWdhaW4sIHRoaXMgaXMgYSByZWFsbHkgYmFzaWMgZXhhbXBsZSBvZiBhIGBmb3JgIGxvb3AsIGp1c3Qgc28geW91IGNhbiBnZXQgdG8gZ3JpcHMgd2l0aCB0aGUgcHJpbmNpcGxlIG9mIGhvdyB0aGV5IHdvcmsgaW4gUi4gCgpXZSBjYW4gYWxzbyBjcmVhdGUgYGZvcmAgbG9vcHMgd2l0aCB2ZWN0b3JzIGNvbnNpc3Rpbmcgb2YgY2hhcmFjdGVyIHN0cmluZ3MgLSBsZXQncyBjcmVhdGUgb25lIHdpdGggNCBjb21wb25lbnRzOgpgYGB7cn0KeWVhcnMgPC0gYygiMjAxOSIsICIyMDIwIiwgIjIwMjEiLCAiMjAyMiIpCmBgYAoqUmVtZW1iZXIgd2hhdCB3aGVuIHdlIGNyZWF0ZSBjaGFyYWN0ZXIgc3RyaW5nIHZlY3RvcnMsIHdlIGhhdmUgdG8gaW5jbHVkZSB0aGUgYGMoKWAgZnVuY3Rpb24qCgpMZXQncyBwb3AgdGhlc2UgaW4gYSBsb29wIHRoYXQgd2lsbCBwcmludCB0aGUgc2VudGVuY2UgIlRoZSB5ZWFyIGlzIiBmb2xsb3dlZCBieSBlYWNoIG9mIHRoZSBsZXZlbHMgb2YgdGhlIHZlY3RvciBpbiB0dXJuCgpgYGB7cn0KeWVhcnMgPC0gYygiMjAxOSIsICIyMDIwIiwgIjIwMjEiLCAiMjAyMiIpCgpmb3IgKHggaW4geWVhcnMpewogIHkgPC0gcGFzdGUoIlRoZSB5ZWFyIGlzIiwgeCkKICBwcmludCh5KQp9CmBgYAoKVGhpcyBsb29wcyB0aHJvdWdoIHRoZSBmb3VyIHllYXJzIHdlIGhhdmUgZ2l2ZW4gaW4gdGhlIHZlY3RvciwgYW5kIHVzZXMgdGhlIGBwYXN0ZSgpYCBmdW5jdGlvbiB0byBzdGljayB0d28gY2hhcmFjdGVyIHN0cmluZ3MgdG9nZXRoZXIsIHByaW50aW5nIGVhY2ggb2YgdGhlIHZlY3RvciBlbGVtZW50cyBpbiB0dXJuLiBOb3RpY2UgdGhhdCB3ZSd2ZSBjcmVhdGVkIGEgbmV3IG9iamVjdCB3aXRoaW4gdGhlIGxvb3AsIGB5YCAtIGlmIHlvdSBsb29rIGluIHlvdXIgUiBlbnZpcm9ubWVudCB3aW5kb3csIG9yIHRyeSBhbmQgcHJpbnQgeSB0byB0aGUgY29uc29sZSB3aXRoIGBwcmludCh5KWAsIHlvdSdsbCBzZWUgdGhhdCB5IGlzIHN0b3JlZCBhcyAiVGhlIHllYXIgaXMgMjAyMiIsIHdoaWNoIGlzIHRoZSBmaW5hbCBpdGVyYXRpb24gb2YgdGhlIGxvb3AuIEl0J3MgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCB0aGUgb3RoZXIgaXRlcmF0aW9ucyBhcmUgbm90IHN0b3JlZCBpbiB0aGUgd2lkZXIgUiBlbnZpcm9ubWVudCwgYXMgdGhlIGxvb3Agb3ZlcndyaXRlcyBpdHNlbGYgZXZlcnkgdGltZSBpdCBwZXJmb3JtcyBhbiBpdGVyYXRpb24uCgpKdXN0IHRvIHJlY2FwLGEgYGZvcmAgbG9vcCBydW5zIHRocm91Z2ggdmFsdWVzIGluIGEgdmVjdG9yIChhbmQgaXMgcXVpY2sgaW4gdGhlc2Ugc21hbGwgdG95IGV4YW1wbGVzISksIGFuZCBkb2VzIHNvbWUgd29yayBmb3IgeW91IGluc2lkZSB0aGUgc3RhdGVtZW50LiBDdXJseSBicmFja2V0cyBge31gIGRlbm90ZSB0aGUgYm9keSBvZiB0aGUgbG9vcCwgd2hpY2ggaXMgd2hlcmUgd2UgdGVsbCBSIHdoYXQgd2Ugd2FudCBpdCB0byBkbyB3aXRoIG91ciBpbnB1dC4gV2hpbHN0IGZvciBsb29wcyBhcmUgZ3JlYXQsIGV2ZXJ5IGV4YW1wbGUgdGhhdCB3ZSd2ZSBqdXN0IHJ1biB0aHJvdWdoIGNhbiBhY3R1YWxseSBiZSBhY2hlaXZlZCB3aXRoIHNpbXBsZXIsIGFuZCBtb3JlIGNvbXB1dGF0aW9uYWxseSBlZmZpY2llbnQgY29kZSAoc29ycnkpLiBSZW1lbWJlciB0byB0aGluayBhYm91dCB5b3VyIGNvZGUsIGFuZCBjb25zaWRlciB3aGV0aGVyIHRoZXJlIG1pZ2h0IGJlIGVhc2llciBzb2x1dGlvbnMgdG8gYSBwcm9ibGVtIQoKIyMgVmVjdG9yaXNhdGlvbiBhcyBhIG1vcmUgZWZmaWNpZW50IG1lY2hhbmlzbT8KCkZvciBvdXIgZmlyc3QgZXhhbXBsZSwgcHJpbnRpbmcgMSAtIDEwIHRvIHRoZSBzY3JlZW4gd2l0aCBhIGxvb3AsIHdlIGNvdWxkIHNhdmUgYSBsb3Qgb2YgdGltZSBieSBleHBsaWNpdGx5IHBvcHBpbmcgeCBpbnRvIGl0J3Mgb3duIHZlY3RvciAocmF0aGVyIHRoYW4gYWRkaW5nIHRoaXMgdG8gdGhlIGNvbmRpdGlvbnMgb2YgYSBgZm9yYCBsb29wKSwgYW5kIGRlYWxpbmcgd2l0aCBpdCB0aGF0IHdheToKCmBgYHtyfQp4IDwtIDE6MTAKcHJpbnQoeCkKYGBgCgpBcyB5b3UgY2FuIHNlZSwgdGhpcyB1bHRpbWF0ZWx5IHlpZWxkcyB0aGUgc2FtZSByZXN1bHQsIHdpdGggY29uc2lkZXJhYmx5IGxlc3MgZmFmZmluZy4gSW4gdGhlc2Ugc21hbGwgdG95IGV4YW1wbGVzLCB0aGVyZSBpc24ndCBhIHdob2xlIGxvdCBvZiBkaWZmZXJlbmNlIGluIGNvbXB1dGF0aW9uIHRpbWUsIGJ1dCBpbiBtdWNoIGxhcmdlciBkYXRhc2V0cywgdGhpcyBpcyBjZXJ0YWlubHkgc29tZXRoaW5nIHdvcnRoIGNvbnNpZGVyaW5nLiBHZW5lcmFsbHksIHZlY3RvcmlzYXRpb24gaXMgbXVjaCBzcGVlZGllciB0aGFuIGZvciBsb29wcy4KCkZvciB0aGUgZXhhbXBsZSB3aGVyZSB3ZSBhZGRlZCAxMCB0byB4LCB3ZSBjYW4gdXNlIHRoZSBzYW1lIHZlY3RvcmlzYXRpb24gcHJpbmNpcGxlLiBUaGlzIGlzIHdoZXJlIFIgZGlmZmVycyBpbiBpdCdzIGZ1bmRlbWVudGFsIGRldiBtYWtldXAgdG8sIGZvciBleGFtcGxlLCBiYXNoLCB3aGVyZSB5b3Ugd291bGQgKipoYXZlKiogdG8gZG8gYSBgZm9yYCBsb29wIHRvIHBlcmZvcm0gdGhlIGZvbGxvd2luZzoKCmBgYHtyfQp4IDwtIDE6MTAgIyByZWNyZWF0ZSBvdXIgMToxMCB2ZWN0b3IKcHJpbnQoeCArIDEwKQpgYGAKCkhlcmUsIHlvdSBkb24ndCBldmVuIG5lZWQgdGhlIGBwcmludCgpYCBmdW5jdGlvbiwganVzdCB0eXBpbmcgYHggKyAxMGAgd291bGQgYmUgc3VmZmljaWVudCEKCllvdSBkb24ndCBldmVuIHJlYWxseSBuZWVkIHRvIHVzZSBsb29wcyBvbiBjaGFyYWN0ZXIgdmVjdG9ycyBpbiBSISBMZXQncyBnbyBiYWNrIHRvIG91ciAidGhlIHllYXIgaXMiIGV4YW1wbGUuIFdlIGNhbiBhdm9pZCBhIGxvb3AgYnkgdXNpbmcgdGhlIGBwYXN0ZSgpYCBmdW5jdGlvbiBvbiB0aGUgdmVjdG9yIGV4cGxpY2l0bHksIHJhdGhlciB0aGFuIGhhdmluZyB0byBmb3JjZSBpdCB0aHJvdWdoIGEgbG9vcDoKCmBgYHtyfQp5ZWFycyA8LSBjKCIyMDE5IiwgIjIwMjAiLCAiMjAyMSIsICIyMDIyIikKcGFzdGUoIlRoZSB5ZWFyIGlzIiwgeWVhcnMpCmBgYAoKIyMgU28gd2h5IGJvdGhlciB3aXRoIGZvciBsb29wcyBpbiB0aGUgZmlyc3QgcGxhY2U/CgpBbGwgb2YgdGhpcyBpcyBub3QgdG8gc2F5IHRoYXQgYGZvcmAgbG9vcHMgYXJlIHJ1YmJpc2ggYW5kIHVzZWxlc3MgaW4gUiAtIGluIGZhY3QgdGhlcmUgd2lsbCBsaWtlbHkgYmUgdGltZXMgd2hlcmUgdGhleSBhcmUgdW5hdm9pZGFibGUsIGFuZCBhIHZlY3RvciBiYXNlZCBzb2x1dGlvbiBqdXN0IHdvbid0IGN1dCBpdC4gSXQgaXMgaG93ZXZlciB3b3J0aCBoYW1tZXJpbmcgaG9tZSB0aGUgcG9pbnQgdGhhdCB0aGV5IGFyZSByZWFsbHkgd29ydGggdGhpbmtpbmcgYWJvdXQgcXVpdGUgY2FyZWZ1bGx5LiBUaGVyZSB3aWxsIG9mdGVuIGJlIGEgYmV0dGVyIHdheSB0byBkbyB3aGF0ZXZlciB5b3UncmUgdHJ5aW5nIHRvIGRvIC0gc2xvdyBkb3duIHdoZW4geW91J3JlIGNvZGluZy4gU3RvcCBhbmQgdGhpbmsgYWJvdXQgd2hhdCBpdCBpcyB5b3UncmUgdHJ5aW5nIHRvIGFjaGlldmUuIEJlZ2lubmVycyBpbiBwYXJ0aWN1bGFyIHRlbmQgdG8gbGVhcm4gaG93IHRvIGNyZWF0ZSBgZm9yYCBsb29wcywgYW5kIHRoZW4gdXNlIHRoZW0gZm9yIGV2ZXJ5dGhpbmcsIHdoZW4gb2Z0ZW4sIGEgdmVjdG9yIGJhc2VkIHNvbHV0aW9uIHdvdWxkIGJlIG11Y2ggcXVpY2tlciBhbmQgc2ltcGxlciEKCgojIGBJZmAgc3RhdGVtZW50cwoKTm93LCBvbiB0byBgaWZgIHN0YXRlbWVudHMuIFRoZXNlIGFyZSBhbm90aGVyIGNvbnRyb2wgZmxvdyBjb2RpbmcgbWVjaGFuaXNtIHlvdSBjYW4gdXNlIGluIFIgYW5kIGZ1cnRoZXIgYWZpZWxkIHRvIGN1c3RvbWlzZSB0aGUgb3JkZXIgdGhhdCBjb21tYW5kcyBhcmUgcnVuIGluLCBkZXBlbmRpbmcgb24gY29uZGl0aW9ucyBvZiB5b3VyIGRhdGEuIFRoaW5rIGFib3V0IHRoZSBrZXR0bGUgZXhhbXBsZSAtICoqSUYqKiB5b3VyIHdhdGVyIGJvaWxlZCwgdGhlbiB5b3UgcGVyZm9ybSB0aGUgdGFzay4gYGlmYCBzdGF0ZW1lbnRzIGFzayB3aGV0aGVyIGEgY29uZGl0aW9uIGhhcyBiZWVuIG1ldCwgYmVmb3JlIHRoZXkgcGVyZm9ybSBhIGZ1bmN0aW9uLiBUaGUgYmVzdCB3YXkgdG8gZXhwbGFpbiB0aGlzIGlzLCBhcyBhbHdheXMsIHdpdGggYW4gZXhhbXBsZToKYGBge3J9CnogPC0gMQppZiAoeiA8IDEwKXsKICBwcmludCgieiBpcyBsZXNzIHRoYW4gMTAiKQp9CmBgYAoKV2UgY2FuIHNlZSB0aGF0IGJlY2F1c2Ugd2UndmUgZ2l2ZW4gYHpgIHRoZSB2YWx1ZSBvZiAxLCB3aGljaCBpcyBsZXNzIHRoYW4gMTAsIHdlIGdldCBhbiBvdXRwdXQgdGVsbGluZyB1cyBzbyAoUiBpcyBwZXJmb3JtaW5nIHRoZSBmdW5jdGlvbiEpLiBXaGF0IGhhcHBlbnMgaWYgd2UgY2hhbmdlIHRoZSBhc3NpZ25tZW50IG9mIGB6YCBhbmQgdHJ5IGFnYWluPwoKYGBge3J9CnogPC0gNDUKaWYgKHogPCAxMCl7CiAgcHJpbnQoInogaXMgbGVzcyB0aGFuIDEwIikKfQpgYGAKCldlIGRvbid0IGdldCBhbiBvdXRwdXQuIEJlY2F1c2UgdGhlIGNvbmRpdGlvbiB3YXMgbm90IG1ldCwgbm8gZnVuY3Rpb24gd2FzIHBlcmZvcm1lZCBvbiBvdXIgZGF0YS4KClRoZSB3YXkgdGhhdCB0aGlzIGlzIGNvZGVkIGluIFIgaXMgdGhhdCB0aGUgcHJvdmlkZWQgY29uZGl0aW9uIChpbiBgKClgKSBpcyBydW4sIHRvIGdpdmUgYSBsb2dpY2FsIG91dHB1dC4gSWYgdGhhdCBvdXRwdXQgaXMgYFRSVUVgLCB0aGUgYm9keSBvZiB0aGUgZnVuY3Rpb24gKGluIGB7fWApIGlzIHJ1bi4gSWYgdGhlIG91dHB1dCBpcyBgRkFMU0VgLCBub3RoaW5nIHdpbGwgaGFwcGVuLiAKCiMgYGVsc2VgIHN0YXRlbWVudHMKCkl0IGlzbid0IGEgaHVnZSBsZWFwIHRvIGFzayB3aGV0aGVyIHdlIGNvdWxkIHRha2UgdGhlIGFib3ZlIGFuZCBwZXJmb3JtIGEgZGlmZmVyZW50IGZ1bmN0aW9uIGlmIHRoZSBjb25kaXRpb24gd2FzIG5vdCBtZXQsIGFuZCB0aGUgbG9naWNhbCBvdXRwdXQgd2FzIGBGQUxTRWAuIFdlIGNhbiBhY2hpZXZlIHRoaXMgYnkgcGFpcmluZyBvdXIgYGlmYCBzdGF0ZW1lbnQgd2l0aCBhbiBgZWxzZWAgc3RhdGVtZW50LiBUaGUgc3ludGF4IG9mIHRoaXMgY2FuIHRha2UgYSBsaXR0bGUgZ2V0dGluZyB1c2VkIHRvLCBiZWNhdXNlIGl0IHBhaXJzIHR3byBzZXRzIG9mIGB7fWAgc2VwYXJhdGVkIGJ5IGFuIGBlbHNlYCBzdGF0ZW1lbnQuIExldCdzIGRlbW9uc3RyYXRlOgoKYGBge3J9CnogPC0gMQoKaWYgKHogPCAxMCl7CiAgcHJpbnQoInogaXMgbGVzcyB0aGFuIDEwIikKfSBlbHNlIHsKICBwcmludCgieiBpcyBtb3JlIHRoYW4gMTAiKQp9CmBgYAoKV2l0aCBhbiBpbnB1dCBvZiAxLCB3ZSBnZXQgYSBwcmludGVkIG1lc3NhZ2UgdGVsbGluZyB1cyB0aGF0IHogaXMgbGVzcyB0aGFuIDEwLiBXaGF0IGlmIHdlIGNoYW5nZSB6IHRvIGJlIGdyZWF0ZXIgdGhhbiAxMD8KCmBgYHtyfQp6IDwtIDIwCgppZiAoeiA8IDEwKXsKICBwcmludCgieiBpcyBsZXNzIHRoYW4gMTAiKQp9IGVsc2UgewogIHByaW50KCJ6IGlzIG1vcmUgdGhhbiAxMCIpCn0KYGBgCgpBcyBleHBlY3RlZCwgUiB0ZWxscyB1cyB0aGF0IHogaXMgbW9yZSB0aGFuIDEwLiBUaGlzIGNvbWJpbmF0aW9uIG9mIGBpZmAgYW5kIGBlbHNlYCBzdGF0ZW1lbnRzIHJ1bnMgYSBjb250cm9sIGZsb3cgdGhhdCB0YWtlcyBhbiBpbnB1dCwgYW5kIGlmIGEgY29uZGl0aW9uIGlzIG1ldCwgcnVucyBmdW5jdGlvbiBhLiBJZiB0aGUgY29uZGl0aW9uIGlzIG5vdCBtZXQsIGl0IHJ1bnMgZnVuY3Rpb24gYi4gVGhpcyBiYXNpYyBwcmluY2lwbGUgYWxsb3dzIHlvdSB0byBwZXJmb3JtIHNsaWdodGx5IG1vcmUgY29tcGxleCBmdW5jdGlvbnMgb3IgYW5hbHlzZXMsIGJhc2VkIG9uIHRoZSBpbnB1dCB0aGF0IHlvdSBnaXZlLgoKIyBUaGUgYGlmZWxzZSgpYCBmdW5jdGlvbgoKVGhlcmUgaXMgYW4gYWx0ZXJuYXRpdmUgdG8gYGlmYCBhbmQgYGVsc2VgIGNvbnRyb2wgZmxvdyBmdW5jdGlvbnMgaW4gUiAtIHRoZSBgaWZlbHNlKClgIGZ1bmN0aW9uLiBUaGlzIGRvZXNuJ3QgYWx3YXlzIHBlcmZvcm0gaW4gcXVpdGUgdGhlIHdheSB0aGF0IHlvdSBtaWdodCBleHBlY3QsIGJ1dCBpdCdzIGNlcnRhaW5seSBhbiBvcHRpb24gdG8gY29uc2lkZXIuIFRoZSBzeW50YXggaXMgcGVyaGFwcyBhIGxpdHRsZSBtb3JlIGZhbWlsaWFyIHRoYW4gdGhlIGNvbnRyb2wgZmxvdyBzdGF0ZW1lbnRzLi4uIExldCdzIHBlcmZvcm0gdGhlIHNhbWUgdGhpbmcgd2UganVzdCBkaWQsIGJ1dCB0aGlzIHRpbWUgdXNpbmcgYW4gYGlmZWxzZSgpYCBmdW5jdGlvbjoKCmBgYHtyfQp6IDwtIDEKaWZlbHNlKHogPCAxMCwgImxlc3MgdGhhbiAxMCIsICJtb3JlIHRoYW4gMTAiKQpgYGAKCgpgYGB7cn0KeiA8LSAyMAppZmVsc2UoeiA8IDEwLCAibGVzcyB0aGFuIDEwIiwgIm1vcmUgdGhhbiAxMCIpCmBgYAoKR3JlYXQuIEFsbCB3b3JrcyB0aGUgc2FtZSBzbyBmYXIhIFRoZSBgaWZlbHNlKClgIGZ1bmN0aW9uIHRha2VzIGFuIGlucHV0LCBldmFsdWF0ZXMgaXQgYWdhaW5zdCBhIGNvbmRpdGlvbiAoaGVyZSB0aGF0IGl0IGlzIDwgMTApLiBJZiB0aGUgY29uZGl0aW9uIGlzIGBUUlVFYCwgaXQgcGVyZm9ybXMgdGhlIGZpcnN0IG9wdGlvbiwgaWYgYEZBTFNFYCwgZG9lcyB0aGUgMm5kLiAKCkhlbHBmdWxseSwgd2UgY2FuIGFsc28gcGVyZm9ybSB0aGUgYGlmZWxzZSgpYCBmdW5jdGlvbnMgb24gYSB2ZWN0b3IuIExldCdzIGNyZWF0ZSBhIG51bWVyaWMgdmVjdG9yIGZyb20gMSAtIDYwIGluIHN0ZXBzIG9mIDYgYW5kIHJ1biBvdXIgZnVuY3Rpb24gYWdhaW4KCmBgYHtyfQp6IDwtIHNlcShmcm9tID0gMSwgdG8gPSA2MCwgYnkgPSA2KQppZmVsc2UoeiA8IDEwLCAibGVzcyB0aGFuIDEwIiwgIm1vcmUgdGhhbiAxMCIpCmBgYAoKV2UgZW5kIHVwIHdpdGggMTAgb3V0cHV0cywgZWFjaCB0ZWxsaW5nIHVzIHdoZXRoZXIgYSByZXN1bHQgaXMgbGVzcyBvciBtb3JlIHRoYW4gMTAhCgpgYGB7cn0KeiA8LSBzZXEoZnJvbSA9IDEsIHRvID0gNjAsIGJ5ID0gNikKCmlmICh6IDwgMTApewogIHByaW50KCJ6IGlzIGxlc3MgdGhhbiAxMCIpCn0gZWxzZSB7CiAgcHJpbnQoInogaXMgbW9yZSB0aGFuIDEwIikKfQpgYGAKCllvdSBjYW4gc2VlIGZyb20gdGhlIGVycm9yIGFib3ZlLCB0aGF0IHlvdSBjYW4ndCBwZXJmb3JtIGBpZmAgYGVsc2VgIHN0YXRlbWVudHMgb24gYSB2ZWN0b3IgLSB0aGUgY29uZGl0aW9uIGlzIG9ubHkgZXhwZWN0aW5nIHNvbWV0aGluZyB3aXRoIGEgbGVuZ3RoIG9mIDEsIHJhdGhlciB0aGFuLCBpbiB0aGlzIGNhc2UsIDEwLgoKCldlIGNhbiB1c2UgYGlmZWxzZSgpYCBvbiBjaGFyYWN0ZXIgdmVjdG9ycyB0b28uIExldCdzIGNyZWF0ZSBvbmUgYW5kIHRyeSBpdCBvdXQ6CgpgYGB7cn0KY291bnRyaWVzIDwtIGMoIlVLIiwgIlVTQSIsICJGcmFuY2UiLCAiU3BhaW4iKQppZmVsc2UoY291bnRyaWVzID09ICJVSyIsICJVSyIsICJFbHNld2hlcmUiKQoKYGBgCgpUaGUgZnVuY3Rpb24gaXMgZXZhbHVhdGluZyB0byBzZWUgaWYgdGhlIGlucHV0IG1hdGNoZXMgdGhlIHN0cmluZyAiVUsiLCBhbmQgaWYgaXQgZG9lcywgd2lsbCBwcmludCAiVUsiLCBvdGhlcndpc2UsIHByaW50cyAiRWxzZXdoZXJlIi4gRmFpcmx5IHN0cmFpZ2h0Zm9yd2FyZCBzdHVmZiEKCgojIFdyaXRpbmcgeW91ciBvd24gZnVuY3Rpb25zOgoKV3JpdGluZyB5b3VyIG93biBmdW5jdGlvbnMgaXMgYW4gaW1wb3J0YW50IHBhcnQgb2YgcHJvZ3JhbW1pbmcuIEl0IGtlZXBzIGNvZGUgc2ltcGxlIGFuZCByZWFkYWJsZSwgYW5kIGFsbG93cyB5b3UgdG8gcGVyZm9ybSBhIHNldCBvZiB0YXNrcyBtdWx0aXBsZSB0aW1lcyB3aXRob3V0IGxvYWRzIG9mIGR1cGxpY2F0aW9uIGluIHlvdXIgY29kZS4gSWYgeW91IHdhbnRlZCB0byBkZXZlbG9wIHlvdXIgb3duIHBhY2thZ2UsIGN1c3RvbSBmdW5jdGlvbiBjcmVhdGlvbiB3b3VsZCBiZSBhIGh1Z2UgcGFydCBvZiB0aGlzIC0gYSBwYWNrYWdlIGlzIGVzc2VudGlhbGx5IGp1c3QgYSBjb2xsZWN0aW9uIG9mIGZ1bmN0aW9ucyEKClRoZSBwcm9jZXNzIG9mIGNyZWF0aW5nIGZ1bmN0aW9ucyBpcyBxdWl0ZSBzdHJhaWdodGZvcndhcmQgLSBJIGRvIGl0IGxvYWRzIHRvIG1ha2UgbXkgbGlmZSBxdWljayBhbmQgZWFzeS4gTGV0J3Mgc3RhcnQgYnkgY3JlYXRpbmcgYSBzaW1wbGUgZnVuY3Rpb24gdGhhdCBhZGRzIDEwIHRvIGFueSBudW1lcmljIGlucHV0OgoKYGBge3J9CmFkZF90ZW4gPC0gZnVuY3Rpb24oeCl7CiAgeSA8LSB4ICsgMTAKICByZXR1cm4oeSkKfQoKYWRkX3RlbigxKQpgYGAKClNvLCBoZXJlLCB3ZSd2ZSBjcmVhdGVkIGFuZCB0ZXN0ZWQgYSBiYXNpYyBmdW5jdGlvbi4gTGV0J3MgZGlzc2VjdCBpdCBhIGxpdHRsZToKCiogYGFkZF90ZW5gIC0gZmlyc3QsIHdlIGhhdmUgdG8gZ2l2ZSBvdXIgbmV3IGZ1bmN0aW9uIGEgbmFtZS4gSSd2ZSBpbWFnaW5hdGl2ZWx5IGNhbGxlZCB0aGlzIG9uZSBhZGRfdGVuLiAKKiBUaGVuLCB3ZSBhc3NpZ24gdGhlIHJlc3Qgb2YgdGhlIGNvZGUgdG8gdGhlIG5ldyBmdW5jdGlvbiBuYW1lIHdpdGggb3VyIGFzc2lnbm1lbnQgYXJyb3cgYDwtYAoqIE5leHQgdXAsIHdlIGhhdmUgdGhlIGBmdW5jdGlvbmAgZnVuY3Rpb24uIFRoaXMgdGVsbHMgUiB0aGF0IHdlIHdhbnQgdG8gdHVybiBvdXIgZnVuY3Rpb24gbmFtZSBpbnRvIGEgbmV3IGZ1bmN0aW9uCiogYGZ1bmN0aW9uKHgpYCAtIHRoaXMgdGVsbHMgUiB0aGF0IHdlIGFyZSBjcmVhdGluZyBhIGZ1bmN0aW9uIHdpdGggYSBzaW5nbGUgYXJndW1lbnQgKG9yIGlucHV0KSwgeC4KKiBge31gIHRoaXMgZGVub3RlcyB0aGUgYm9keSBvZiB0aGUgZnVuY3Rpb24gLSB3aGF0ZXZlciBjb2RlIGlzIGluIGhlcmUgaXMgd2hhdCB3aWxsIGJlIGFwcGxpZWQgdG8gYW4gaW5wdXQKKiBgeSA8LSB4ICsgMTBgIC0gdGhpcyBiaXRzIG9idmlvdXMgLSBhZGQgMTAgdG8gb3VyIGlucHV0IG9mIHggYW5kIGFzc2lnbiBpdCBhIG5ldyBuYW1lLCBgeWAuCiogYHJldHVybih5KWAgLSBnaXZlIHVzIGFuIG91dHB1dCEgV2l0aG91dCB0aGlzLCBSIHdvdWxkbid0IGF1dG9tYXRpY2FsbHkgdGVsbCB1cyB3aGF0IHRoZSBvdXRwdXQgb2Ygd2hhdGV2ZXIgd2UndmUganVzdCBhc2tlZCBpdCB0byBkbyBpcyEKCk5vdGljZSBoZXJlIHRoYXQgdGhlIG5ldyBgeWAgb2JqZWN0IGlzIHRyZWF0ZWQgYSBsaXR0bGUgZGlmZmVyZW50bHkgaW4gZnVuY3Rpb25zIHRoYW4gbG9vcHMuIElmIHdlIHJlbW92ZSBgeWAgZnJvbSBvdXIgZW52aXJvbm1lbnQgYW5kIHJ1biB0aGUgZnVuY3Rpb24gYWdhaW4sIHlvdSdsbCBub3RpY2UgdGhhdCBpdCBkb2VzIG5vdCByZS1hcHBlYXIuIFdoYXRldmVyIG9iamVjdHMgeW91IGNyZWF0ZSB3aXRoaW4gdGhlIGJvZHkgb2YgdGhlIGZ1bmN0aW9uIGV4aXN0IG9ubHkgd2l0aGluIHRoYXQgZnVuY3Rpb24gLSB0aGV5IGFyZSBub3QgY2FsbGFibGUgdG8gdGhlIHdpZGVyIFIgZW52aXJvbm1lbnQuCgpGdW5jdGlvbnMgY2FuIGFsc28gdGFrZSBhIHZlY3RvciBpbnB1dCAtIGxldCdzIHJ1biBvdXIgYGFkZF90ZW4oKWAgZnVuY3Rpb24gd2l0aCBhIHZlY3RvciBhbmQgc2VlIHdoYXQgaGFwcGVucwoKYGBge3J9CmFkZF90ZW4gPC0gZnVuY3Rpb24oeCl7CiAgeSA8LSB4ICsgMTAKICByZXR1cm4oeSkKfQoKeiA8LSAxOjEwCmFkZF90ZW4oeikKYGBgCgpPZiBjb3Vyc2UsIHdlIGNvdWxkIHBlcmZvcm0gdGhpcyBmdW5jdGlvbiBtYW51YWxseSwgYXMgaXQgaXMgYSByZWFsbHkgc3RyYWlnaHRmb3J3YXJkIGV4YW1wbGUuIEknZCBiZSB1bmxpa2VseSB0byBib3RoZXIgY3JlYXRpbmcgYSBmdW5jdGlvbiB0byBkbyB0aGlzIGluIHByYWN0aWNlLCBidXQgaXQncyBhIHVzZWZ1bCBkZW1vbnN0cmF0aW9uLiAKCgojIFRoZSBhbmF0b215IG9mIGEgZnVuY3Rpb24KCkxldCdzIHF1aWNrbHkgcmVjYXAgdGhlIGFuYXRvbXkgb2YgaG93IGEgZnVuY3Rpb24gd29ya3MKCmBmdW5jdGlvbih4KWAgZGVjbGFyZXMgYSBmdW5jdGlvbi4gSXQgY3JlYXRlcyB0aGUgZnVuY3Rpb24gd2l0aGluIHRoZSBSIGVudmlyb25tZW50LCBhbmQgZGVmaW5lcyB0aGUgYXJndW1lbnRzIHRoYXQgdGhlIGZ1bmN0aW9uIHJlcXVpcmVzLiBJbiBvdXIgZXhhbXBsZSBhYm92ZSwgd2hlbmV2ZXIgeW91IHJ1biBgYWRkX3RlbmAsIHlvdSAqbXVzdCogaGF2ZSBhbiB4IGFyZ3VtZW50LCBvdGhlcndpc2UgdGhlIGZ1bmN0aW9uIHdpbGwgbm90IHJ1bi4KCmB7fWAgZGVmaW5lIHRoZSBibG9jayBvZiBjb2RlIHdpdGhpbiB3aGljaCB0aGUgd29yayB0aGF0IHRoZSBmdW5jdGlvbiBkb2VzIHRha2VzIHBsYWNlLiBIZXJlLCBgeWAgaXMgb25seSBkZWZpbmVkIHdpdGhpbiB0aGUgZnVuY3Rpb24uCgpgcmV0dXJuKHkpYCB0ZWxscyBSIHRvIGdpdmUgdXMgYW4gb3V0cHV0LCBhbmQgZGlzcGxheSB3aGF0IHRoZSBmdW5jdGlvbiBoYXMgZG9uZS4KCgojIEZ1bmN0aW9ucyB3aXRoIG11bHRpcGxlIGFyZ3VtZW50cwoKV2UgY2FuIGV4dGVuZCBvdXIgZnVuY3Rpb25zIHRvIHRha2UgbXVsdGlwbGUgYXJndW1lbnRzLCBvciBpbnB1dHMsIHVzaW5nIHRoZSBiYXNpY3MgdGhhdCB3ZSd2ZSBqdXN0IGxlYXJuZWQuIEZ1bmN0aW9ucyB0aGF0IHdlIGhhdmUgdXNlZCB0aHJvdWdob3V0IHRoZSBjb3Vyc2Ugc28gZmFyIGhhdmUgdGFrZW4gbXVsdGlwbGUgYXJndW1lbnRzLCBzbyBsZXQncyB0cnkgYW5kIGFsc28gY3JlYXRlIG9uZS4gV2UnbGwgd3JpdGUgYSBmdW5jdGlvbiB0aGF0IG11bHRpcGxpZXMgdHdvIG51bWJlcnMgdG9nZXRoZXI6CmBgYHtyfQptdWx0aXBseSA8LSBmdW5jdGlvbih4LCB5KXsKICB6IDwtIHggKiB5CiAgcmV0dXJuKHopCn0KCm11bHRpcGx5KDMsMikKYGBgCgpJbiBvdXIgUiBlbnZpcm9ubWVudCB3aW5kb3csIHdlIGNhbiBzZWUgYSBuZXcgc2VjdGlvbiBoYXMgYmVlbiBjcmVhdGVkIGNhbGxlZCAnRnVuY3Rpb25zJy4gV2l0aGluIHRoYXQsIHdlIGNhbiBzZWUgYm90aCBvdXIgYGFkZF90ZW5gIGFuZCBvdXIgYG11bHRpcGx5YCBmdW5jdGlvbnMsIGFuZCB0aGUgbnVtYmVyIG9mIGFyZ3VtZW50cyB0aGF0IGVhY2ggdGFrZXMuIAoKIyBGdW5jdGlvbnMgd2l0aCBkZWZhdWx0IGFyZ3VtZW50cwoKWW91J2xsIGZpbmQgb2Z0ZW4gdGhhdCBzZXZlcmFsIGFyZ3VtZW50cyBpbiBmdW5jdGlvbnMgdGhhdCB5b3UncmUgcnVubmluZyBpbiBSIGhhdmUgZGVmYXVsdCBzZXR0bmdzIHRoYXQgeW91IGRvIG5vdCBoYXZlIHRvIGV4cGxpY2l0bHkgY29kZSBpbiBvcmRlciBmb3IgUiB0byBwZXJmb3JtIHRoZW0uIEZvciBleGFtcGxlLCBpbiB0aGUgYHN1bSgpYCBhbmQgYG1lYW4oKWAgZnVuY3Rpb25zLCB0aGUgZGVmYXVsdCBmb3IgdGhlIGBuYS5ybWAgYXJndW1lbnQgaXMgYEZBTFNFYC4gV2UgY2FuIGVkaXQgb3VyIGBtdWx0aXBseSgpYCBmdW5jdGlvbiB0byBoYXZlIGEgZGVmYXVsdCBgeWAgdmFsdWUgb2YgMTA6CgpgYGB7cn0KbXVsdGlwbHkgPC0gZnVuY3Rpb24oeCwgeSA9IDEwKXsKICB6IDwtIHggKiB5CiAgcmV0dXJuKHopCn0KCm11bHRpcGx5KDMpCm11bHRpcGx5KDMsIDIpCmBgYAoKSGVyZSwgd2UgY2FuIHNlZSB0aGF0IGlmIHdlIGluY2x1ZGUgb25seSAxIGFyZ3VtZW50IHRvIHRoZSBmdW5jdGlvbiBub3csIGl0IHdpbGwgcnVuIGFuZCB1c2UgdGhlIGRlZmF1bHQgb2YgeSA9IDEwLiBJZiB3ZSBpbmNsdWRlIHR3byBhcmd1bWVudHMgb3Vyc2VsdmVzLCB3ZSBvdmVycmlkZSB0aGUgZGVmYXVsdCBhbmQgdGhlIGZ1bmN0aW9uIHBlcmZvcm1zIG9uIGJvdGggb2YgdGhlIGFyZ3VtZW50cyB0aGF0IHdlIGhhdmUgc3BlY2lmaWVkLiBZb3UgY2FuIGhvcGVmdWxseSBzZWUgaG93IHdyaXRpbmcgZnVuY3Rpb25zIHdpdGggbXVsdGlwbGUgYXJndW1lbnRzIGFuZCBkZWZhdWx0cyBpc24ndCB0b28gbXVjaCBvZiBhIHN0cmV0Y2ggZnJvbSB3cml0aW5nIGEgZnVuY3Rpb24gd2l0aCBhIHNpbmdsZSBhcmd1bWVudCwgYW5kIHNlZSBob3cgdXNlZnVsIHRoYXQgbWlnaHQgYmUgaW4geW91ciBjb2RpbmchCgojIENvbWJpbmluZyBmdW5jdGlvbnMgYW5kIGNvbmRpdGlvbmFsczoKCk5vdywgd2UgY2FuIGNvbWJpbmUgYWxsIG9mIHRoZSBza2lsbHMgdGhhdCB3ZSd2ZSBsZWFybmVkIHRvZGF5IGFuZCBjcmVhdGUgY29tcGxleCBmdW5jdGlvbnMgd2l0aCBzb21lIGNvbnRyb2wgZmxvdyBzdGF0ZW1lbnRzIGluc2lkZSBvZiB0aGVtLiBMZXQncyBzdGFydCBieSB3dGl0aW5nIGEgZnVuY3Rpb24gdGhhdCBldmFsdWF0ZXMgd2hldGhlciBhIG51bWVyaWNhbCBpbnB1dCBpcyBncmVhdGVyIHRoYW4gb3IgbGVzcyB0aGFuIDEwLiAKCmBgYHtyfQpldmFsMTAgPC0gZnVuY3Rpb24oeCl7CiAgeSA8LSBpZmVsc2UoeCA8IDEwLCAibGVzcyB0aGFuIDEwIiwgImdyZWF0ZXIgdGhhbiAxMCIpCiAgcmV0dXJuKHkpCn0KCmV2YWwxMCgxKQpldmFsMTAoMTUpCgpgYGAKCldlJ3ZlIGluY2x1ZGVkIGEgc2ltcGxlIGlmZWxzZSBmdW5jdGlvbiB3aXRoaW4gb3VyIGV2YWwxMCBmdW5jdGlvbiwgd2hpY2ggdGFrZXMgYSBuZXcgb2JqZWN0LCB5LCBhbmQgcGVyZm9ybXMgYW4gaWZlbHNlKCkgZnVuY3Rpb24gdXBvbiBpdCwgYW5kIHJldHVybnMgdGhlIG91dHB1dC4gV2UgY291bGQgZG8gdGhlIHNhbWUgd2l0aCB0aGUgZXhwbGljaXQgYGlmYCBhbmQgYGVsc2VgIGNvbnRyb2wgZmxvdyBzdGF0ZW1lbnRzCgpgYGB7cn0KZXZhbDEwXzIgPC0gZnVuY3Rpb24oeCl7CiAgeSA8LSBpZiAoeCA8IDEwKXsKICAgIHByaW50KCJsZXNzIHRoYW4gMTAiKQogICAgfSBlbHNlIHsKICAgICAgcHJpbnQoImdyZWF0ZXIgdGhhbiAxMCIpCiAgICB9Cn0KCmV2YWwxMF8yKDEpCmV2YWwxMF8yKDE1KQpgYGAKCldoaWxzdCB0aGlzIGlzIGEgc2ltcGxlIGV4YW1wbGUsIHdlIGNvdWxkIGJ1aWxkIHVwIHRvIGNyZWF0aW5nIHNvbWUgaW5jcmVkaWJseSBjb21wbGV4IGZ1bmN0aW9ucyB3aXRoIGN1c3RvbSBjb250cm9sIGZsb3dzIHRvIGVmZmljaWVudGx5IGhhbmRsZSBvdXIgZGF0YSBhbmQgZG93bnN0cmVhbSBhbmFseXNpcyBpbiBSLiBJdCBtYXkgd2VsbCBiZSB1c2VmdWwgZm9yIHRoaW5ncyBzdWNoIGFzIGxvb2tpbmcgYXQgZGF0YSB0byBzZWUgaWYgaXQgY29udGFpbnMgaGVhZGVycyBiZWZvcmUgcmVtb3ZpbmcgdGhlbSwgb3IgYXNzZXNzaW5nIHRoZSBsZW5ndGggb2YgYSBkYXRhIHNldCBiZWZvcmUgcGVyZm9ybWluZyBhIGZ1bmN0aW9uIG9uIGl0LiAKCiMgTGlzdHMgaW4gUgoKTm93LCB3ZSd2ZSBoYWQgYSB3aGlzdGxlIHN0b3AgdG91ciBvZiBmdW5jdGlvbnMsIG9idmlvdXNseSB0aGlzIGlzIG5vdCB0aGUgZnVsbCBleHRlbnQgb2YgdGhlaXIgZnVuY3Rpb25hbGl0eSwgYnV0IGl0J3MgdGltZSB0byBtb3ZlIG9uIHRvIGxpc3RzLiBXZSd2ZSBub3QgcmVhbGx5IG1lbnRpb25lZCBsaXN0cyBzbyBmYXIsIG90aGVyIHRoYW4gdmVyeSBicmllZmx5IGluIHNvbWUgb2YgdGhlIGJlZ2lubmVyIHNlc3Npb25zLiBUbyByZWNhcCwgdGhlcmUgYXJlIDQgbWFpbiBkYXRhIHN0cnVjdHVyZXMgaW4gUiAtIHZlY3RvcnMsIG1hdHJpY2llcywgZGF0YS5mcmFtZXMsIGFuZCBsaXN0cy4gCgpBIGxpc3QgaXMgYSBzcGVjaWFsIGZvcm0gb2YgZGF0YSBzdHJ1Y3R1cmUgd2hpY2ggYWxsb3dzIHlvdSB0byBjb250YWluIG9iamVjdHMgb2YgZGlmZmVyZW50IGxlbmd0aHMgd2l0aGluIGl0LiBUaGV5IGFyZSBhIGxpdHRsZSBtb3JlIGNvbXBsaWNhdGVkIHRoYW4gdGhlIG90aGVyIGRhdGEgc3RydWN0dXJlcyB3ZSBjb3ZlcmVkIGJlZm9yZSAtIHBhcnRseSBiZWNhdXNlIGEgZGF0YS5mcmFtZSBpcyBib3RoIGEgc3BlY2lhbCB0eXBlIG9mIGxpc3QsIGFuZCBjYW4gYmUgY29udGFpbmVkIHdpdGhpbiBhIGxpc3QhIEluIGEgZGF0YS5mcmFtZSwgZWFjaCBjb21wb25lbnQgcGFydCAob3IgY29sdW1uKSBtdXN0IGJlIHRoZSBzYW1lIGxlbmd0aCAtIHRoaXMgaXMgbm90IHRydWUgb2YgYSBsaXN0LgoKVGhleSBhcmUgcXVpdGUgY29tcGxpY2F0ZWQgb24gZmlyc3QgZ2xhbmNlLCBhbmQgb2Z0ZW4gYXJlIG5vdCB0YXVnaHQgYXQgYWxsIGluIFIgY291cnNlcyAtIEkgd2FzIG5ldmVyIGZvcm1hbGx5IHRhdWdodCB3aGF0IGEgbGlzdCB3YXMgb3IgaG93IG9uIGVhcnRoIHRvIHVzZSBvbmUsIGFuZCBJIGhhZCB0byB0cnkgYW5kIHdvcmsgaXQgb3V0IGZvciBteXNlbGYuIExpc3RzIGFyZSBwcm9iYWJseSB0aGUgZm9ybSBvZCBkYXRhIHN0cnVjdHVyZSB0aGF0IEkgdXNlIHRoZSBsZWFzdCBpbiBSLCBzaW1wbHkgYmVjYXVzZSBJIG5ldmVyIGdvdCBpbnRvIHRoZSBoYWJpdCBvZiB1c2luZyB0aGVtLiBOb3csIGxldCdzIG1ha2UgYSBsaXN0IGFuZCBzZWUgaG93IHRoZXkgd29yaywgYW5kIGZpZ3VyZSBvdXQgaG93IHRvIGFjY2VzcyBzdHVmZiB3aXRoaW4gdGhlbS4gRmlyc3QsIHdlJ2xsIGNyZWF0ZSB0aHJlZSB2ZWN0b3JzIChvbmUgY2hhcmFjdGVyLCBvbmUgbnVtZXJpYywgYW5kIG9uZSBsb2dpY2FsKSwgYW5kIGNvbWJpbmUgdGhlbSB3aXRoIHRoZSBgbGlzdCgpYCBmdW5jdGlvbi4KCmBgYHtyfQpuaW50ZW5kbyA8LSBjKCJNYXJpbyIsICJMdWlnaSIsICJQZWFjaCIpCm51bWJlcnMgPC0gMToxMDAKbG9naWMgPC0gYyhUUlVFLCBGQUxTRSwgRkFMU0UsIFRSVUUpCgpteV9saXN0IDwtIGxpc3QobmludGVuZG8sIG51bWJlcnMsIGxvZ2ljKQpgYGAKTm93LCB3ZSBoYXZlIG91ciBsaXN0LiBXZSBjYW4gcHJpbnQgaXQgdG8gdGhlIHNjcmVlbiBieSB0eXBpbmcgdGhlIG5hbWUgb2Ygb3VyIGxpc3QsIGFuZCBpdCdsbCBwcmludCBldmVyeXRoaW5nIG91dC4KCmBgYHtyfQpteV9saXN0CmBgYApGcm9tIHRoaXMsIHdlIGNhbiBjbGVhcmx5IHNlZSB0aGF0IHRoZSBvYmplY3RzIGNvbnRhaW5lZCB3aXRoaW4gdGhlIGxpc3QgYXJlIG9mIGRpZmZlcmVudCBsZW5ndGhzIC0gbmludGVuZG8gaGFzIGEgbGVuZ3RoIG9mIDMsIG51bWJlcnMgaGFzIGEgbGVuZ3RoIG9mIDEwMCwgYW5kIGxvZ2ljIGhhcyBhIGxlbmd0aCBvZiA0LgoKU28sIGhvdyBkbyB3ZSBhY2Nlc3MgdGhlIGxpc3Q/IEl0IGNhbiBzZWVtIGNvbXBsaWNhdGVkLCBidXQgYWN0dWFsbHkgcHJpbnRpbmcgaXQgdG8gdGhlIHNjcmVlbiBoYXMgZ2l2ZW4gdXMgbG90cyBvZiBpbmZvcm1hdGlvbi4gV2UgY2FuIHVzZSBzcXVhcmUgYnJhY2tldHMgYFtdYCB0byBjaG9vc2Ugb2JqZWN0cy4gV2UgY2FuIGFsc28gYWNjZXNzIGVsZW1lbnRzIHdpdGggdGhlaXIgbmFtZXMsIHByb3ZpZGVkIHdlIGhhdmUgZ2l2ZW4gdGhlbSBuYW1lcywgYnV0IHdlIHdpbGwgY29tZSBiYWNrIHRvIHRoYXQuCgpMZXQncyB0cnkgYW5kIHNlbGVjdCB0aGUgZmlyc3QgdmVjdG9yIGVsZW1lbnQgb2Ygb3VyIGxpc3QuIFdlIG1pZ2h0IHRyeSBhbmQgYWNjZXNzIGl0IHdpdGg6CgpgYGB7cn0KbXlfbGlzdFsxXQpgYGAKCldoaWxzdCB0aGlzIGRvZXMgcmV0dXJuIHdoYXQgd2Ugd2FudCBpdCB0bywgdGhpcyBhY3R1YWxseSBpc24ndCBpbiB0aGUgdmVjdG9yIGNsYXNzIHRoYXQgd2UgY3JlYXRlZCB0aGUgbGlzdCB3aXRoLiBXZSBjYW4gY2hlY2sgd2l0aCB0aGUgYGNsYXNzKClgIGZ1bmN0aW9uOgoKYGBge3J9CmNsYXNzKG15X2xpc3RbMV0pCmBgYAoKV2UgY2FuIHNlZSBoZXJlIHRoYXQgdGhlIG9iamVjdCBoYXMgcmV0YWluZWQgaXQncyBsaXN0IGNsYXNzLCBhbmQgaGFzIHRha2VuIHRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBsaXN0LCBidXQgbm90IHRoZSB2ZWN0b3IgaXRzZWxmLiBXZSBjYW4gYWNjZXNzIHRoZSB2ZWN0b3Igd2l0aGluIHRoZSBsaXN0IHdpdGggZG91YmxlIHNxdWFyZSBicmFja2V0cyBgW1tdXWAsIHRoZSBjbHVlIGlzIGluIHRoZSBkaXNwbGF5IG9mIHRoZSBsaXN0IQoKYGBge3J9Cm15X2xpc3RbWzFdXQoKY2xhc3MobXlfbGlzdFtbMV1dKQpgYGAKCldoZW4gd2UgdmVyaWZ5IHdoYXQgd2UncmUgZG9pbmcgd2l0aCBgY2xhc3MoKWAsIHdlIGNhbiBzZWUgdGhhdCB3ZSdyZSBnZXR0aW5nIHRoZSBvcmlnaW5hbCBjaGFyYWN0ZXIgdmVjdG9yIHN0b3JlZCB3aXRoaW4gdGhlIGxpc3QuIFRoaXMgaXMgYSBiaXQgY29tcGxleCBhbmQgaGFuZC13YXZ5LCBidXQgYmFzaWNhbGx5IHJlbWVtYmVyIHRoYXQgYFtbXV1gIGFsbG93cyB5b3UgdG8gYWNjZXNzIHRoZSBlbGVtZW50IGZyb20gd2l0aGluIHRoZSBsaXN0IGluIGl0cyBuYXRpdmUgZm9ybSwgd2hlcmVhcyBgW11gIGdpdmVzIHlvdSB0aGUgZWxlbWVudCBvZiB0aGUgbGlzdCwgd2hpbHN0IHJldGFpbmluZyBpdCdzIGxpc3QgY2xhc3MuCgpCZSBhd2FyZSB0aGF0IHRoZSB3YXkgd2UgYWNjZXNzIGxpc3RzIHdpdGggYFtdYCBpcyBkaWZmZXJlbnQgdGhhbiB2ZWN0b3JzLiBGb3IgZXhhbXBsZSwgaWYgd2Ugd2VyZSB0byB0eXBlIGBteV9saXN0WzE6Ml1gIHdlIGdldCB0aGUgZmlyc3QgdHdvIGVsZW1lbnRzIG9mIHRoZSBsaXN0LCBidXQgYG15X2xpc3RbWzE6Ml1dYCBnaXZlcyB5b3UgdGhlIHNlY29uZCBlbGVtZW50IG9mIHRoZSBmaXJzdCBiaXQgb2YgdGhlIGxpc3Q6CgpgYGB7cn0KbXlfbGlzdFsxOjJdCgpteV9saXN0W1sxOjJdXQpgYGAKWW91IGNhbiBhY2Nlc3MgYml0cyBvZiBsaXN0cyBhcyBhYm92ZSwgb3IgcGVyaGFwcyBtb3JlIGludHVpdGl2ZWx5IGFuZCBsZXNzIGNvbmZ1c2luZ2x5LCBieSBjb21iaW5pbmcgZG91YmxlIGFuZCBzaW5nbGUgc3F1YXJlIGJyYWNrZXRzCgpgYGB7cn0KbXlfbGlzdFtbMV1dWzJdICMgVGhpcyBhY2Nlc3NlcyB0aGUgMm5kIGl0ZW0gb2YgdGhlIDFzdCBsaXN0IGVsZW1lbnQuCmBgYAoKWW91IGNhbiBhbHNvIHVzZSBuYW1lcyB0byBhY2Nlc3MgbGlzdCBlbGVtZW50cyBpbiBhIHdheSB0aGF0IGlzIGVxdWl2YWxlbnQgdG8gaG93IGEgZGF0YWZyYW1lIHdvdWxkIHdvcmsuIEluIG9yZGVyIHRvIGRvIHRoaXMsIGhvd2V2ZXIsIHlvdSBtdXN0IHNwZWNpZnkgdGhlIG5hbWVzIHdoZW4geW91J3JlIGNyZWF0aW5nIHRoZSBsaXN0LCBsaWtlIHRoaXM6CgpgYGB7cn0KbXlfbGlzdCA8LSBsaXN0KG5pbnRlbmRvID0gbmludGVuZG8sIG51bWJlcnMgPSBudW1iZXJzLCBsb2dpYyA9IGxvZ2ljKQpgYGAKSWYgd2UgcHJpbnQgdGhlIGxpc3QgYWdhaW4sIHlvdSdsbCBzZWUgdGhhdCB0aGUgW1sxXV0sIFtbMl1dLCBhbmQgW1szXV0gaGF2ZSBiZWVuIHJlcGxhY2VkIGJ5ICRuaW50ZW5kbywgJG51bWJlcnMsIGFuZCAkbG9naWM6CmBgYHtyfQpteV9saXN0CmBgYApOb3cgeW91IGNhbiBhY2Nlc3MgeW91ciBsaXN0IHVzaW5nIHRoZSBuYW1lcywgYnV0IG5vdGUgdGhhdCBqdXN0IGxpa2UgYSBkYXRhZnJhbWUsIGBteV9saXN0W1sxXV1gIHdpbGwgc3RpbGwgd29yawoKYGBge3J9Cm15X2xpc3QkbmludGVuZG8KCm15X2xpc3RbWzFdXQpgYGAKCiMjIFdoeSBhcmUgbGlzdHMgaW1wb3J0YW50PwoKSXQgcGVyaGFwcyBpc24ndCBpbW1lZGlhdGVseSBvYnZpb3VzIHdoeSBsaXN0cyBhcmUgaW1wb3J0YW50LCBidXQgd2Ugd2lsbCB0YWxrIG1vcmUgYWJvdXQgdGhpcyBpbiB0aGUgbmV4dCBzZXNzaW9uLiBJdCdzIHVzZWZ1bCBmb3IgeW91IHRvIGtub3cgaG93IHRvIHVzZSB0aGVtLCBhcyB0aGV5IHdpbGwgbWFrZSBSIG1vcmUgdXNlZnVsIHRvIHlvdS4KCkJyaWVmbHksIGxpc3RzIGNhbiBiZSBoZWxwZnVsIGlmIHlvdSBhcmUgd29ya2luZyBvbiBsb3RzIG9mIGRhdGFmcmFtZXMvdGliYmxlcyBhdCB0aGUgc2FtZSB0aW1lLCBhcyB5b3UgY2FuIHN0b3JlIHRoZW0gd2l0aGluIGEgbGlzdC4gVGhlIHZlcnNhdGlsaXR5IG9mIHRoaXMgd2lsbCBiZWNvbWUgY2xlYXJlciBuZXh0IHRpbWUgd2hlbiB3ZSdyZSB0YWxraW5nIGFib3V0IHRoZSBhcHBseSBmYW1pbHkgb2YgZnVuY3Rpb25zLCBgc2FwcGx5KClgLCBgbGFwcGx5KClgLCBhbmQgYGFwcGx5KClgLgoKIyBTdW1tYXJ5CgpTbywgdG9kYXkgd2UgaGF2ZSBsZWFybmVkIGFib3V0IGNvbnRyb2wgZmxvdyB3aXRoIGBmb3JgLCBgaWZgLCBgZWxzZWAsIGFuZCBgaWZlbHNlKClgLCBhbmQgaG93IHRoZXNlIGFyZSB1c2VkIHRvIGNvbnRyb2wgdGhlIGZsb3cgb2YgZGF0YSB0aHJvdWdoIGEgc2V0IG9mIGZ1bmN0aW9ucywgZGVwZW5kaW5nIG9uIHdoZXRoZXIgY29uZGl0aW9ucyBhcmUgbWV0LiAKCldlJ3ZlIGxlYXJuZWQgaG93IHRvIHdyaXRlIG91ciBvd24gZnVuY3Rpb25zLCBpbmNsdWRpbmcgd2l0aCBtdWx0aXBsZSBhcmd1bWVudHMgYW5kIGRlZmF1bHRzLCBhbmQgaGF2ZSBjb21iaW5lZCB0aGlzIHdpdGggb3VyIG5ldyBrbm93bGVkZ2Ugb2YgY29udHJvbCBmbG93LgoKRmluYWxseSwgd2UgdG91Y2hlZCBvbiBsaXN0cyB3aGljaCBmZWVkcyBuaWNlbHkgaW50byB0aGUgYXBwbHkgc2V0IG9mIGZ1bmN0aW9ucyB0aGF0IHdlJ2xsIGxvb2sgYXQgaW4gbW9yZSBkZXRhaWwgb24gVGh1cnNkYXkuIFdlIGNhbiB1c2UgYHNhcHBseSgpYCwgYGxhcHBseSgpYCBhbmQgYGFwcGx5KClgIHRvIGVmZmljaWVudGx5IHByb2Nlc3MgdmVjdG9ycyBpbiBSLCBhbmQgd2UnbGwgbGVhcm4gbW9yZSBhYm91dCB0aGUgcHJpbmNpcGxlcyBvZiBwcm9wZXIgc2NyaXB0aW5nLgoKCgo=