In this lab, we will introduce some simple R commands.
The best way to learn a new language is to try out the commands.
R can be downloaded from CRAN
website.
I recommend that you run R within an integrated development environment
(IDE) such as RStudio, which can be freely downloaded from Posit website.
The RStudio website also provides a cloud-based version of R, which does
not require installing any software.
Basic commands
R uses functions to perform operations. To run a function called
funcname, we type funcname(input1, input2), where the inputs (or
arguments) input1 and input2 tell R how to run the function. A function
can have any number of inputs. For example, to create a vector of
numbers, we use the function c() (for concatenate). Any numbers inside
the parentheses are joined together. The following command instructs R
to join together the numbers 1, 3, 2, and 5, and to save them as a
vector named x. When we type x, it gives us back the vector.
x <- c(1, 3, 2, 5)
x
[1] 1 3 2 5
Note that the > is not part of the command; rather, it is printed
by R to indicate that it is ready for another command to be entered. We
can also save things using = rather than <-:
x = c(1, 6, 2)
y = c(1, 4, 3)
x
[1] 1 6 2
Hitting the up arrow multiple times will display the previous
commands, which can then be edited. This is useful since one often
wishes to repeat a similar command. In addition, typing ?funcname will
always cause R to open a new help file window with additional
information about the function funcname(). We can tell R to add two sets
of numbers together. It will then add the first number from x to the
first number from y, and so on. However, x and y should be the same
length. We can check their length using the length() function.
length(x)
[1] 3
length(y)
[1] 3
length(y)
[1] 3
x+y
[1] 2 10 5
The ls() function allows us to look at a list of all of the objects,
such as data and functions, that we have saved so far. The rm() function
can be used to delete any that we don’t want.
ls()
[1] "die" "magic" "result" "simple_math" "x" "x_values" "x3" "y" "y_values"
rm(x, y)
ls()
[1] "die" "magic" "result" "simple_math" "x_values" "x3" "y_values"
It’s also possible to remove all objects at once:
rm(list = ls())
The matrix() function can be used to create a matrix of numbers.
Before we use the matrix() function, we can learn more about it:
?matrix
The help file reveals that the matrix() function takes a number of
inputs, but for now we focus on the first three: the data (the entries
in the matrix), the number of rows, and the number of columns. First, we
create a simple matrix.
x <- matrix(data = c(1, 2, 3, 4), nrow = 2, ncol = 2)
x
[,1] [,2]
[1,] 1 3
[2,] 2 4
Note that we could just as well omit typing data=, nrow=, and ncol=
in the matrix() command above: that is, we could just type
x <- matrix(c(1, 2, 3, 4), 2, 2)
and this would have the same effect. However, it can sometimes be
useful to specify the names of the arguments passed in, since otherwise
R will assume that the function arguments are passed into the function
in the same order that is given in the function’s help file. As this
example illustrates, by default R creates matrices by successively
filling in columns. Alternatively, the byrow = TRUE option can be used
to populate the matrix in order of the rows.
matrix(c(1, 2, 3, 4), 2, 2, byrow = TRUE)
[,1] [,2]
[1,] 1 2
[2,] 3 4
Notice that in the above command we did not assign the matrix to a
value such as x. In this case the matrix is printed to the screen but is
not saved for future calculations. The sqrt() function returns the
square root of each element of a vector or matrix. The command x2̂ raises
each element of x to the power 2; any powers are possible, including
fractional or negative powers.
sqrt(x)
[,1] [,2]
[1,] 1.000000 1.732051
[2,] 1.414214 2.000000
The rnorm() function generates a vector of random normal variables,
with first argument n the sample size. Each time we call this function,
we will get a different answer. Here we create two correlated sets of
numbers, x and y, and use the cor() function to compute the correlation
between them.
x <- rnorm(50)
y <- x + rnorm(50, mean = 50, sd = .1)
cor(x, y)
[1] 0.9925745
By default, rnorm() creates standard normal random variables with a
mean of 0 and a standard deviation of 1. However, the mean and standard
deviation can be altered using the mean and sd arguments, as illustrated
above. Sometimes we want our code to reproduce the exact same set of
random numbers; we can use the set.seed() function to do this. The
set.seed() function takes an (arbitrary) integer argument.
set.seed(1303)
rnorm(50)
[1] -1.1439763145 1.3421293656 2.1853904757 0.5363925179 0.0631929665 0.5022344825 -0.0004167247 0.5658198405 -0.5725226890
[10] -1.1102250073 -0.0486871234 -0.6956562176 0.8289174803 0.2066528551 -0.2356745091 -0.5563104914 -0.3647543571 0.8623550343
[19] -0.6307715354 0.3136021252 -0.9314953177 0.8238676185 0.5233707021 0.7069214120 0.4202043256 -0.2690521547 -1.5103172999
[28] -0.6902124766 -0.1434719524 -1.0135274099 1.5732737361 0.0127465055 0.8726470499 0.4220661905 -0.0188157917 2.6157489689
[37] -0.6931401748 -0.2663217810 -0.7206364412 1.3677342065 0.2640073322 0.6321868074 -1.3306509858 0.0268888182 1.0406363208
[46] 1.3120237985 -0.0300020767 -0.2500257125 0.0234144857 1.6598706557
We use set.seed() throughout the labs whenever we perform
calculations involving random quantities. In general this should allow
the user to reproduce our results. However, as new versions of R become
available, small discrepancies may arise between this document and the
output from R. The mean() and var() functions can be used to compute the
mean and variance of a vector of numbers. Applying sqrt() to the output
of var() will give the standard deviation. Or we can simply use the sd()
function.
set.seed(3)
y <- rnorm(100)
mean(y)
[1] 0.01103557
var(y)
[1] 0.7328675
sqrt(var(y))
[1] 0.8560768
sd(y)
[1] 0.8560768
Graphics
The plot() function is the primary way to plot data in R. For
instance, plot(x, y) produces a scatterplot of the numbers in x versus
the numbers in y. There are many additional options that can be passed
in to the plot() function. For example, passing in the argument xlab
will result in a label on the x-axis. To find out more information about
the plot() function, type ?plot. plot()
x <- rnorm(100)
y <- rnorm(100)
plot(x, y)
plot(x, y, xlab = "this is the x-axis",
ylab = "this is the y-axis", main = "Plot of X vs Y")
We will often want to save the output of an R plot. The command that
we use to do this will depend on the file type that we would like to
create. For instance, to create a pdf, we use the pdf() function, and to
create a jpeg, we use the jpeg() function.
pdf("Figure.pdf")
plot(x, y, col = "green")
The function dev.off() indicates to R that we are done creating the
plot. Alternatively, we can simply copy the plot window and paste it
into an appropriate file type, such as a Word document.
dev.off()
The function seq() can be used to create a sequence of numbers. For
instance, seq(a, b) makes a vector of integers between a and b. There
are manyotheroptions:forinstance,seq(0, 1, length = 10)makesasequence of
10 numbers that are equally spaced between 0 and 1. Typing 3:11 is a
shorthand for seq(3, 11) for integer arguments.
x <- seq(1, 10)
x
x <- 1:10
x
x <- seq(-pi, pi, length = 50)
We will now create some more sophisticated plots. The contour() func-
tion produces a contour plot in order to represent three-dimensional
data; it is like a topographical map. It takes three arguments: 1. A
vector of the x values (the first dimension), 2. A vector of the y
values (the second dimension), and 3. A matrix whose elements correspond
to the z value (the third dimen- sion) for each pair of (x, y)
coordinates.
As with the plot() function, there are many other inputs that can be
used to fine-tune the output of the contour() function. To learn more
about these, take a look at the help file by typing ?contour.
y <- x
f <- outer(x, y, function(x, y) cos(y) / (1 + x^2))
contour(x, y, f)
contour(x, y, f, nlevels = 45, add = T)
fa <- (f - t(f)) / 2
contour(x, y, fa, nlevels = 15)
The image() function works the same way as contour(), except that it
produces a color-coded plot whose colors depend on the z value. This is
known as a heatmap, and is sometimes used to plot temperature in weather
forecasts.Alternatively,persp()canbeusedtoproduceathree-dimensional
plot. The arguments theta and phi control the angles at which the plot
is viewed.
image(x, y, fa)
persp(x, y, fa)
persp(x, y, fa, theta=30)
persp(x, y, fa, theta=30, phi=20)
persp(x, y, fa, theta=30, phi=50)
persp(x, y, fa, theta=30, phi=70)
Indexing data
We often wish to examine part of a set of data. Suppose that our data
is stored in the matrix A.
A <- matrix(1:16, 4, 4)
A
Then, typing
A[2, 3]
will select the element corresponding to the second row and the third
col- umn. The first number after the open-bracket symbol [ always refers
to the row, and the second number always refers to the column. We can
also select multiple rows and columns at a time, by providing vectors as
the indices.
A[c(1, 3), c(2, 4)]
A[1:3, 2:4]
A[1:2, ]
A[, 1:2]
The last two examples include either no index for the columns or no
index for the rows. These indicate that R should include all columns or
all rows, respectively. R treats a single row or column of a matrix as a
vector.
A[1, ]
The use of a negative sign - in the index tells R to keep all rows or
columns except those indicated in the index.
A[-c(1, 3), ]
A[-c(1, 3), -c(1, 3, 4)]
The dim() function outputs the number of rows followed by the number
of columns of a given matrix.
dim(A)
LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIFIiCmF1dGhvcjogTmF5ZWwgQmV0dGFjaGUKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKSW4gdGhpcyBsYWIsIHdlIHdpbGwgaW50cm9kdWNlIHNvbWUgc2ltcGxlIFIgY29tbWFuZHMuIFwKVGhlIGJlc3Qgd2F5IHRvIGxlYXJuIGEgbmV3IGxhbmd1YWdlIGlzIHRvIHRyeSBvdXQgdGhlIGNvbW1hbmRzLiBcClIgY2FuIGJlIGRvd25sb2FkZWQgZnJvbSBbQ1JBTiB3ZWJzaXRlXShodHRwOi8vY3Jhbi5yLXByb2plY3Qub3JnLykuXApJIHJlY29tbWVuZCB0aGF0IHlvdSBydW4gUiB3aXRoaW4gYW4gaW50ZWdyYXRlZCBkZXZlbG9wbWVudCBlbnZpcm9ubWVudCAoSURFKSBzdWNoIGFzIFJTdHVkaW8sIHdoaWNoIGNhbiBiZSBmcmVlbHkgZG93bmxvYWRlZCBmcm9tIFtQb3NpdCB3ZWJzaXRlXShodHRwczovL3Bvc2l0LmNvL2Rvd25sb2Fkcy8pLsKgXApUaGUgUlN0dWRpbyB3ZWJzaXRlIGFsc28gcHJvdmlkZXMgYSBjbG91ZC1iYXNlZCB2ZXJzaW9uIG9mIFIsIHdoaWNoIGRvZXMgbm90IHJlcXVpcmUgaW5zdGFsbGluZyBhbnkgc29mdHdhcmUuXAoKIyBCYXNpYyBjb21tYW5kcwoKUiB1c2VzIGZ1bmN0aW9ucyB0byBwZXJmb3JtIG9wZXJhdGlvbnMuIFRvIHJ1biBhIGZ1bmN0aW9uIGNhbGxlZCBmdW5jbmFtZSwgd2UgdHlwZSBmdW5jbmFtZShpbnB1dDEsIGlucHV0MiksIHdoZXJlIHRoZSBpbnB1dHMgKG9yIGFyZ3VtZW50cykgaW5wdXQxIGFuZCBpbnB1dDIgdGVsbCBSIGhvdyB0byBydW4gdGhlIGZ1bmN0aW9uLiBBIGZ1bmN0aW9uIGNhbiBoYXZlIGFueSBudW1iZXIgb2YgaW5wdXRzLiBGb3IgZXhhbXBsZSwgdG8gY3JlYXRlIGEgdmVjdG9yIG9mIG51bWJlcnMsIHdlIHVzZSB0aGUgZnVuY3Rpb24gYygpIChmb3IgY29uY2F0ZW5hdGUpLiBBbnkgbnVtYmVycyBpbnNpZGUgdGhlIHBhcmVudGhlc2VzIGFyZSBqb2luZWQgdG9nZXRoZXIuIFRoZSBmb2xsb3dpbmcgY29tbWFuZCBpbnN0cnVjdHMgUiB0byBqb2luIHRvZ2V0aGVyIHRoZSBudW1iZXJzIDEsIDMsIDIsIGFuZCA1LCBhbmQgdG8gc2F2ZSB0aGVtIGFzIGEgdmVjdG9yIG5hbWVkIHguIFdoZW4gd2UgdHlwZSB4LCBpdCBnaXZlcyB1cyBiYWNrIHRoZSB2ZWN0b3IuCgpgYGB7cn0KeCA8LSBjKDEsIDMsIDIsIDUpIAp4CmBgYAoKTm90ZSB0aGF0IHRoZSA+IGlzIG5vdCBwYXJ0IG9mIHRoZSBjb21tYW5kOyByYXRoZXIsIGl0IGlzIHByaW50ZWQgYnkgUiB0byBpbmRpY2F0ZSB0aGF0IGl0IGlzIHJlYWR5IGZvciBhbm90aGVyIGNvbW1hbmQgdG8gYmUgZW50ZXJlZC4gV2UgY2FuIGFsc28gc2F2ZSB0aGluZ3MgdXNpbmcgPSByYXRoZXIgdGhhbiA8LToKCmBgYHtyfQp4ID0gYygxLCA2LCAyKQp5ID0gYygxLCA0LCAzKQp4CmBgYAoKSGl0dGluZyB0aGUgdXAgYXJyb3cgbXVsdGlwbGUgdGltZXMgd2lsbCBkaXNwbGF5IHRoZSBwcmV2aW91cyBjb21tYW5kcywgd2hpY2ggY2FuIHRoZW4gYmUgZWRpdGVkLiBUaGlzIGlzIHVzZWZ1bCBzaW5jZSBvbmUgb2Z0ZW4gd2lzaGVzIHRvIHJlcGVhdCBhIHNpbWlsYXIgY29tbWFuZC4gSW4gYWRkaXRpb24sIHR5cGluZyA/ZnVuY25hbWUgd2lsbCBhbHdheXMgY2F1c2UgUiB0byBvcGVuIGEgbmV3IGhlbHAgZmlsZSB3aW5kb3cgd2l0aCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBmdW5jdGlvbiBmdW5jbmFtZSgpLgpXZSBjYW4gdGVsbCBSIHRvIGFkZCB0d28gc2V0cyBvZiBudW1iZXJzIHRvZ2V0aGVyLiBJdCB3aWxsIHRoZW4gYWRkIHRoZSBmaXJzdCBudW1iZXIgZnJvbSB4IHRvIHRoZSBmaXJzdCBudW1iZXIgZnJvbSB5LCBhbmQgc28gb24uIEhvd2V2ZXIsIHggYW5kIHkgc2hvdWxkIGJlIHRoZSBzYW1lIGxlbmd0aC4gV2UgY2FuIGNoZWNrIHRoZWlyIGxlbmd0aCB1c2luZyB0aGUgbGVuZ3RoKCkgZnVuY3Rpb24uCgpgYGB7cn0KbGVuZ3RoKHgpCmBgYAoKYGBge3J9Cmxlbmd0aCh5KQpgYGAKCmBgYHtyfQpsZW5ndGgoeSkKYGBgCgpgYGB7cn0KeCt5CmBgYApUaGUgbHMoKSBmdW5jdGlvbiBhbGxvd3MgdXMgdG8gbG9vayBhdCBhIGxpc3Qgb2YgYWxsIG9mIHRoZSBvYmplY3RzLCBzdWNoIGFzIGRhdGEgYW5kIGZ1bmN0aW9ucywgdGhhdCB3ZSBoYXZlIHNhdmVkIHNvIGZhci4gVGhlIHJtKCkgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZGVsZXRlIGFueSB0aGF0IHdlIGRvbuKAmXQgd2FudC4KYGBge3J9CmxzKCkKYGBgCgpgYGB7cn0Kcm0oeCwgeSkKYGBgCgpgYGB7cn0KbHMoKQpgYGAKSXTigJlzIGFsc28gcG9zc2libGUgdG8gcmVtb3ZlIGFsbCBvYmplY3RzIGF0IG9uY2U6CmBgYHtyfQpybShsaXN0ID0gbHMoKSkKYGBgClRoZSBtYXRyaXgoKSBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYSBtYXRyaXggb2YgbnVtYmVycy4gQmVmb3JlIHdlIHVzZSB0aGUgbWF0cml4KCkgZnVuY3Rpb24sIHdlIGNhbiBsZWFybiBtb3JlIGFib3V0IGl0OgpgYGB7cn0KP21hdHJpeApgYGAKVGhlIGhlbHAgZmlsZSByZXZlYWxzIHRoYXQgdGhlIG1hdHJpeCgpIGZ1bmN0aW9uIHRha2VzIGEgbnVtYmVyIG9mIGlucHV0cywgYnV0IGZvciBub3cgd2UgZm9jdXMgb24gdGhlIGZpcnN0IHRocmVlOiB0aGUgZGF0YSAodGhlIGVudHJpZXMgaW4gdGhlIG1hdHJpeCksIHRoZSBudW1iZXIgb2Ygcm93cywgYW5kIHRoZSBudW1iZXIgb2YgY29sdW1ucy4gRmlyc3QsIHdlIGNyZWF0ZSBhIHNpbXBsZSBtYXRyaXguCmBgYHtyfQp4IDwtIG1hdHJpeChkYXRhID0gYygxLCAyLCAzLCA0KSwgbnJvdyA9IDIsIG5jb2wgPSAyKQp4CmBgYApOb3RlIHRoYXQgd2UgY291bGQganVzdCBhcyB3ZWxsIG9taXQgdHlwaW5nIGRhdGE9LCBucm93PSwgYW5kIG5jb2w9IGluIHRoZSBtYXRyaXgoKSBjb21tYW5kIGFib3ZlOiB0aGF0IGlzLCB3ZSBjb3VsZCBqdXN0IHR5cGUKCmBgYHtyfQp4IDwtIG1hdHJpeChjKDEsIDIsIDMsIDQpLCAyLCAyKQpgYGAKYW5kIHRoaXMgd291bGQgaGF2ZSB0aGUgc2FtZSBlZmZlY3QuIEhvd2V2ZXIsIGl0IGNhbiBzb21ldGltZXMgYmUgdXNlZnVsIHRvIHNwZWNpZnkgdGhlIG5hbWVzIG9mIHRoZSBhcmd1bWVudHMgcGFzc2VkIGluLCBzaW5jZSBvdGhlcndpc2UgUiB3aWxsIGFzc3VtZSB0aGF0IHRoZSBmdW5jdGlvbiBhcmd1bWVudHMgYXJlIHBhc3NlZCBpbnRvIHRoZSBmdW5jdGlvbiBpbiB0aGUgc2FtZSBvcmRlciB0aGF0IGlzIGdpdmVuIGluIHRoZSBmdW5jdGlvbuKAmXMgaGVscCBmaWxlLiBBcyB0aGlzIGV4YW1wbGUgaWxsdXN0cmF0ZXMsIGJ5IGRlZmF1bHQgUiBjcmVhdGVzIG1hdHJpY2VzIGJ5IHN1Y2Nlc3NpdmVseSBmaWxsaW5nIGluIGNvbHVtbnMuIEFsdGVybmF0aXZlbHksIHRoZSBieXJvdyA9IFRSVUUgb3B0aW9uIGNhbiBiZSB1c2VkIHRvIHBvcHVsYXRlIHRoZSBtYXRyaXggaW4gb3JkZXIgb2YgdGhlIHJvd3MuCmBgYHtyfQptYXRyaXgoYygxLCAyLCAzLCA0KSwgMiwgMiwgYnlyb3cgPSBUUlVFKQpgYGAKTm90aWNlIHRoYXQgaW4gdGhlIGFib3ZlIGNvbW1hbmQgd2UgZGlkIG5vdCBhc3NpZ24gdGhlIG1hdHJpeCB0byBhIHZhbHVlIHN1Y2ggYXMgeC4gSW4gdGhpcyBjYXNlIHRoZSBtYXRyaXggaXMgcHJpbnRlZCB0byB0aGUgc2NyZWVuIGJ1dCBpcyBub3Qgc2F2ZWQgZm9yIGZ1dHVyZSBjYWxjdWxhdGlvbnMuIFRoZSBzcXJ0KCkgZnVuY3Rpb24gcmV0dXJucyB0aGUgc3F1YXJlIHJvb3Qgb2YgZWFjaCBlbGVtZW50IG9mIGEgdmVjdG9yIG9yIG1hdHJpeC4gVGhlIGNvbW1hbmQgeDLMgiByYWlzZXMgZWFjaCBlbGVtZW50IG9mIHggdG8gdGhlIHBvd2VyIDI7IGFueSBwb3dlcnMgYXJlIHBvc3NpYmxlLCBpbmNsdWRpbmcgZnJhY3Rpb25hbCBvciBuZWdhdGl2ZSBwb3dlcnMuCmBgYHtyfQpzcXJ0KHgpCmBgYApUaGUgcm5vcm0oKSBmdW5jdGlvbiBnZW5lcmF0ZXMgYSB2ZWN0b3Igb2YgcmFuZG9tIG5vcm1hbCB2YXJpYWJsZXMsIHdpdGggZmlyc3QgYXJndW1lbnQgbiB0aGUgc2FtcGxlIHNpemUuIEVhY2ggdGltZSB3ZSBjYWxsIHRoaXMgZnVuY3Rpb24sIHdlIHdpbGwgZ2V0IGEgZGlmZmVyZW50IGFuc3dlci4gSGVyZSB3ZSBjcmVhdGUgdHdvIGNvcnJlbGF0ZWQgc2V0cyBvZiBudW1iZXJzLCB4IGFuZCB5LCBhbmQgdXNlIHRoZSBjb3IoKSBmdW5jdGlvbiB0byBjb21wdXRlIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZW0uCmBgYHtyfQp4IDwtIHJub3JtKDUwKQp5IDwtIHggKyBybm9ybSg1MCwgbWVhbiA9IDUwLCBzZCA9IC4xKSAKY29yKHgsIHkpCmBgYApCeSBkZWZhdWx0LCBybm9ybSgpIGNyZWF0ZXMgc3RhbmRhcmQgbm9ybWFsIHJhbmRvbSB2YXJpYWJsZXMgd2l0aCBhIG1lYW4gb2YgMCBhbmQgYSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMS4gSG93ZXZlciwgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBjYW4gYmUgYWx0ZXJlZCB1c2luZyB0aGUgbWVhbiBhbmQgc2QgYXJndW1lbnRzLCBhcyBpbGx1c3RyYXRlZCBhYm92ZS4gU29tZXRpbWVzIHdlIHdhbnQgb3VyIGNvZGUgdG8gcmVwcm9kdWNlIHRoZSBleGFjdCBzYW1lIHNldCBvZiByYW5kb20gbnVtYmVyczsgd2UgY2FuIHVzZSB0aGUgc2V0LnNlZWQoKSBmdW5jdGlvbiB0byBkbyB0aGlzLiBUaGUgc2V0LnNlZWQoKSBmdW5jdGlvbiB0YWtlcyBhbiAoYXJiaXRyYXJ5KSBpbnRlZ2VyIGFyZ3VtZW50LgpgYGB7cn0Kc2V0LnNlZWQoMTMwMykKcm5vcm0oNTApCmBgYApXZSB1c2Ugc2V0LnNlZWQoKSB0aHJvdWdob3V0IHRoZSBsYWJzIHdoZW5ldmVyIHdlIHBlcmZvcm0gY2FsY3VsYXRpb25zIGludm9sdmluZyByYW5kb20gcXVhbnRpdGllcy4gSW4gZ2VuZXJhbCB0aGlzIHNob3VsZCBhbGxvdyB0aGUgdXNlciB0byByZXByb2R1Y2Ugb3VyIHJlc3VsdHMuIEhvd2V2ZXIsIGFzIG5ldyB2ZXJzaW9ucyBvZiBSIGJlY29tZSBhdmFpbGFibGUsIHNtYWxsIGRpc2NyZXBhbmNpZXMgbWF5IGFyaXNlIGJldHdlZW4gdGhpcyBkb2N1bWVudCBhbmQgdGhlIG91dHB1dCBmcm9tIFIuClRoZSBtZWFuKCkgYW5kIHZhcigpIGZ1bmN0aW9ucyBjYW4gYmUgdXNlZCB0byBjb21wdXRlIHRoZSBtZWFuIGFuZCB2YXJpYW5jZSBvZiBhIHZlY3RvciBvZiBudW1iZXJzLiBBcHBseWluZyBzcXJ0KCkgdG8gdGhlIG91dHB1dCBvZiB2YXIoKSB3aWxsIGdpdmUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbi4gT3Igd2UgY2FuIHNpbXBseSB1c2UgdGhlIHNkKCkgZnVuY3Rpb24uCmBgYHtyfQpzZXQuc2VlZCgzKQp5IDwtIHJub3JtKDEwMCkgCm1lYW4oeSkKYGBgCgpgYGB7cn0KdmFyKHkpCmBgYAoKYGBge3J9CnNxcnQodmFyKHkpKQpgYGAKCmBgYHtyfQpzZCh5KQpgYGAKCiMgR3JhcGhpY3MgClRoZSBwbG90KCkgZnVuY3Rpb24gaXMgdGhlIHByaW1hcnkgd2F5IHRvIHBsb3QgZGF0YSBpbiBSLiBGb3IgaW5zdGFuY2UsIHBsb3QoeCwgeSkgcHJvZHVjZXMgYSBzY2F0dGVycGxvdCBvZiB0aGUgbnVtYmVycyBpbiB4IHZlcnN1cyB0aGUgbnVtYmVycyBpbiB5LiBUaGVyZSBhcmUgbWFueSBhZGRpdGlvbmFsIG9wdGlvbnMgdGhhdCBjYW4gYmUgcGFzc2VkIGluIHRvIHRoZSBwbG90KCkgZnVuY3Rpb24uIEZvciBleGFtcGxlLCBwYXNzaW5nIGluIHRoZSBhcmd1bWVudCB4bGFiIHdpbGwgcmVzdWx0IGluIGEgbGFiZWwgb24gdGhlIHgtYXhpcy4gVG8gZmluZCBvdXQgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcGxvdCgpIGZ1bmN0aW9uLCB0eXBlID9wbG90LgpwbG90KCkKYGBge3J9CnggPC0gcm5vcm0oMTAwKQp5IDwtIHJub3JtKDEwMCkKcGxvdCh4LCB5KQpgYGAKCmBgYHtyfQpwbG90KHgsIHksIHhsYWIgPSAidGhpcyBpcyB0aGUgeC1heGlzIiwKeWxhYiA9ICJ0aGlzIGlzIHRoZSB5LWF4aXMiLCBtYWluID0gIlBsb3Qgb2YgWCB2cyBZIikKYGBgCldlIHdpbGwgb2Z0ZW4gd2FudCB0byBzYXZlIHRoZSBvdXRwdXQgb2YgYW4gUiBwbG90LiBUaGUgY29tbWFuZCB0aGF0IHdlIHVzZSB0byBkbyB0aGlzIHdpbGwgZGVwZW5kIG9uIHRoZSBmaWxlIHR5cGUgdGhhdCB3ZSB3b3VsZCBsaWtlIHRvIGNyZWF0ZS4gRm9yIGluc3RhbmNlLCB0byBjcmVhdGUgYSBwZGYsIHdlIHVzZSB0aGUgcGRmKCkgZnVuY3Rpb24sIGFuZCB0byBjcmVhdGUgYSBqcGVnLCB3ZSB1c2UgdGhlIGpwZWcoKSBmdW5jdGlvbi4KCmBgYHtyfQpwZGYoIkZpZ3VyZS5wZGYiKQpgYGAKCmBgYHtyfQpwbG90KHgsIHksIGNvbCA9ICJncmVlbiIpCmBgYApUaGUgZnVuY3Rpb24gZGV2Lm9mZigpIGluZGljYXRlcyB0byBSIHRoYXQgd2UgYXJlIGRvbmUgY3JlYXRpbmcgdGhlIHBsb3QuIEFsdGVybmF0aXZlbHksIHdlIGNhbiBzaW1wbHkgY29weSB0aGUgcGxvdCB3aW5kb3cgYW5kIHBhc3RlIGl0IGludG8gYW4gYXBwcm9wcmlhdGUgZmlsZSB0eXBlLCBzdWNoIGFzIGEgV29yZCBkb2N1bWVudC4KYGBge3J9CmRldi5vZmYoKQpgYGAKVGhlIGZ1bmN0aW9uIHNlcSgpIGNhbiBiZSB1c2VkIHRvIGNyZWF0ZSBhIHNlcXVlbmNlIG9mIG51bWJlcnMuIEZvciBpbnN0YW5jZSwgc2VxKGEsIGIpIG1ha2VzIGEgdmVjdG9yIG9mIGludGVnZXJzIGJldHdlZW4gYSBhbmQgYi4gVGhlcmUgYXJlIG1hbnlvdGhlcm9wdGlvbnM6Zm9yaW5zdGFuY2Usc2VxKDAsIDEsIGxlbmd0aCA9IDEwKW1ha2VzYXNlcXVlbmNlIG9mIDEwIG51bWJlcnMgdGhhdCBhcmUgZXF1YWxseSBzcGFjZWQgYmV0d2VlbiAwIGFuZCAxLiBUeXBpbmcgMzoxMSBpcyBhIHNob3J0aGFuZCBmb3Igc2VxKDMsIDExKSBmb3IgaW50ZWdlciBhcmd1bWVudHMuCmBgYHtyfQp4IDwtIHNlcSgxLCAxMCkgCngKYGBgCgpgYGB7cn0KeCA8LSAxOjEwCngKYGBgCgpgYGB7cn0KeCA8LSBzZXEoLXBpLCBwaSwgbGVuZ3RoID0gNTApCmBgYApXZSB3aWxsIG5vdyBjcmVhdGUgc29tZSBtb3JlIHNvcGhpc3RpY2F0ZWQgcGxvdHMuIFRoZSBjb250b3VyKCkgZnVuYy0gdGlvbiBwcm9kdWNlcyBhIGNvbnRvdXIgcGxvdCBpbiBvcmRlciB0byByZXByZXNlbnQgdGhyZWUtZGltZW5zaW9uYWwgZGF0YTsgaXQgaXMgbGlrZSBhIHRvcG9ncmFwaGljYWwgbWFwLiBJdCB0YWtlcyB0aHJlZSBhcmd1bWVudHM6CjEuIEEgdmVjdG9yIG9mIHRoZSB4IHZhbHVlcyAodGhlIGZpcnN0IGRpbWVuc2lvbiksCjIuIEEgdmVjdG9yIG9mIHRoZSB5IHZhbHVlcyAodGhlIHNlY29uZCBkaW1lbnNpb24pLCBhbmQKMy4gQSBtYXRyaXggd2hvc2UgZWxlbWVudHMgY29ycmVzcG9uZCB0byB0aGUgeiB2YWx1ZSAodGhlIHRoaXJkIGRpbWVuLSBzaW9uKSBmb3IgZWFjaCBwYWlyIG9mICh4LCB5KSBjb29yZGluYXRlcy4gXApBcyB3aXRoIHRoZSBwbG90KCkgZnVuY3Rpb24sIHRoZXJlIGFyZSBtYW55IG90aGVyIGlucHV0cyB0aGF0IGNhbiBiZSB1c2VkIHRvIGZpbmUtdHVuZSB0aGUgb3V0cHV0IG9mIHRoZSBjb250b3VyKCkgZnVuY3Rpb24uIFRvIGxlYXJuIG1vcmUgYWJvdXQgdGhlc2UsIHRha2UgYSBsb29rIGF0IHRoZSBoZWxwIGZpbGUgYnkgdHlwaW5nID9jb250b3VyLgpgYGB7cn0KeSA8LSB4CmYgPC0gb3V0ZXIoeCwgeSwgZnVuY3Rpb24oeCwgeSkgY29zKHkpIC8gKDEgKyB4XjIpKQpjb250b3VyKHgsIHksIGYpCmBgYAoKYGBge3J9CmNvbnRvdXIoeCwgeSwgZiwgbmxldmVscyA9IDQ1LCBhZGQgPSBUKQpgYGAKCmBgYHtyfQpmYSA8LSAoZiAtIHQoZikpIC8gMgpjb250b3VyKHgsIHksIGZhLCBubGV2ZWxzID0gMTUpCmBgYApUaGUgaW1hZ2UoKSBmdW5jdGlvbiB3b3JrcyB0aGUgc2FtZSB3YXkgYXMgY29udG91cigpLCBleGNlcHQgdGhhdCBpdCBwcm9kdWNlcyBhIGNvbG9yLWNvZGVkIHBsb3Qgd2hvc2UgY29sb3JzIGRlcGVuZCBvbiB0aGUgeiB2YWx1ZS4gVGhpcyBpcyBrbm93biBhcyBhIGhlYXRtYXAsIGFuZCBpcyBzb21ldGltZXMgdXNlZCB0byBwbG90IHRlbXBlcmF0dXJlIGluIHdlYXRoZXIgZm9yZWNhc3RzLkFsdGVybmF0aXZlbHkscGVyc3AoKWNhbmJldXNlZHRvcHJvZHVjZWF0aHJlZS1kaW1lbnNpb25hbCBwbG90LiBUaGUgYXJndW1lbnRzIHRoZXRhIGFuZCBwaGkgY29udHJvbCB0aGUgYW5nbGVzIGF0IHdoaWNoIHRoZSBwbG90IGlzIHZpZXdlZC4KYGBge3J9CmltYWdlKHgsIHksIGZhKQpgYGAKCmBgYHtyfQpwZXJzcCh4LCB5LCBmYSkKYGBgCgpgYGB7cn0KcGVyc3AoeCwgeSwgZmEsIHRoZXRhPTMwKQpgYGAKCmBgYHtyfQpwZXJzcCh4LCB5LCBmYSwgdGhldGE9MzAsIHBoaT0yMCkKYGBgCgpgYGB7cn0KcGVyc3AoeCwgeSwgZmEsIHRoZXRhPTMwLCBwaGk9NTApCmBgYAoKYGBge3J9CnBlcnNwKHgsIHksIGZhLCB0aGV0YT0zMCwgcGhpPTcwKQpgYGAKCiMgSW5kZXhpbmcgZGF0YQpXZSBvZnRlbiB3aXNoIHRvIGV4YW1pbmUgcGFydCBvZiBhIHNldCBvZiBkYXRhLiBTdXBwb3NlIHRoYXQgb3VyIGRhdGEgaXMgc3RvcmVkIGluIHRoZSBtYXRyaXggQS4KYGBge3J9CkEgPC0gbWF0cml4KDE6MTYsIDQsIDQpCkEKYGBgClRoZW4sIHR5cGluZwpgYGB7cn0KQVsyLCAzXQpgYGAKd2lsbCBzZWxlY3QgdGhlIGVsZW1lbnQgY29ycmVzcG9uZGluZyB0byB0aGUgc2Vjb25kIHJvdyBhbmQgdGhlIHRoaXJkIGNvbC0gdW1uLiBUaGUgZmlyc3QgbnVtYmVyIGFmdGVyIHRoZSBvcGVuLWJyYWNrZXQgc3ltYm9sIFsgYWx3YXlzIHJlZmVycyB0byB0aGUgcm93LCBhbmQgdGhlIHNlY29uZCBudW1iZXIgYWx3YXlzIHJlZmVycyB0byB0aGUgY29sdW1uLiBXZSBjYW4gYWxzbyBzZWxlY3QgbXVsdGlwbGUgcm93cyBhbmQgY29sdW1ucyBhdCBhIHRpbWUsIGJ5IHByb3ZpZGluZyB2ZWN0b3JzIGFzIHRoZSBpbmRpY2VzLgpgYGB7cn0KQVtjKDEsIDMpLCBjKDIsIDQpXQpgYGAKCmBgYHtyfQpBWzE6MywgMjo0XQpgYGAKCmBgYHtyfQpBWzE6MiwgXQpgYGAKCmBgYHtyfQpBWywgMToyXQpgYGAKVGhlIGxhc3QgdHdvIGV4YW1wbGVzIGluY2x1ZGUgZWl0aGVyIG5vIGluZGV4IGZvciB0aGUgY29sdW1ucyBvciBubyBpbmRleCBmb3IgdGhlIHJvd3MuIFRoZXNlIGluZGljYXRlIHRoYXQgUiBzaG91bGQgaW5jbHVkZSBhbGwgY29sdW1ucyBvciBhbGwgcm93cywgcmVzcGVjdGl2ZWx5LiBSIHRyZWF0cyBhIHNpbmdsZSByb3cgb3IgY29sdW1uIG9mIGEgbWF0cml4IGFzIGEgdmVjdG9yLgpgYGB7cn0KQVsxLCBdCmBgYApUaGUgdXNlIG9mIGEgbmVnYXRpdmUgc2lnbiAtIGluIHRoZSBpbmRleCB0ZWxscyBSIHRvIGtlZXAgYWxsIHJvd3Mgb3IgY29sdW1ucyBleGNlcHQgdGhvc2UgaW5kaWNhdGVkIGluIHRoZSBpbmRleC4KYGBge3J9CkFbLWMoMSwgMyksIF0KYGBgCgpgYGB7cn0KQVstYygxLCAzKSwgLWMoMSwgMywgNCldCmBgYApUaGUgZGltKCkgZnVuY3Rpb24gb3V0cHV0cyB0aGUgbnVtYmVyIG9mIHJvd3MgZm9sbG93ZWQgYnkgdGhlIG51bWJlciBvZiBjb2x1bW5zIG9mIGEgZ2l2ZW4gbWF0cml4LgpgYGB7cn0KZGltKEEpCmBgYA==