Basic calculations
You can use R for basic computations you would perform in a
calculator
# Addition
2-3
[1] -1
# Division
2/3
[1] 0.6666667
# Exponentiation
2^3
[1] 8
# Square root
sqrt(2)
[1] 1.414214
# Logarithms
log(2)
[1] 0.6931472
Cool lines of code, so let us now run a similar chunk of code
log(10)
[1] 2.302585
Well, I thought that log(10) was equal to one. What if we are
actually calculating log based e(2.72)
log(2.72)
[1] 1.000632
Let us compute now some log expressions
log10(10)
[1] 1
Often you will want to test whether something is less than, greater
than or equal to something.
3 == 8
[1] FALSE
3 != 8
[1] TRUE
3 <= 8
[1] TRUE
1==0
[1] FALSE
2==5
[1] FALSE
1==1
[1] TRUE
The logical operators are &
for logical
AND, |
for logical OR,
and !
for NOT. These are some
examples:
# Logical Disjunction (or)
FALSE | FALSE
[1] FALSE
# Logical Conjunction (and)
TRUE & FALSE
[1] FALSE
# Negation
! FALSE
[1] TRUE
# Combination of statements
2 < 3 | 1 == 5
[1] TRUE
Assigning Values to Variables
In R, you create a variable and assign it a value using
<-
as follows
foo <- 2 + 2
foo*3
[1] 12
#Let us now multiply foo by 5
foo*5
[1] 20
fii<-3+4
To see the variables that are currently defined, use ls
(as in “list”)
ls()
[1] "fii" "foo"
To delete a variable, use rm
(as in “remove”)
rm(fii)
ls()
character(0)
Either <-
or =
can be used to assign a
value to a variable, but I prefer <-
because is less
likely to be confused with the logical operator ==
Vectors
The basic type of object in R is a vector, which is an
ordered list of values of the same type. You can create a vector using
the c()
function (as in “concatenate”).
bar <- c(2, 5, 10, 2, 1)
bar
[1] 2 5 10 2 1
baz <- c(2, 2, 3, 3, 3)
baz
[1] 2 2 3 3 3
There are also some functions that will create vectors with regular
patterns, like repeated elements.
# replicate function
rep(2, 5)
[1] 2 2 2 2 2
# consecutive numbers
1:5
[1] 1 2 3 4 5
# sequence from 1 to 10 with a step of 2
seq(1, 10, by=2)
[1] 1 3 5 7 9
seq(1,20,by=3)
[1] 1 4 7 10 13 16 19
rep(1,3)
[1] 1 1 1
Many functions and operators like +
or -
will work on all elements of the vector.
# add vectors
bar + baz
[1] 4 7 13 5 4
# compare vectors
bar == baz
[1] TRUE FALSE FALSE FALSE FALSE
# find length of vector
length(bar)
[1] 5
# find minimum value in vector
min(bar)
[1] 1
# find average value in vector
mean(bar)
[1] 4
You can access parts of a vector by using [
. Recall what
the value is of the vector bar
.
bar
[1] 2 5 10 2 1
# If you want to get the first element:
bar[1]
[1] 2
If you want to get the last element of bar
without
explicitly typing the number of elements of bar
, make use
of the length
function, which calculates the length of a
vector:
bar[length(bar)]
[1] 1
You can also extract multiple values from a vector. For instance to
get the 2nd through 4th values use
bar[c(2, 3, 4)]
Vectors can also be strings or logical values
quxx <- c("a", "b", "cde", "fg")
quxx
[1] "a" "b" "cde" "fg"
Data Frames
In statistical applications, data is often stored as a data frame,
which is like a spreadsheet, with rows as observations and
columns as variables.
To manually create a data frame, use the data.frame()
function.
data.frame(foo = c(1, 2, 3),
bar = c("a", "b", "c"),
baz = c(1.5, 2.5, 3))
NA
Most often you will be using data frames loaded from a file. For
example, load the results of a class survey. The function
load
or read.table
can be used for this.
How to Make a Random Sample
To randomly select a sample use the function sample()
.
The following code selects 5 numbers between 1 and 10 at random (without
duplication)
sample(1:10, size=5)
[1] 4 8 7 2 9
- The first argument gives the vector of data to select elements
from.
- The second argument (
size=
) gives the size of the
sample to select.
Taking a simple random sample from a data frame is only slightly more
complicated, having two steps:
- Use
sample()
to select a sample of size n
from a vector of the row numbers of the data frame.
- Use the index operator
[
to select those rows from the
data frame.
Consider the following example with fake data. First, make
up a data frame with two columns. (LETTERS
is a character
vector of length 26 with capital letters âAâ to âZâ;
LETTERS
is automatically defined and pre-loaded in
R
)
bar <- data.frame(var1 = LETTERS[1:10], var2 = 1:10)
# Check data frame
bar
Suppose you want to select a random sample of size 5. First, define a
variable n
with the size of the sample, i.e. 5
n <- 5
Now, select a sample of size 5 from the vector with 1 to 10 (the
number of rows in bar
). Use the function
nrow()
to find the number of rows in bar
instead of manually entering that number.
Use :
to create a vector with all the integers between 1
and the number of rows in bar
.
samplerows <- sample(1:nrow(bar), size=n)
# print sample rows
samplerows
The variable samplerows
contains the rows of
bar
which make a random sample from all the rows in
bar
. Extract those rows from bar
with
# extract rows
barsample <- bar[samplerows, ]
# print sample
print(barsample)
The code above creates a new data frame called
barsample
with a random sample of rows from
bar
.
In a single line of code:
bar[sample(1:nrow(bar), n), ]
Using Tables
The table()
command allows us to look at tables. Its
simplest usage looks like table(x)
where x
is
a categorical variable.
For example, a survey asks people if they smoke or not. The data
is
Yes, No, No, Yes, Yes
We can enter this into R with the c()
command, and
summarize with the table()
command as follows
x <- c("Yes","No","No","Yes","Yes")
table(x)
x
No Yes
2 3
y<-c("Yes","No","Yes","Yes")
y
[1] "Yes" "No" "Yes" "Yes"
table(y)
y
No Yes
1 3
Numeric measures of center and spread
Suppose, CEO yearly compensations are sampled and the following are
found (in millions)
12 .4 5 2 50 8 3 1 4 0.25
sals <- c(12, .4, 5, 2, 50, 8, 3, 1, 4, 0.25)
# the average
mean(sals)
[1] 8.565
# the variance
var(sals)
[1] 225.5145
# the standard deviation
sd(sals)
[1] 15.01714
# the median
median(sals)
[1] 3.5
# Tukey's five number summary, usefull for boxplots
# five numbers: min, lower hinge, median, upper hinge, max
fivenum(sals)
[1] 0.25 1.00 3.50 8.00 50.00
# summary statistics
summary(sals)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.250 1.250 3.500 8.565 7.250 50.000
How about the mode?
In R we can write our own functions, and a first example of
a function is shown below in order to compute the mode of a
vector of observations x
# Function to find the mode, i.e. most frequent value
getMode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
As an example, we can use the function defined above to find the most
frequent value in te vector baz
# Most frequent value in baz
baz
[1] 2 2 3 3 3
getMode(baz)
[1] 3
bar
[1] 2 5 10 2 1
getMode(bar)
[1] 2
LS0tDQp0aXRsZTogIkZpcnN0IFN0ZXBzIGluIGBSYCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMgQmFzaWMgY2FsY3VsYXRpb25zDQoNCllvdSBjYW4gdXNlIFIgZm9yIGJhc2ljIGNvbXB1dGF0aW9ucyB5b3Ugd291bGQgcGVyZm9ybSBpbiBhIGNhbGN1bGF0b3INCg0KYGBge3J9DQojIEFkZGl0aW9uDQoyLTMNCiMgRGl2aXNpb24NCjIvMw0KIyBFeHBvbmVudGlhdGlvbg0KMl4zIA0KIyBTcXVhcmUgcm9vdA0Kc3FydCgyKQ0KIyBMb2dhcml0aG1zDQpsb2coMikNCmBgYA0KDQpDb29sIGxpbmVzIG9mIGNvZGUsIHNvIGxldCB1cyBub3cgcnVuIGEgc2ltaWxhciBjaHVuayBvZiBjb2RlDQoNCmBgYHtyfQ0KbG9nKDEwKQ0KDQpgYGANCg0KV2VsbCwgSSB0aG91Z2h0IHRoYXQgbG9nKDEwKSB3YXMgZXF1YWwgdG8gb25lLiBXaGF0IGlmIHdlIGFyZSBhY3R1YWxseSBjYWxjdWxhdGluZyBsb2cgYmFzZWQgZSgyLjcyKQ0KDQoNCmBgYHtyfQ0KbG9nKDIuNzIpDQpgYGANCg0KTGV0IHVzIGNvbXB1dGUgbm93IHNvbWUgbG9nIGV4cHJlc3Npb25zDQoNCmBgYHtyfQ0KbG9nMTAoMTApDQpgYGANCg0KDQoNCk9mdGVuIHlvdSB3aWxsIHdhbnQgdG8gdGVzdCB3aGV0aGVyIHNvbWV0aGluZyBpcyBsZXNzIHRoYW4sIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBzb21ldGhpbmcuDQoNCg0KDQoNCmBgYHtyfQ0KMyA9PSA4DQozICE9IDgNCjMgPD0gOA0KYGBgDQoNCmBgYHtyfQ0KMT09MA0KYGBgDQoNCmBgYHtyfQ0KMj09NQ0KMT09MQ0KDQpgYGANCg0KDQoNClRoZSBfbG9naWNhbCBvcGVyYXRvcnNfIGFyZSBgJmAgZm9yIGxvZ2ljYWwgKipBTkQqKiwgYHxgIGZvciBsb2dpY2FsICoqT1IqKiwgYW5kIGAhYCBmb3IgKipOT1QqKi4gVGhlc2UgYXJlIHNvbWUgZXhhbXBsZXM6DQoNCmBgYHtyfQ0KIyBMb2dpY2FsIERpc2p1bmN0aW9uIChvcikNCkZBTFNFIHwgRkFMU0UNCiMgTG9naWNhbCBDb25qdW5jdGlvbiAoYW5kKQ0KVFJVRSAmIEZBTFNFDQojIE5lZ2F0aW9uDQohIEZBTFNFDQojIENvbWJpbmF0aW9uIG9mIHN0YXRlbWVudHMNCjIgPCAzIHwgMSA9PSA1DQpgYGANCg0KIyBBc3NpZ25pbmcgVmFsdWVzIHRvIFZhcmlhYmxlcw0KDQoNCkluIFIsIHlvdSBjcmVhdGUgYSB2YXJpYWJsZSBhbmQgYXNzaWduIGl0IGEgdmFsdWUgdXNpbmcgYDwtYCBhcyBmb2xsb3dzDQoNCmBgYHtyfQ0KZm9vIDwtIDIgKyAyDQpmb28qMw0KYGBgDQpgYGB7cn0NCiNMZXQgdXMgbm93IG11bHRpcGx5IGZvbyBieSA1DQpmb28qNQ0KYGBgDQoNCmBgYHtyfQ0KZmlpPC0zKzQNCmBgYA0KDQoNClRvIHNlZSB0aGUgdmFyaWFibGVzIHRoYXQgYXJlIGN1cnJlbnRseSBkZWZpbmVkLCB1c2UgYGxzYCAoYXMgaW4gImxpc3QiKQ0KDQpgYGB7cn0NCmxzKCkNCmBgYA0KDQpUbyBkZWxldGUgYSB2YXJpYWJsZSwgdXNlIGBybSBgIChhcyBpbiAicmVtb3ZlIikNCg0KYGBge3J9DQpybShmaWkpDQpgYGANCg0KDQpgYGB7cn0NCmxzKCkNCmBgYA0KDQoNCkVpdGhlciBgPC1gIG9yIGA9YCBjYW4gYmUgdXNlZCB0byBhc3NpZ24gYSB2YWx1ZSB0byBhIHZhcmlhYmxlLCBidXQgSSBwcmVmZXIgYDwtYCBiZWNhdXNlIGlzIGxlc3MgbGlrZWx5IHRvIGJlIGNvbmZ1c2VkIHdpdGggdGhlIGxvZ2ljYWwgb3BlcmF0b3IgYD09YA0KDQojIFZlY3RvcnMNCg0KVGhlIGJhc2ljIHR5cGUgb2Ygb2JqZWN0IGluIFIgaXMgYSBfdmVjdG9yXywgd2hpY2ggaXMgYW4gb3JkZXJlZCBsaXN0IG9mIHZhbHVlcyBvZiB0aGUgc2FtZSB0eXBlLiBZb3UgY2FuIGNyZWF0ZSBhIHZlY3RvciB1c2luZyB0aGUgYGMoKWAgZnVuY3Rpb24gKGFzIGluICJjb25jYXRlbmF0ZSIpLg0KDQpgYGB7cn0NCmJhciA8LSBjKDIsIDUsIDEwLCAyLCAxKSANCmJhcg0KYGBgDQoNCmBgYHtyfQ0KYmF6IDwtIGMoMiwgMiwgMywgMywgMykNCmJheg0KYGBgDQoNCg0KVGhlcmUgYXJlIGFsc28gc29tZSBmdW5jdGlvbnMgdGhhdCB3aWxsIGNyZWF0ZSB2ZWN0b3JzIHdpdGggcmVndWxhciBwYXR0ZXJucywgbGlrZSByZXBlYXRlZCBlbGVtZW50cy4gDQoNCmBgYHtyfQ0KIyByZXBsaWNhdGUgZnVuY3Rpb24NCnJlcCgyLCA1KQ0KIyBjb25zZWN1dGl2ZSBudW1iZXJzDQoxOjUNCiMgc2VxdWVuY2UgZnJvbSAxIHRvIDEwIHdpdGggYSBzdGVwIG9mIDINCnNlcSgxLCAxMCwgYnk9MikNCg0Kc2VxKDEsMjAsYnk9MykNCg0KcmVwKDEsMykNCmBgYA0KDQpNYW55IGZ1bmN0aW9ucyBhbmQgb3BlcmF0b3JzIGxpa2UgYCtgIG9yIGAtYCB3aWxsIHdvcmsgb24gYWxsIGVsZW1lbnRzIG9mIHRoZSB2ZWN0b3IuDQoNCmBgYHtyfQ0KIyBhZGQgdmVjdG9ycw0KYmFyICsgYmF6DQojIGNvbXBhcmUgdmVjdG9ycw0KYmFyID09IGJheg0KIyBmaW5kIGxlbmd0aCBvZiB2ZWN0b3INCmxlbmd0aChiYXIpDQojIGZpbmQgbWluaW11bSB2YWx1ZSBpbiB2ZWN0b3INCm1pbihiYXIpDQojIGZpbmQgYXZlcmFnZSB2YWx1ZSBpbiB2ZWN0b3INCm1lYW4oYmFyKQ0KYGBgDQoNCllvdSBjYW4gYWNjZXNzIHBhcnRzIG9mIGEgdmVjdG9yIGJ5IHVzaW5nIGBbYC4gUmVjYWxsIHdoYXQgdGhlIHZhbHVlIGlzIG9mIHRoZSB2ZWN0b3IgYGJhcmAuDQoNCmBgYHtyfQ0KYmFyDQojIElmIHlvdSB3YW50IHRvIGdldCB0aGUgZmlyc3QgZWxlbWVudDoNCmJhclsxXQ0KYGBgDQoNCg0KSWYgeW91IHdhbnQgdG8gZ2V0IHRoZSBsYXN0IGVsZW1lbnQgb2YgYGJhcmAgd2l0aG91dCBleHBsaWNpdGx5IHR5cGluZyB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIG9mIGBiYXJgLCBtYWtlIHVzZSBvZiB0aGUgYGxlbmd0aGAgZnVuY3Rpb24sIHdoaWNoIGNhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlY3RvcjoNCg0KYGBge3J9DQpiYXJbbGVuZ3RoKGJhcildDQpgYGANCg0KDQpZb3UgY2FuIGFsc28gZXh0cmFjdCBtdWx0aXBsZSB2YWx1ZXMgZnJvbSBhIHZlY3Rvci4gRm9yIGluc3RhbmNlIHRvIGdldCB0aGUgMm5kIHRocm91Z2ggNHRoIHZhbHVlcyB1c2UNCg0KYGBge3J9DQpiYXJbYygyLCAzLCA0KV0NCmBgYA0KDQoNClZlY3RvcnMgY2FuIGFsc28gYmUgc3RyaW5ncyBvciBsb2dpY2FsIHZhbHVlcw0KDQpgYGB7cn0NCnF1eHggPC0gYygiYSIsICJiIiwgImNkZSIsICJmZyIpDQpgYGANCg0KDQpgYGB7cn0NCnF1eHgNCmBgYA0KDQoNCiMgRGF0YSBGcmFtZXMNCg0KSW4gc3RhdGlzdGljYWwgYXBwbGljYXRpb25zLCBkYXRhIGlzIG9mdGVuIHN0b3JlZCBhcyBhIGRhdGEgZnJhbWUsIHdoaWNoIGlzIGxpa2UgYSBzcHJlYWRzaGVldCwgd2l0aCBfcm93cyBhcyBvYnNlcnZhdGlvbnNfIGFuZCBfY29sdW1ucyBhcyB2YXJpYWJsZXNfLg0KDQpUbyBtYW51YWxseSBjcmVhdGUgYSBkYXRhIGZyYW1lLCB1c2UgdGhlIGBkYXRhLmZyYW1lKClgIGZ1bmN0aW9uLg0KDQpgYGB7cn0NCmRhdGEuZnJhbWUoZm9vID0gYygxLCAyLCAzKSwgDQogICAgICAgICAgIGJhciA9IGMoImEiLCAiYiIsICJjIiksIA0KICAgICAgICAgICBiYXogPSBjKDEuNSwgMi41LCAzKSkgDQoNCmBgYA0KDQpNb3N0IG9mdGVuIHlvdSB3aWxsIGJlIHVzaW5nIGRhdGEgZnJhbWVzIGxvYWRlZCBmcm9tIGEgZmlsZS4gRm9yIGV4YW1wbGUsIGxvYWQgdGhlIHJlc3VsdHMgb2YgYSBjbGFzcyBzdXJ2ZXkuIFRoZSBmdW5jdGlvbiBgbG9hZGAgb3IgYHJlYWQudGFibGVgIGNhbiBiZSB1c2VkIGZvciB0aGlzLiANCg0KIyBIb3cgdG8gTWFrZSBhIFJhbmRvbSBTYW1wbGUNCg0KVG8gcmFuZG9tbHkgc2VsZWN0IGEgc2FtcGxlIHVzZSB0aGUgZnVuY3Rpb24gYHNhbXBsZSgpYC4gVGhlIGZvbGxvd2luZyBjb2RlIHNlbGVjdHMgNSBudW1iZXJzIGJldHdlZW4gMSBhbmQgMTAgYXQgcmFuZG9tICh3aXRob3V0IGR1cGxpY2F0aW9uKQ0KDQpgYGB7cn0NCnNhbXBsZSgxOjEwLCBzaXplPTUpDQpgYGANCg0KDQotIFRoZSBmaXJzdCBhcmd1bWVudCBnaXZlcyB0aGUgdmVjdG9yIG9mIGRhdGEgdG8gc2VsZWN0IGVsZW1lbnRzIGZyb20uDQotIFRoZSBzZWNvbmQgYXJndW1lbnQgKGBzaXplPWApIGdpdmVzIHRoZSBzaXplIG9mIHRoZSBzYW1wbGUgdG8gc2VsZWN0Lg0KDQpUYWtpbmcgYSBzaW1wbGUgcmFuZG9tIHNhbXBsZSBmcm9tIGEgZGF0YSBmcmFtZSBpcyBvbmx5IHNsaWdodGx5IG1vcmUgY29tcGxpY2F0ZWQsIGhhdmluZyB0d28gc3RlcHM6DQoNCjEuIFVzZSBgc2FtcGxlKClgIHRvIHNlbGVjdCBhIHNhbXBsZSBvZiBzaXplIGBuYCBmcm9tIGEgdmVjdG9yIG9mIHRoZSByb3cgbnVtYmVycyBvZiB0aGUgZGF0YSBmcmFtZS4gDQoyLiBVc2UgdGhlIGluZGV4IG9wZXJhdG9yIGBbYCB0byBzZWxlY3QgdGhvc2Ugcm93cyBmcm9tIHRoZSBkYXRhIGZyYW1lLg0KDQoNCkNvbnNpZGVyIHRoZSBmb2xsb3dpbmcgZXhhbXBsZSB3aXRoIF9mYWtlIGRhdGFfLiBGaXJzdCwgbWFrZSB1cCBhIGRhdGEgZnJhbWUgd2l0aCB0d28gY29sdW1ucy4gKGBMRVRURVJTYCBpcyBhIGNoYXJhY3RlciB2ZWN0b3Igb2YgbGVuZ3RoIDI2IHdpdGggY2FwaXRhbCBsZXR0ZXJzIMOiwoDCnEHDosKAwp0gdG8gw6LCgMKcWsOiwoDCnTsgYExFVFRFUlNgIGlzIGF1dG9tYXRpY2FsbHkgZGVmaW5lZCBhbmQgcHJlLWxvYWRlZCBpbiBgUmApDQoNCmBgYHtyfQ0KYmFyIDwtIGRhdGEuZnJhbWUodmFyMSA9IExFVFRFUlNbMToxMF0sIHZhcjIgPSAxOjEwKQ0KIyBDaGVjayBkYXRhIGZyYW1lDQpiYXINCmBgYA0KDQoNClN1cHBvc2UgeW91IHdhbnQgdG8gc2VsZWN0IGEgcmFuZG9tIHNhbXBsZSBvZiBzaXplIDUuIEZpcnN0LCBkZWZpbmUgYSB2YXJpYWJsZSBgbmAgd2l0aCB0aGUgc2l6ZSBvZiB0aGUgc2FtcGxlLCBpLmUuIDUNCg0KYGBge3J9DQpuIDwtIDUNCmBgYA0KDQpOb3csIHNlbGVjdCBhIHNhbXBsZSBvZiBzaXplIDUgZnJvbSB0aGUgdmVjdG9yIHdpdGggMSB0byAxMCAodGhlIG51bWJlciBvZiByb3dzIGluIGBiYXJgKS4gVXNlIHRoZSBmdW5jdGlvbiBgbnJvdygpYCB0byBmaW5kIHRoZSBudW1iZXIgb2Ygcm93cyBpbiBgYmFyYCBpbnN0ZWFkIG9mIG1hbnVhbGx5IGVudGVyaW5nIHRoYXQgbnVtYmVyLiANCg0KVXNlIGA6YCB0byBjcmVhdGUgYSB2ZWN0b3Igd2l0aCBhbGwgdGhlIGludGVnZXJzIGJldHdlZW4gMSBhbmQgdGhlIG51bWJlciBvZiByb3dzIGluIGBiYXJgLg0KDQpgYGB7cn0NCnNhbXBsZXJvd3MgPC0gc2FtcGxlKDE6bnJvdyhiYXIpLCBzaXplPW4pIA0KIyBwcmludCBzYW1wbGUgcm93cw0Kc2FtcGxlcm93cw0KYGBgDQoNCg0KDQpUaGUgdmFyaWFibGUgYHNhbXBsZXJvd3NgIGNvbnRhaW5zIHRoZSByb3dzIG9mIGBiYXJgIHdoaWNoIG1ha2UgYSByYW5kb20gc2FtcGxlIGZyb20gYWxsIHRoZSByb3dzIGluIGBiYXJgLiBFeHRyYWN0IHRob3NlIHJvd3MgZnJvbSBgYmFyYCB3aXRoDQoNCmBgYHtyfQ0KIyBleHRyYWN0IHJvd3MNCmJhcnNhbXBsZSA8LSBiYXJbc2FtcGxlcm93cywgXQ0KIyBwcmludCBzYW1wbGUNCnByaW50KGJhcnNhbXBsZSkNCmBgYA0KDQoNCg0KVGhlIGNvZGUgYWJvdmUgY3JlYXRlcyBhIG5ldyBfZGF0YSBmcmFtZV8gY2FsbGVkIGBiYXJzYW1wbGVgIHdpdGggYSByYW5kb20gc2FtcGxlIG9mIHJvd3MgZnJvbSBgYmFyYC4NCg0KSW4gYSBzaW5nbGUgbGluZSBvZiBjb2RlOiANCg0KYGBge3J9DQpiYXJbc2FtcGxlKDE6bnJvdyhiYXIpLCBuKSwgXQ0KYGBgDQoNCiMgVXNpbmcgVGFibGVzDQoNClRoZSBgdGFibGUoKWAgY29tbWFuZCBhbGxvd3MgdXMgdG8gbG9vayBhdCB0YWJsZXMuIEl0cyBzaW1wbGVzdCB1c2FnZSBsb29rcyBsaWtlIGB0YWJsZSh4KWAgd2hlcmUgYHhgIGlzIGEgX2NhdGVnb3JpY2FsIHZhcmlhYmxlXy4NCg0KRm9yIGV4YW1wbGUsIGEgc3VydmV5IGFza3MgcGVvcGxlIGlmIHRoZXkgc21va2Ugb3Igbm90LiBUaGUgZGF0YSBpcyANCg0KX1llcywgTm8sIE5vLCBZZXMsIFllc18NCg0KV2UgY2FuIGVudGVyIHRoaXMgaW50byBSIHdpdGggdGhlIGBjKClgIGNvbW1hbmQsIGFuZCBzdW1tYXJpemUgd2l0aCB0aGUgYHRhYmxlKClgIGNvbW1hbmQgYXMgZm9sbG93cw0KDQpgYGB7cn0NCnggPC0gYygiWWVzIiwiTm8iLCJObyIsIlllcyIsIlllcyIpIA0KdGFibGUoeCkNCg0KYGBgDQoNCmBgYHtyfQ0KeTwtYygiWWVzIiwiTm8iLCJZZXMiLCJZZXMiKQ0KeQ0KdGFibGUoeSkNCmBgYA0KDQoNCiMgTnVtZXJpYyBtZWFzdXJlcyBvZiBjZW50ZXIgYW5kIHNwcmVhZA0KDQpTdXBwb3NlLCBDRU8geWVhcmx5IGNvbXBlbnNhdGlvbnMgYXJlIHNhbXBsZWQgYW5kIHRoZSBmb2xsb3dpbmcgYXJlIGZvdW5kIChpbiBtaWxsaW9ucykNCg0KMTIgICAgLjQgICAgNSAgICAgMiAgICAgNTAgICAgOCAgICAgMyAgICAgMSAgICAgNCAgICAgMC4yNQ0KDQpgYGB7cn0NCnNhbHMgPC0gYygxMiwgLjQsIDUsIDIsIDUwLCA4LCAzLCAxLCA0LCAwLjI1KQ0KIyB0aGUgYXZlcmFnZQ0KbWVhbihzYWxzKSANCiMgdGhlIHZhcmlhbmNlDQp2YXIoc2FscykNCiMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbg0Kc2Qoc2FscykNCiMgdGhlIG1lZGlhbg0KbWVkaWFuKHNhbHMpDQojIFR1a2V5J3MgZml2ZSBudW1iZXIgc3VtbWFyeSwgdXNlZnVsbCBmb3IgYm94cGxvdHMNCiMgZml2ZSBudW1iZXJzOiBtaW4sIGxvd2VyIGhpbmdlLCBtZWRpYW4sIHVwcGVyIGhpbmdlLCBtYXgNCmZpdmVudW0oc2FscykNCiMgc3VtbWFyeSBzdGF0aXN0aWNzDQpzdW1tYXJ5KHNhbHMpDQoNCmBgYA0KDQoNCiMjIyBIb3cgYWJvdXQgdGhlIF9tb2RlXz8gDQoNCkluIFIgd2UgY2FuIHdyaXRlIG91ciBvd24gX2Z1bmN0aW9uc18sIGFuZCBhIGZpcnN0IGV4YW1wbGUgb2YgYSBmdW5jdGlvbiBpcyBzaG93biBiZWxvdyBpbiBvcmRlciB0byBjb21wdXRlIF90aGUgbW9kZV8gb2YgYSB2ZWN0b3Igb2Ygb2JzZXJ2YXRpb25zIGB4YA0KDQpgYGB7cn0NCiMgRnVuY3Rpb24gdG8gZmluZCB0aGUgbW9kZSwgaS5lLiBtb3N0IGZyZXF1ZW50IHZhbHVlDQpnZXRNb2RlIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICAgdXggPC0gdW5pcXVlKHgpDQogICAgIHV4W3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LCB1eCkpKV0NCiB9DQpgYGANCg0KQXMgYW4gZXhhbXBsZSwgd2UgY2FuIHVzZSB0aGUgZnVuY3Rpb24gZGVmaW5lZCBhYm92ZSB0byBmaW5kIHRoZSBtb3N0IGZyZXF1ZW50IHZhbHVlIGluIHRlIHZlY3RvciBgYmF6YA0KDQpgYGB7cn0NCiMgTW9zdCBmcmVxdWVudCB2YWx1ZSBpbiBiYXoNCmJheg0KZ2V0TW9kZShiYXopDQpiYXINCmdldE1vZGUoYmFyKQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K