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
#Question_1: Compute the log base 5 of 10 and the log of 10.
log10(5)
[1] 0.69897
log(10)
[1] 2.302585
#LN and Log can refer to the same thing (natural logarithm) in most
#context in Posit Cloud
Computing some offensive metrics in Baseball
#Batting Average=(No. of Hits)/(No. of At Bats)
#What is the batting average of a player that bats 29 hits in 112 at bats?
BA=(29)/(112)
BA
[1] 0.2589286
Batting_Average=round(BA,digits = 3)
Batting_Average
#Question_2:What is the batting average of a player that bats 42 hits
in 212 at bats?
Batting_Average_42= 42/212
Batting_Average_42
[1] 0.1981132
Batting_Average42rounded = round(Batting_Average_42,digits = 2)
Batting_Average42rounded
[1] 0.2
#On Base Percentage
#OBP=(H+BB+HBP)/(At Bats+H+BB+HBP+SF)
#Let us compute the OBP for a player with the following general stats
#AB=515,H=172,BB=84,HBP=5,SF=6
OBP=(172+84+5)/(515+172+84+5+6)
OBP
[1] 0.3337596
On_Base_Percentage=round(OBP,digits = 3)
On_Base_Percentage
[1] 0.334
#Question_3:Compute the OBP for a player with the following general
stats: #AB=565,H=156,BB=65,HBP=3,SF=7
OBP= (156+65+3)/(515+172+65+3+7)
OBP
[1] 0.2939633
OBP_rounded = round(OBP, digits=3)
OBP_rounded
[1] 0.294
Often you will want to test whether something is less than, greater
than or equal to something.
3 == 8# Does 3 equals 8?
[1] FALSE
3 != 8# Is 3 different from 8?
[1] TRUE
3 <= 8# Is 3 less than or equal to 8?
[1] TRUE
3>4
[1] FALSE
The logical operators are & for logical AND, | for logical OR,
and ! for NOT. These are some examples:
# Logical Disjunction (or)
FALSE | FALSE # False OR False
[1] FALSE
# Logical Conjunction (and)
TRUE & FALSE #True AND False
[1] FALSE
# Negation
! FALSE # Not False
[1] TRUE
# Combination of statements
2 < 3 | 1 == 5 # 2<3 is True, 1==5 is False, True OR False is True
[1] TRUE
Assigning Values to Variables In R, you create a variable and assign
it a value using <- as follows
Total_Bases <- 6 + 5
Total_Bases*3
[1] 33
To see the variables that are currently defined, use ls (as in
“list”)
ls()
[1] "BA" "Batting_Average"
[3] "Batting_Average_42" "Batting_Average42rounded"
[5] "OBP" "OBP_rounded"
[7] "On_Base_Percentage" "Total_Bases"
To delete a variable, use rm (as in “remove”)
rm(Total_Bases)
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”).
pitches_by_innings <- c(12, 15, 10, 20, 10)
pitches_by_innings
[1] 12 15 10 20 10
strikes_by_innings <- c(9, 12, 6, 14, 9)
strikes_by_innings
[1] 9 12 6 14 9
#Question_4: Define two vectors,runs_per_9innings and
hits_per_9innings, each with five elements.
runs_per_9innings <- c(11,7,3,9,8)
runs_per_9innings
[1] 11 7 3 9 8
hits_per_9innings <- c(4,6,2,8,2)
hits_per_9innings
[1] 4 6 2 8 2
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
# replicate function
rep(2, 5)
[1] 2 2 2 2 2
# consecutive numbers
1:5
[1] 1 2 3 4 5
2:10
[1] 2 3 4 5 6 7 8 9 10
# sequence from 1 to 10 with a step of 2
seq(1, 10, by=2)
[1] 1 3 5 7 9
seq(2,13,by=3)
[1] 2 5 8 11
Many functions and operators like + or - will work on all elements of
the vector.
# add vectors
pitches_by_innings+strikes_by_innings
[1] 21 27 16 34 19
# compare vectors
pitches_by_innings == strikes_by_innings
[1] FALSE FALSE FALSE FALSE FALSE
# find length of vector
length(pitches_by_innings)
[1] 5
# find minimum value in vector
min(pitches_by_innings)
[1] 10
# find average value in vector
mean(pitches_by_innings)
[1] 13.4
You can access parts of a vector by using [. Recall what the value is
of the vector pitches_by_innings.
pitches_by_innings
[1] 12 15 10 20 10
# If you want to get the first element:
pitches_by_innings[1]
[1] 12
#Question_5: Get the first element of hits_per_9innings.
hits_per_9innings[1]
[1] 4
If you want to get the last element of pitches_by_innings without
explicitly typing the number of elements of pitches_by_innings, make use
of the length function, which calculates the length of a vector:
pitches_by_innings[length(pitches_by_innings)]
[1] 10
#Question_6: Get the last element of hits_per_9innings.
hits_per_9innings[length(hits_per_9innings)]
[1] 2
You can also extract multiple values from a vector. For instance to
get the 2nd through 4th values use
pitches_by_innings[c(2, 3, 4)]
[1] 15 10 20
Vectors can also be strings or logical values
player_positions <- c("catcher", "pitcher", "infielders", "outfielders")
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(bonus = c(2, 3, 1),#in millions
active_roster = c("yes", "no", "yes"),
salary = c(1.5, 2.5, 1))#in millions
NA
Most often you will be using data frames loaded from a file. For
example, load the results of a fan’s 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] 10 4 6 2 8
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
NA
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
[1] 1 3 5 4 10
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), ]
NA
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 support the home team 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
Numerical measures of center and spread Suppose, MLB Teams’ CEOs
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 of the number of pitches_by_innings
# Most frequent value in pitches_by_innings
getMode(pitches_by_innings)
[1] 10
#Question_7: Find the most frequent value of hits_per_9innings.
getMode(hits_per_9innings)
[1] 2
#Question_8: Summarize the following survey with the
table() command: #What is your favorite day of the week to
watch baseball? A total of 10 fans submitted this survey. #Saturday,
Saturday, Sunday, Monday, Saturday,Tuesday, Sunday, Friday, Friday,
Monday
game_day<-c("Saturday", "Saturday", "Sunday", "Monday", "Saturday","Tuesday", "Sunday", "Friday", "Friday", "Monday")
game_day
[1] "Saturday" "Saturday" "Sunday" "Monday" "Saturday"
[6] "Tuesday" "Sunday" "Friday" "Friday" "Monday"
summary(game_day)
Length Class Mode
10 character character
#Question_9: What is the most frequent answer recorded in the survey?
Use the getMode function to compute results.
getMode(game_day)
[1] "Saturday"
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpCYXNpYyBjYWxjdWxhdGlvbnMKWW91IGNhbiB1c2UgUiBmb3IgYmFzaWMgY29tcHV0YXRpb25zIHlvdSB3b3VsZCBwZXJmb3JtIGluIGEgY2FsY3VsYXRvcgoKYGBge3J9CgojIEFkZGl0aW9uCjItMwpgYGAKCgpgYGB7cn0KIyBEaXZpc2lvbgoyLzMKYGBgCgpgYGB7cn0KIyBFeHBvbmVudGlhdGlvbgoyXjMgCmBgYAoKYGBge3J9CiMgU3F1YXJlIHJvb3QKc3FydCgyKQoKYGBgCgpgYGB7cn0KIyBMb2dhcml0aG1zCmxvZygyKQpgYGAKCiNRdWVzdGlvbl8xOiBDb21wdXRlIHRoZSBsb2cgYmFzZSA1IG9mIDEwIGFuZCB0aGUgbG9nIG9mIDEwLgpgYGB7cn0KbG9nMTAoNSkKbG9nKDEwKQojTE4gYW5kIExvZyBjYW4gcmVmZXIgdG8gdGhlIHNhbWUgdGhpbmcgKG5hdHVyYWwgbG9nYXJpdGhtKSBpbiBtb3N0IAojY29udGV4dCBpbiBQb3NpdCBDbG91ZAoKYGBgCkNvbXB1dGluZyBzb21lIG9mZmVuc2l2ZSBtZXRyaWNzIGluIEJhc2ViYWxsCmBgYHtyfQojQmF0dGluZyBBdmVyYWdlPShOby4gb2YgSGl0cykvKE5vLiBvZiBBdCBCYXRzKQojV2hhdCBpcyB0aGUgYmF0dGluZyBhdmVyYWdlIG9mIGEgcGxheWVyIHRoYXQgYmF0cyAyOSBoaXRzIGluIDExMiBhdCBiYXRzPwpCQT0oMjkpLygxMTIpCkJBCmBgYAoKCmBgYHtyfQpCYXR0aW5nX0F2ZXJhZ2U9cm91bmQoQkEsZGlnaXRzID0gMykKQmF0dGluZ19BdmVyYWdlCmBgYAojUXVlc3Rpb25fMjpXaGF0IGlzIHRoZSBiYXR0aW5nIGF2ZXJhZ2Ugb2YgYSBwbGF5ZXIgdGhhdCBiYXRzIDQyIGhpdHMgaW4gMjEyIGF0IGJhdHM/CmBgYHtyfQpCYXR0aW5nX0F2ZXJhZ2VfNDI9IDQyLzIxMgpCYXR0aW5nX0F2ZXJhZ2VfNDIKI3ByYWN0aWNlIHJvdW5kaW5nIHRvIDIgZGlnaXRzCkJhdHRpbmdfQXZlcmFnZTQycm91bmRlZCA9IHJvdW5kKEJhdHRpbmdfQXZlcmFnZV80MixkaWdpdHMgPSAyKQpCYXR0aW5nX0F2ZXJhZ2U0MnJvdW5kZWQKCmBgYApgYGB7cn0KI09uIEJhc2UgUGVyY2VudGFnZQojT0JQPShIK0JCK0hCUCkvKEF0IEJhdHMrSCtCQitIQlArU0YpCiNMZXQgdXMgY29tcHV0ZSB0aGUgT0JQIGZvciBhIHBsYXllciB3aXRoIHRoZSBmb2xsb3dpbmcgZ2VuZXJhbCBzdGF0cwojQUI9NTE1LEg9MTcyLEJCPTg0LEhCUD01LFNGPTYKT0JQPSgxNzIrODQrNSkvKDUxNSsxNzIrODQrNSs2KQpPQlAKYGBgCgpgYGB7cn0KT25fQmFzZV9QZXJjZW50YWdlPXJvdW5kKE9CUCxkaWdpdHMgPSAzKQpPbl9CYXNlX1BlcmNlbnRhZ2UKCmBgYAojUXVlc3Rpb25fMzpDb21wdXRlIHRoZSBPQlAgZm9yIGEgcGxheWVyIHdpdGggdGhlIGZvbGxvd2luZyBnZW5lcmFsIHN0YXRzOgojQUI9NTY1LEg9MTU2LEJCPTY1LEhCUD0zLFNGPTcKCgpgYGB7cn0KT0JQPSAoMTU2KzY1KzMpLyg1MTUrMTcyKzY1KzMrNykKT0JQCmBgYApgYGB7cn0KT0JQX3JvdW5kZWQgPSByb3VuZChPQlAsIGRpZ2l0cz0zKQpPQlBfcm91bmRlZApgYGAKT2Z0ZW4geW91IHdpbGwgd2FudCB0byB0ZXN0IHdoZXRoZXIgc29tZXRoaW5nIGlzIGxlc3MgdGhhbiwgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHNvbWV0aGluZy4KCmBgYHtyfQozID09IDgjIERvZXMgMyBlcXVhbHMgOD8KYGBgCmBgYHtyfQozICE9IDgjIElzIDMgZGlmZmVyZW50IGZyb20gOD8KYGBgCmBgYHtyfQozIDw9IDgjIElzIDMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIDg/CmBgYApgYGB7cn0KMz40CmBgYApUaGUgbG9naWNhbCBvcGVyYXRvcnMgYXJlICYgZm9yIGxvZ2ljYWwgQU5ELCB8IGZvciBsb2dpY2FsIE9SLCBhbmQgISBmb3IgTk9ULiBUaGVzZSBhcmUgc29tZSBleGFtcGxlczoKCmBgYHtyfQojIExvZ2ljYWwgRGlzanVuY3Rpb24gKG9yKQpGQUxTRSB8IEZBTFNFICMgRmFsc2UgT1IgRmFsc2UKYGBgCmBgYHtyfQojIExvZ2ljYWwgQ29uanVuY3Rpb24gKGFuZCkKVFJVRSAmIEZBTFNFICNUcnVlIEFORCBGYWxzZQpgYGAKCmBgYHtyfQojIE5lZ2F0aW9uCiEgRkFMU0UgIyBOb3QgRmFsc2UKYGBgCmBgYHtyfQojIENvbWJpbmF0aW9uIG9mIHN0YXRlbWVudHMKMiA8IDMgfCAxID09IDUgIyAyPDMgaXMgVHJ1ZSwgMT09NSBpcyBGYWxzZSwgVHJ1ZSBPUiBGYWxzZSBpcyBUcnVlCmBgYApBc3NpZ25pbmcgVmFsdWVzIHRvIFZhcmlhYmxlcwpJbiBSLCB5b3UgY3JlYXRlIGEgdmFyaWFibGUgYW5kIGFzc2lnbiBpdCBhIHZhbHVlIHVzaW5nIDwtIGFzIGZvbGxvd3MKYGBge3J9ClRvdGFsX0Jhc2VzIDwtIDYgKyA1ClRvdGFsX0Jhc2VzKjMKYGBgClRvIHNlZSB0aGUgdmFyaWFibGVzIHRoYXQgYXJlIGN1cnJlbnRseSBkZWZpbmVkLCB1c2UgbHMgKGFzIGluIOKAnGxpc3TigJ0pCmBgYHtyfQpscygpCgpgYGAKVG8gZGVsZXRlIGEgdmFyaWFibGUsIHVzZSBybSAoYXMgaW4g4oCccmVtb3Zl4oCdKQoKYGBge3J9CnJtKFRvdGFsX0Jhc2VzKQpgYGAKCkVpdGhlciA8LSBvciA9IGNhbiBiZSB1c2VkIHRvIGFzc2lnbiBhIHZhbHVlIHRvIGEgdmFyaWFibGUsIGJ1dCBJIHByZWZlciA8LSBiZWNhdXNlIGlzIGxlc3MgbGlrZWx5IHRvIGJlIGNvbmZ1c2VkIHdpdGggdGhlIGxvZ2ljYWwgb3BlcmF0b3IgPT0KCgpWZWN0b3JzClRoZSBiYXNpYyB0eXBlIG9mIG9iamVjdCBpbiBSIGlzIGEgdmVjdG9yLCB3aGljaCBpcyBhbiBvcmRlcmVkIGxpc3Qgb2YgdmFsdWVzIG9mIHRoZSBzYW1lIHR5cGUuIFlvdSBjYW4gY3JlYXRlIGEgdmVjdG9yIHVzaW5nIHRoZSBjKCkgZnVuY3Rpb24gKGFzIGluIOKAnGNvbmNhdGVuYXRl4oCdKS4KCmBgYHtyfQpwaXRjaGVzX2J5X2lubmluZ3MgPC0gYygxMiwgMTUsIDEwLCAyMCwgMTApIApwaXRjaGVzX2J5X2lubmluZ3MKYGBgCmBgYHtyfQpzdHJpa2VzX2J5X2lubmluZ3MgPC0gYyg5LCAxMiwgNiwgMTQsIDkpCnN0cmlrZXNfYnlfaW5uaW5ncwpgYGAKCiNRdWVzdGlvbl80OiBEZWZpbmUgdHdvIHZlY3RvcnMscnVuc19wZXJfOWlubmluZ3MgYW5kIGhpdHNfcGVyXzlpbm5pbmdzLCBlYWNoIHdpdGggZml2ZSBlbGVtZW50cy4KYGBge3J9CnJ1bnNfcGVyXzlpbm5pbmdzIDwtIGMoMTEsNywzLDksOCkKcnVuc19wZXJfOWlubmluZ3MKCmBgYApgYGB7cn0KaGl0c19wZXJfOWlubmluZ3MgPC0gYyg0LDYsMiw4LDIpCmhpdHNfcGVyXzlpbm5pbmdzCmBgYApUaGVyZSBhcmUgYWxzbyBzb21lIGZ1bmN0aW9ucyB0aGF0IHdpbGwgY3JlYXRlIHZlY3RvcnMgd2l0aCByZWd1bGFyIHBhdHRlcm5zLCBsaWtlIHJlcGVhdGVkIGVsZW1lbnRzLgoKYGBge3J9CiMgcmVwbGljYXRlIGZ1bmN0aW9uCnJlcCgyLCA1KQpgYGAKYGBge3J9CiMgcmVwbGljYXRlIGZ1bmN0aW9uCnJlcCgyLCA1KQpgYGAKYGBge3J9CiMgY29uc2VjdXRpdmUgbnVtYmVycwoxOjUKYGBgCmBgYHtyfQoyOjEwCmBgYApgYGB7cn0KIyBzZXF1ZW5jZSBmcm9tIDEgdG8gMTAgd2l0aCBhIHN0ZXAgb2YgMgpzZXEoMSwgMTAsIGJ5PTIpCmBgYApgYGB7cn0Kc2VxKDIsMTMsYnk9MykKYGBgCk1hbnkgZnVuY3Rpb25zIGFuZCBvcGVyYXRvcnMgbGlrZSArIG9yIC0gd2lsbCB3b3JrIG9uIGFsbCBlbGVtZW50cyBvZiB0aGUgdmVjdG9yLgpgYGB7cn0KIyBhZGQgdmVjdG9ycwpwaXRjaGVzX2J5X2lubmluZ3Mrc3RyaWtlc19ieV9pbm5pbmdzCgpgYGAKYGBge3J9CiMgY29tcGFyZSB2ZWN0b3JzCnBpdGNoZXNfYnlfaW5uaW5ncyA9PSBzdHJpa2VzX2J5X2lubmluZ3MKYGBgCmBgYHtyfQojIGZpbmQgbGVuZ3RoIG9mIHZlY3RvcgpsZW5ndGgocGl0Y2hlc19ieV9pbm5pbmdzKQpgYGAKYGBge3J9CiMgZmluZCBtaW5pbXVtIHZhbHVlIGluIHZlY3RvcgptaW4ocGl0Y2hlc19ieV9pbm5pbmdzKQpgYGAKYGBge3J9CiMgZmluZCBhdmVyYWdlIHZhbHVlIGluIHZlY3RvcgptZWFuKHBpdGNoZXNfYnlfaW5uaW5ncykKYGBgCllvdSBjYW4gYWNjZXNzIHBhcnRzIG9mIGEgdmVjdG9yIGJ5IHVzaW5nIFsuIFJlY2FsbCB3aGF0IHRoZSB2YWx1ZSBpcyBvZiB0aGUgdmVjdG9yIHBpdGNoZXNfYnlfaW5uaW5ncy4KCmBgYHtyfQpwaXRjaGVzX2J5X2lubmluZ3MKCmBgYApgYGB7cn0KIyBJZiB5b3Ugd2FudCB0byBnZXQgdGhlIGZpcnN0IGVsZW1lbnQ6CnBpdGNoZXNfYnlfaW5uaW5nc1sxXQpgYGAKI1F1ZXN0aW9uXzU6IEdldCB0aGUgZmlyc3QgZWxlbWVudCBvZiBoaXRzX3Blcl85aW5uaW5ncy4KYGBge3J9CmhpdHNfcGVyXzlpbm5pbmdzWzFdCmBgYApJZiB5b3Ugd2FudCB0byBnZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBwaXRjaGVzX2J5X2lubmluZ3Mgd2l0aG91dCBleHBsaWNpdGx5IHR5cGluZyB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIG9mIHBpdGNoZXNfYnlfaW5uaW5ncywgbWFrZSB1c2Ugb2YgdGhlIGxlbmd0aCBmdW5jdGlvbiwgd2hpY2ggY2FsY3VsYXRlcyB0aGUgbGVuZ3RoIG9mIGEgdmVjdG9yOgpgYGB7cn0KcGl0Y2hlc19ieV9pbm5pbmdzW2xlbmd0aChwaXRjaGVzX2J5X2lubmluZ3MpXQoKYGBgCiNRdWVzdGlvbl82OiBHZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBoaXRzX3Blcl85aW5uaW5ncy4KYGBge3J9CmhpdHNfcGVyXzlpbm5pbmdzW2xlbmd0aChoaXRzX3Blcl85aW5uaW5ncyldCgpgYGAKWW91IGNhbiBhbHNvIGV4dHJhY3QgbXVsdGlwbGUgdmFsdWVzIGZyb20gYSB2ZWN0b3IuIEZvciBpbnN0YW5jZSB0byBnZXQgdGhlIDJuZCB0aHJvdWdoIDR0aCB2YWx1ZXMgdXNlCgpgYGB7cn0KcGl0Y2hlc19ieV9pbm5pbmdzW2MoMiwgMywgNCldCgpgYGAKVmVjdG9ycyBjYW4gYWxzbyBiZSBzdHJpbmdzIG9yIGxvZ2ljYWwgdmFsdWVzCgpgYGB7cn0KcGxheWVyX3Bvc2l0aW9ucyA8LSBjKCJjYXRjaGVyIiwgInBpdGNoZXIiLCAiaW5maWVsZGVycyIsICJvdXRmaWVsZGVycyIpCgpgYGAKRGF0YSBGcmFtZXMKSW4gc3RhdGlzdGljYWwgYXBwbGljYXRpb25zLCBkYXRhIGlzIG9mdGVuIHN0b3JlZCBhcyBhIGRhdGEgZnJhbWUsIHdoaWNoIGlzIGxpa2UgYSBzcHJlYWRzaGVldCwgd2l0aCByb3dzIGFzIG9ic2VydmF0aW9ucyBhbmQgY29sdW1ucyBhcyB2YXJpYWJsZXMuCgpUbyBtYW51YWxseSBjcmVhdGUgYSBkYXRhIGZyYW1lLCB1c2UgdGhlIGRhdGEuZnJhbWUoKSBmdW5jdGlvbi4KCmBgYHtyfQpkYXRhLmZyYW1lKGJvbnVzID0gYygyLCAzLCAxKSwjaW4gbWlsbGlvbnMgCiAgICAgICAgICAgYWN0aXZlX3Jvc3RlciA9IGMoInllcyIsICJubyIsICJ5ZXMiKSwgCiAgICAgICAgICAgc2FsYXJ5ID0gYygxLjUsIDIuNSwgMSkpI2luIG1pbGxpb25zIAoKYGBgCk1vc3Qgb2Z0ZW4geW91IHdpbGwgYmUgdXNpbmcgZGF0YSBmcmFtZXMgbG9hZGVkIGZyb20gYSBmaWxlLiBGb3IgZXhhbXBsZSwgbG9hZCB0aGUgcmVzdWx0cyBvZiBhIGZhbuKAmXMgc3VydmV5LiBUaGUgZnVuY3Rpb24gbG9hZCBvciByZWFkLnRhYmxlIGNhbiBiZSB1c2VkIGZvciB0aGlzLgoKSG93IHRvIE1ha2UgYSBSYW5kb20gU2FtcGxlClRvIHJhbmRvbWx5IHNlbGVjdCBhIHNhbXBsZSB1c2UgdGhlIGZ1bmN0aW9uIHNhbXBsZSgpLiBUaGUgZm9sbG93aW5nIGNvZGUgc2VsZWN0cyA1IG51bWJlcnMgYmV0d2VlbiAxIGFuZCAxMCBhdCByYW5kb20gKHdpdGhvdXQgZHVwbGljYXRpb24pCgpgYGB7cn0Kc2FtcGxlKDE6MTAsIHNpemU9NSkKYGBgClRoZSBmaXJzdCBhcmd1bWVudCBnaXZlcyB0aGUgdmVjdG9yIG9mIGRhdGEgdG8gc2VsZWN0IGVsZW1lbnRzIGZyb20uClRoZSBzZWNvbmQgYXJndW1lbnQgKHNpemU9KSBnaXZlcyB0aGUgc2l6ZSBvZiB0aGUgc2FtcGxlIHRvIHNlbGVjdC4KVGFraW5nIGEgc2ltcGxlIHJhbmRvbSBzYW1wbGUgZnJvbSBhIGRhdGEgZnJhbWUgaXMgb25seSBzbGlnaHRseSBtb3JlIGNvbXBsaWNhdGVkLCBoYXZpbmcgdHdvIHN0ZXBzOgoKVXNlIHNhbXBsZSgpIHRvIHNlbGVjdCBhIHNhbXBsZSBvZiBzaXplIG4gZnJvbSBhIHZlY3RvciBvZiB0aGUgcm93IG51bWJlcnMgb2YgdGhlIGRhdGEgZnJhbWUuClVzZSB0aGUgaW5kZXggb3BlcmF0b3IgWyB0byBzZWxlY3QgdGhvc2Ugcm93cyBmcm9tIHRoZSBkYXRhIGZyYW1lLgpDb25zaWRlciB0aGUgZm9sbG93aW5nIGV4YW1wbGUgd2l0aCBmYWtlIGRhdGEuIEZpcnN0LCBtYWtlIHVwIGEgZGF0YSBmcmFtZSB3aXRoIHR3byBjb2x1bW5zLiAoTEVUVEVSUyBpcyBhIGNoYXJhY3RlciB2ZWN0b3Igb2YgbGVuZ3RoIDI2IHdpdGggY2FwaXRhbCBsZXR0ZXJzIMOiwoDCnEHDosKAwp0gdG8gw6LCgMKcWsOiwoDCnTsgTEVUVEVSUyBpcyBhdXRvbWF0aWNhbGx5IGRlZmluZWQgYW5kIHByZS1sb2FkZWQgaW4gUikKCgpgYGB7cn0KYmFyIDwtIGRhdGEuZnJhbWUodmFyMSA9IExFVFRFUlNbMToxMF0sIHZhcjIgPSAxOjEwKQojIENoZWNrIGRhdGEgZnJhbWUKYmFyCgpgYGAKU3VwcG9zZSB5b3Ugd2FudCB0byBzZWxlY3QgYSByYW5kb20gc2FtcGxlIG9mIHNpemUgNS4gRmlyc3QsIGRlZmluZSBhIHZhcmlhYmxlIG4gd2l0aCB0aGUgc2l6ZSBvZiB0aGUgc2FtcGxlLCBpLmUuIDUKYGBge3J9Cm4gPC0gNQpgYGAKCk5vdywgc2VsZWN0IGEgc2FtcGxlIG9mIHNpemUgNSBmcm9tIHRoZSB2ZWN0b3Igd2l0aCAxIHRvIDEwICh0aGUgbnVtYmVyIG9mIHJvd3MgaW4gYmFyKS4gVXNlIHRoZSBmdW5jdGlvbiBucm93KCkgdG8gZmluZCB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gYmFyIGluc3RlYWQgb2YgbWFudWFsbHkgZW50ZXJpbmcgdGhhdCBudW1iZXIuCgpVc2UgOiB0byBjcmVhdGUgYSB2ZWN0b3Igd2l0aCBhbGwgdGhlIGludGVnZXJzIGJldHdlZW4gMSBhbmQgdGhlIG51bWJlciBvZiByb3dzIGluIGJhci4KCmBgYHtyfQpzYW1wbGVyb3dzIDwtIHNhbXBsZSgxOm5yb3coYmFyKSwgc2l6ZT1uKSAKIyBwcmludCBzYW1wbGUgcm93cwpzYW1wbGVyb3dzCgpgYGAKVGhlIHZhcmlhYmxlIHNhbXBsZXJvd3MgY29udGFpbnMgdGhlIHJvd3Mgb2YgYmFyIHdoaWNoIG1ha2UgYSByYW5kb20gc2FtcGxlIGZyb20gYWxsIHRoZSByb3dzIGluIGJhci4gRXh0cmFjdCB0aG9zZSByb3dzIGZyb20gYmFyIHdpdGgKCgpgYGB7cn0KIyBleHRyYWN0IHJvd3MKYmFyc2FtcGxlIDwtIGJhcltzYW1wbGVyb3dzLCBdCiMgcHJpbnQgc2FtcGxlCnByaW50KGJhcnNhbXBsZSkKYGBgClRoZSBjb2RlIGFib3ZlIGNyZWF0ZXMgYSBuZXcgZGF0YSBmcmFtZSBjYWxsZWQgYmFyc2FtcGxlIHdpdGggYSByYW5kb20gc2FtcGxlIG9mIHJvd3MgZnJvbSBiYXIuCgpJbiBhIHNpbmdsZSBsaW5lIG9mIGNvZGU6CgpgYGB7cn0KYmFyW3NhbXBsZSgxOm5yb3coYmFyKSwgbiksIF0KCmBgYApVc2luZyBUYWJsZXMKVGhlIHRhYmxlKCkgY29tbWFuZCBhbGxvd3MgdXMgdG8gbG9vayBhdCB0YWJsZXMuIEl0cyBzaW1wbGVzdCB1c2FnZSBsb29rcyBsaWtlIHRhYmxlKHgpIHdoZXJlIHggaXMgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZS4KCkZvciBleGFtcGxlLCBhIHN1cnZleSBhc2tzIHBlb3BsZSBpZiB0aGV5IHN1cHBvcnQgdGhlIGhvbWUgdGVhbSBvciBub3QuIFRoZSBkYXRhIGlzCgpZZXMsIE5vLCBObywgWWVzLCBZZXMKCldlIGNhbiBlbnRlciB0aGlzIGludG8gUiB3aXRoIHRoZSBjKCkgY29tbWFuZCwgYW5kIHN1bW1hcml6ZSB3aXRoIHRoZSB0YWJsZSgpIGNvbW1hbmQgYXMgZm9sbG93cwoKYGBge3J9CnggPC0gYygiWWVzIiwiTm8iLCJObyIsIlllcyIsIlllcyIpIAp0YWJsZSh4KQoKYGBgCgpOdW1lcmljYWwgbWVhc3VyZXMgb2YgY2VudGVyIGFuZCBzcHJlYWQKU3VwcG9zZSwgTUxCIFRlYW1z4oCZIENFT3MgeWVhcmx5IGNvbXBlbnNhdGlvbnMgYXJlIHNhbXBsZWQgYW5kIHRoZSBmb2xsb3dpbmcgYXJlIGZvdW5kIChpbiBtaWxsaW9ucykKCjEyIC40IDUgMiA1MCA4IDMgMSA0IDAuMjUKCgoKYGBge3J9CnNhbHMgPC0gYygxMiwgLjQsIDUsIDIsIDUwLCA4LCAzLCAxLCA0LCAwLjI1KQojIHRoZSBhdmVyYWdlCm1lYW4oc2FscykgCgpgYGAKCmBgYHtyfQojIHRoZSB2YXJpYW5jZQp2YXIoc2FscykKYGBgCmBgYHtyfQojIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24Kc2Qoc2FscykKYGBgCmBgYHtyfQojIHRoZSBtZWRpYW4KbWVkaWFuKHNhbHMpCmBgYApgYGB7cn0KIyBUdWtleSdzIGZpdmUgbnVtYmVyIHN1bW1hcnksIHVzZWZ1bGwgZm9yIGJveHBsb3RzCiMgZml2ZSBudW1iZXJzOiBtaW4sIGxvd2VyIGhpbmdlLCBtZWRpYW4sIHVwcGVyIGhpbmdlLCBtYXgKZml2ZW51bShzYWxzKQpgYGAKCgpgYGB7cn0KCiMgc3VtbWFyeSBzdGF0aXN0aWNzCnN1bW1hcnkoc2FscykKYGBgCkhvdyBhYm91dCB0aGUgbW9kZT8KSW4gUiB3ZSBjYW4gd3JpdGUgb3VyIG93biBmdW5jdGlvbnMsIGFuZCBhIGZpcnN0IGV4YW1wbGUgb2YgYSBmdW5jdGlvbiBpcyBzaG93biBiZWxvdyBpbiBvcmRlciB0byBjb21wdXRlIHRoZSBtb2RlIG9mIGEgdmVjdG9yIG9mIG9ic2VydmF0aW9ucyB4CgpgYGB7cn0KCiMgRnVuY3Rpb24gdG8gZmluZCB0aGUgbW9kZSwgaS5lLiBtb3N0IGZyZXF1ZW50IHZhbHVlCmdldE1vZGUgPC0gZnVuY3Rpb24oeCkgewogICAgIHV4IDwtIHVuaXF1ZSh4KQogICAgIHV4W3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LCB1eCkpKV0KIH0KYGBgCgpBcyBhbiBleGFtcGxlLCB3ZSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBkZWZpbmVkIGFib3ZlIHRvIGZpbmQgdGhlIG1vc3QgZnJlcXVlbnQgdmFsdWUgb2YgdGhlIG51bWJlciBvZiBwaXRjaGVzX2J5X2lubmluZ3MKCmBgYHtyfQojIE1vc3QgZnJlcXVlbnQgdmFsdWUgaW4gcGl0Y2hlc19ieV9pbm5pbmdzCmdldE1vZGUocGl0Y2hlc19ieV9pbm5pbmdzKQpgYGAKI1F1ZXN0aW9uXzc6IEZpbmQgdGhlIG1vc3QgZnJlcXVlbnQgdmFsdWUgb2YgaGl0c19wZXJfOWlubmluZ3MuCgpgYGB7cn0KZ2V0TW9kZShoaXRzX3Blcl85aW5uaW5ncykKCmBgYAojUXVlc3Rpb25fODogU3VtbWFyaXplIHRoZSBmb2xsb3dpbmcgc3VydmV5IHdpdGggdGhlIGB0YWJsZSgpYCBjb21tYW5kOgojV2hhdCBpcyB5b3VyIGZhdm9yaXRlIGRheSBvZiB0aGUgd2VlayB0byB3YXRjaCBiYXNlYmFsbD8gQSB0b3RhbCBvZiAxMCBmYW5zIHN1Ym1pdHRlZCB0aGlzIHN1cnZleS4KI1NhdHVyZGF5LCBTYXR1cmRheSwgU3VuZGF5LCBNb25kYXksIFNhdHVyZGF5LFR1ZXNkYXksIFN1bmRheSwgRnJpZGF5LCBGcmlkYXksIE1vbmRheQpgYGB7cn0KCmdhbWVfZGF5PC1jKCJTYXR1cmRheSIsICJTYXR1cmRheSIsICJTdW5kYXkiLCAiTW9uZGF5IiwgIlNhdHVyZGF5IiwiVHVlc2RheSIsICJTdW5kYXkiLCAiRnJpZGF5IiwgIkZyaWRheSIsICJNb25kYXkiKQpnYW1lX2RheQoKYGBgCgpgYGB7cn0Kc3VtbWFyeShnYW1lX2RheSkKYGBgCgojUXVlc3Rpb25fOTogV2hhdCBpcyB0aGUgbW9zdCBmcmVxdWVudCBhbnN3ZXIgcmVjb3JkZWQgaW4gdGhlIHN1cnZleT8gVXNlIHRoZSBnZXRNb2RlIGZ1bmN0aW9uIHRvIGNvbXB1dGUgcmVzdWx0cy4gCgpgYGB7cn0KZ2V0TW9kZShnYW1lX2RheSkKYGBgCgo=