Basic calculations
You can use R for basic computations you would perform in a
calculator
# Addition
2 + 3
[1] 5
# Substraction
2 - 5
[1] -3
# Division
6 / 2
[1] 3
# Exponent
2 ^ 3
[1] 8
# Logarithmic
log(10) # Base e
[1] 2.302585
log(10, base = 10)
[1] 1
logb(10, base = 10)
[1] 1
log10(10)
[1] 1
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
[1] 0.259
Question_2:What is the batting average of a player that bats 42 hits
in 212 at bats?
BA=(42)/(212)
Batting_Average=round(BA,digits = 3)
Batting_Average
[1] 0.198
#On Base Percentage
#OBP=(H+BB+HBP)/(At Bats+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+84+5+6)
OBP
[1] 0.4278689
On_Base_Percentage=round(OBP,digits = 3)
On_Base_Percentage
[1] 0.428
Question_3:Compute the OBP for a player with the following general
stats:
AB=565,H=156,BB=65,HBP=3,SF=7
#OBP=(H+BB+HBP)/(At Bats+BB+HBP+SF)
OBP=(156+65+3)/(565+65+7)
On_Base_Percentage=round(OBP,digits = 3)
On_Base_Percentage
[1] 0.352
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
2 > 3 & 3 >= 3
[1] FALSE
2 > 1 | 3 >= 4
[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" "OBP" "On_Base_Percentage" "Total_Bases"
To delete a variable, use rm (as in “remove”)
rm(Total_Bases)
ls()
[1] "BA" "Batting_Average" "OBP" "On_Base_Percentage"
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(2,5,7,11,13)
hits_per_9innings <- c(11,13, 16, 18, 19)
runs_per_9innings
[1] 2 5 7 11 13
hits_per_9innings
[1] 11 13 16 18 19
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
rep(1,4)
[1] 1 1 1 1
# 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
[1] 12 15 10 20 10
strikes_by_innings
[1] 9 12 6 14 9
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
runs_per_9innings == hits_per_9innings
[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
pitches_by_innings[1]
[1] 12
##Question_5: Get the first element of hits_per_9innings.
hits_per_9innings[1]
[1] 11
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] 19
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
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 1 2 7 4
- 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
[1] 6 3 8 4 1
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)
var1 var2
6 F 6
3 C 3
8 H 8
4 D 4
1 A 1
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] 11
getMode(strikes_by_innings)
[1] 9
#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")
table(game_day)
game_day
Friday Monday Saturday Sunday Tuesday
2 2 3 2 1
##Question_9: What is the most frequent answer recorded in the
survey? Use the getMode function to compute results.
getMode(game_day)
[1] "Saturday"
LS0tCnRpdGxlOiAiQWN0aXZpdHkgNCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBCYXNpYyBjYWxjdWxhdGlvbnMKCllvdSBjYW4gdXNlIFIgZm9yIGJhc2ljIGNvbXB1dGF0aW9ucyB5b3Ugd291bGQgcGVyZm9ybSBpbiBhIGNhbGN1bGF0b3IKCmBgYHtyfQojIEFkZGl0aW9uCgoyICsgMwoKIyBTdWJzdHJhY3Rpb24KCjIgLSA1CmBgYAoKYGBge3J9CiMgRGl2aXNpb24KCjYgLyAyCmBgYAoKYGBge3J9CiAjIEV4cG9uZW50CgoyIF4gMwpgYGAKCmBgYHtyfQojIExvZ2FyaXRobWljCgpsb2coMTApICMgQmFzZSBlCgpsb2coMTAsIGJhc2UgPSAxMCkKCmxvZ2IoMTAsIGJhc2UgPSAxMCkKCmxvZzEwKDEwKQpgYGAKCkNvbXB1dGluZyBzb21lIG9mZmVuc2l2ZSBtZXRyaWNzIGluIEJhc2ViYWxsCgpgYGB7cn0KI0JhdHRpbmcgQXZlcmFnZT0oTm8uIG9mIEhpdHMpLyhOby4gb2YgQXQgQmF0cykKI1doYXQgaXMgdGhlIGJhdHRpbmcgYXZlcmFnZSBvZiBhIHBsYXllciB0aGF0IGJhdHMgMjkgaGl0cyBpbiAxMTIgYXQgYmF0cz8KQkE9KDI5KS8oMTEyKQpCQQpgYGAKCmBgYHtyfQpCYXR0aW5nX0F2ZXJhZ2U9cm91bmQoQkEsZGlnaXRzID0gMykKQmF0dGluZ19BdmVyYWdlCmBgYAoKUXVlc3Rpb25fMjpXaGF0IGlzIHRoZSBiYXR0aW5nIGF2ZXJhZ2Ugb2YgYSBwbGF5ZXIgdGhhdCBiYXRzIDQyIGhpdHMgaW4gMjEyIGF0IGJhdHM/CgpgYGB7cn0KQkE9KDQyKS8oMjEyKQpCYXR0aW5nX0F2ZXJhZ2U9cm91bmQoQkEsZGlnaXRzID0gMykKQmF0dGluZ19BdmVyYWdlCmBgYAoKCgoKYGBge3J9CiNPbiBCYXNlIFBlcmNlbnRhZ2UKI09CUD0oSCtCQitIQlApLyhBdCBCYXRzK0JCK0hCUCtTRikKI0xldCB1cyBjb21wdXRlIHRoZSBPQlAgZm9yIGEgcGxheWVyIHdpdGggdGhlIGZvbGxvd2luZyBnZW5lcmFsIHN0YXRzCiNBQj01MTUsSD0xNzIsQkI9ODQsSEJQPTUsU0Y9NgpPQlA9KDE3Mis4NCs1KS8oNTE1Kzg0KzUrNikKT0JQCmBgYAoKCmBgYHtyfQpPbl9CYXNlX1BlcmNlbnRhZ2U9cm91bmQoT0JQLGRpZ2l0cyA9IDMpCk9uX0Jhc2VfUGVyY2VudGFnZQpgYGAKClF1ZXN0aW9uXzM6Q29tcHV0ZSB0aGUgT0JQIGZvciBhIHBsYXllciB3aXRoIHRoZSBmb2xsb3dpbmcgZ2VuZXJhbCBzdGF0czoKCkFCPTU2NSxIPTE1NixCQj02NSxIQlA9MyxTRj03CgpgYGB7cn0KI09CUD0oSCtCQitIQlApLyhBdCBCYXRzK0JCK0hCUCtTRikKT0JQPSgxNTYrNjUrMykvKDU2NSs2NSs3KQpPbl9CYXNlX1BlcmNlbnRhZ2U9cm91bmQoT0JQLGRpZ2l0cyA9IDMpCk9uX0Jhc2VfUGVyY2VudGFnZQpgYGAKCk9mdGVuIHlvdSB3aWxsIHdhbnQgdG8gdGVzdCB3aGV0aGVyIHNvbWV0aGluZyBpcyBsZXNzIHRoYW4sIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBzb21ldGhpbmcuCgpgYGB7cn0KCjMgPT0gOCMgRG9lcyAzIGVxdWFscyA4PwoKMyAhPSA4IyBJcyAzIGRpZmZlcmVudCBmcm9tIDg/CgozIDw9IDgjIElzIDMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIDg/CgozID4gNAoKYGBgCgpUaGUgbG9naWNhbCBvcGVyYXRvcnMgYXJlICYgZm9yIGxvZ2ljYWwgQU5ELCB8IGZvciBsb2dpY2FsIE9SLCBhbmQgISBmb3IgTk9ULiBUaGVzZSBhcmUgc29tZSBleGFtcGxlczoKCmBgYHtyfQojIExvZ2ljYWwgRGlzanVuY3Rpb24gKG9yKQpGQUxTRSB8IEZBTFNFICMgRmFsc2UgT1IgRmFsc2UKYGBgCgoKYGBge3J9CiMgTG9naWNhbCBDb25qdW5jdGlvbiAoYW5kKQpUUlVFICYgRkFMU0UgI1RydWUgQU5EIEZhbHNlCmBgYAoKYGBge3J9CiMgTmVnYXRpb24KISBGQUxTRSAjIE5vdCBGYWxzZQpgYGAKCmBgYHtyfQojIENvbWJpbmF0aW9uIG9mIHN0YXRlbWVudHMKMiA8IDMgfCAxID09IDUgIyAyPDMgaXMgVHJ1ZSwgMT09NSBpcyBGYWxzZSwgVHJ1ZSBPUiBGYWxzZSBpcyBUcnVlCgoyID4gMyAmIDMgPj0gMwoKMiA+IDEgfCAzID49IDQKYGBgCgojIEFzc2lnbmluZyBWYWx1ZXMgdG8gVmFyaWFibGVzCgpJbiBSLCB5b3UgY3JlYXRlIGEgdmFyaWFibGUgYW5kIGFzc2lnbiBpdCBhIHZhbHVlIHVzaW5nIDwtIGFzIGZvbGxvd3MKCmBgYHtyfQpUb3RhbF9CYXNlcyA8LSA2ICsgNQpUb3RhbF9CYXNlcyozCmBgYAoKVG8gc2VlIHRoZSB2YXJpYWJsZXMgdGhhdCBhcmUgY3VycmVudGx5IGRlZmluZWQsIHVzZSBscyAoYXMgaW4g4oCcbGlzdOKAnSkKCmBgYHtyfQpscygpCmBgYAoKVG8gZGVsZXRlIGEgdmFyaWFibGUsIHVzZSBybSAoYXMgaW4g4oCccmVtb3Zl4oCdKQoKYGBge3J9CnJtKFRvdGFsX0Jhc2VzKQpscygpCmBgYAoKRWl0aGVyIDwtIG9yID0gY2FuIGJlIHVzZWQgdG8gYXNzaWduIGEgdmFsdWUgdG8gYSB2YXJpYWJsZSwgYnV0IEkgcHJlZmVyIDwtIGJlY2F1c2UgaXMgbGVzcyBsaWtlbHkgdG8gYmUgY29uZnVzZWQgd2l0aCB0aGUgbG9naWNhbCBvcGVyYXRvciA9PQoKIyBWZWN0b3JzCgpUaGUgYmFzaWMgdHlwZSBvZiBvYmplY3QgaW4gUiBpcyBhIHZlY3Rvciwgd2hpY2ggaXMgYW4gb3JkZXJlZCBsaXN0IG9mIHZhbHVlcyBvZiB0aGUgc2FtZSB0eXBlLiBZb3UgY2FuIGNyZWF0ZSBhIHZlY3RvciB1c2luZyB0aGUgYygpIGZ1bmN0aW9uIChhcyBpbiDigJxjb25jYXRlbmF0ZeKAnSkuCgpgYGB7cn0KcGl0Y2hlc19ieV9pbm5pbmdzIDwtIGMoMTIsIDE1LCAxMCwgMjAsIDEwKSAKcGl0Y2hlc19ieV9pbm5pbmdzCgpgYGAKCgpgYGB7cn0Kc3RyaWtlc19ieV9pbm5pbmdzIDwtIGMoOSwgMTIsIDYsIDE0LCA5KQpzdHJpa2VzX2J5X2lubmluZ3MKYGBgCgojI1F1ZXN0aW9uXzQ6IERlZmluZSB0d28gdmVjdG9ycyxydW5zX3Blcl85aW5uaW5ncyBhbmQgaGl0c19wZXJfOWlubmluZ3MsIGVhY2ggd2l0aCBmaXZlIGVsZW1lbnRzLiAKCmBgYHtyfQpydW5zX3Blcl85aW5uaW5ncyA8LSBjKDIsNSw3LDExLDEzKQpoaXRzX3Blcl85aW5uaW5ncyA8LSBjKDExLDEzLCAxNiwgMTgsIDE5KQpydW5zX3Blcl85aW5uaW5ncwpoaXRzX3Blcl85aW5uaW5ncwpgYGAKClRoZXJlIGFyZSBhbHNvIHNvbWUgZnVuY3Rpb25zIHRoYXQgd2lsbCBjcmVhdGUgdmVjdG9ycyB3aXRoIHJlZ3VsYXIgcGF0dGVybnMsIGxpa2UgcmVwZWF0ZWQgZWxlbWVudHMuCgpgYGB7cn0KIyByZXBsaWNhdGUgZnVuY3Rpb24KcmVwKDIsIDUpCgpgYGAKCmBgYHtyfQpyZXAoMSw0KQpgYGAKCmBgYHtyfQojIGNvbnNlY3V0aXZlIG51bWJlcnMKMTo1CmBgYAoKYGBge3J9CjI6MTAKYGBgCgpgYGB7cn0KIyBzZXF1ZW5jZSBmcm9tIDEgdG8gMTAgd2l0aCBhIHN0ZXAgb2YgMgpzZXEoMSwgMTAsIGJ5PTIpCmBgYAoKYGBge3J9CnNlcSgyLDEzLGJ5PTMpCgpgYGAKCk1hbnkgZnVuY3Rpb25zIGFuZCBvcGVyYXRvcnMgbGlrZSArIG9yIC0gd2lsbCB3b3JrIG9uIGFsbCBlbGVtZW50cyBvZiB0aGUgdmVjdG9yLgoKYGBge3J9CiMgYWRkIHZlY3RvcnMKcGl0Y2hlc19ieV9pbm5pbmdzCnN0cmlrZXNfYnlfaW5uaW5ncwpwaXRjaGVzX2J5X2lubmluZ3Mrc3RyaWtlc19ieV9pbm5pbmdzCmBgYAoKYGBge3J9CiMgY29tcGFyZSB2ZWN0b3JzCnBpdGNoZXNfYnlfaW5uaW5ncyA9PSBzdHJpa2VzX2J5X2lubmluZ3MKCnJ1bnNfcGVyXzlpbm5pbmdzID09IGhpdHNfcGVyXzlpbm5pbmdzCgpgYGAKCmBgYHtyfQojIGZpbmQgbGVuZ3RoIG9mIHZlY3RvcgpsZW5ndGgocGl0Y2hlc19ieV9pbm5pbmdzKQpgYGAKCmBgYHtyfQojIGZpbmQgbWluaW11bSB2YWx1ZSBpbiB2ZWN0b3IKbWluKHBpdGNoZXNfYnlfaW5uaW5ncykKYGBgCgpgYGB7cn0KIyBmaW5kIGF2ZXJhZ2UgdmFsdWUgaW4gdmVjdG9yCm1lYW4ocGl0Y2hlc19ieV9pbm5pbmdzKQoKYGBgCgpZb3UgY2FuIGFjY2VzcyBwYXJ0cyBvZiBhIHZlY3RvciBieSB1c2luZyBbLiBSZWNhbGwgd2hhdCB0aGUgdmFsdWUgaXMgb2YgdGhlIHZlY3RvciBwaXRjaGVzX2J5X2lubmluZ3MuCgoKYGBge3J9CnBpdGNoZXNfYnlfaW5uaW5ncwpwaXRjaGVzX2J5X2lubmluZ3NbMV0KCmBgYAoKIyNRdWVzdGlvbl81OiBHZXQgdGhlIGZpcnN0IGVsZW1lbnQgb2YgaGl0c19wZXJfOWlubmluZ3MuCgpgYGB7cn0KaGl0c19wZXJfOWlubmluZ3NbMV0KYGBgCgpJZiB5b3Ugd2FudCB0byBnZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBwaXRjaGVzX2J5X2lubmluZ3Mgd2l0aG91dCBleHBsaWNpdGx5IHR5cGluZyB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIG9mIHBpdGNoZXNfYnlfaW5uaW5ncywgbWFrZSB1c2Ugb2YgdGhlIGxlbmd0aCBmdW5jdGlvbiwgd2hpY2ggY2FsY3VsYXRlcyB0aGUgbGVuZ3RoIG9mIGEgdmVjdG9yOgoKYGBge3J9CnBpdGNoZXNfYnlfaW5uaW5nc1tsZW5ndGgocGl0Y2hlc19ieV9pbm5pbmdzKV0KCmBgYAoKIyNRdWVzdGlvbl82OiBHZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBoaXRzX3Blcl85aW5uaW5ncy4KCmBgYHtyfQpoaXRzX3Blcl85aW5uaW5nc1tsZW5ndGgoaGl0c19wZXJfOWlubmluZ3MpXQoKYGBgCgpZb3UgY2FuIGFsc28gZXh0cmFjdCBtdWx0aXBsZSB2YWx1ZXMgZnJvbSBhIHZlY3Rvci4gRm9yIGluc3RhbmNlIHRvIGdldCB0aGUgMm5kIHRocm91Z2ggNHRoIHZhbHVlcyB1c2UKCmBgYHtyfQpwaXRjaGVzX2J5X2lubmluZ3NbYygyLCAzLCA0KV0KCmBgYAoKVmVjdG9ycyBjYW4gYWxzbyBiZSBzdHJpbmdzIG9yIGxvZ2ljYWwgdmFsdWVzCgpgYGB7cn0KcGxheWVyX3Bvc2l0aW9ucyA8LSBjKCJjYXRjaGVyIiwgInBpdGNoZXIiLCAiaW5maWVsZGVycyIsICJvdXRmaWVsZGVycyIpCmBgYAoKIyBEYXRhIEZyYW1lcwoKSW4gc3RhdGlzdGljYWwgYXBwbGljYXRpb25zLCBkYXRhIGlzIG9mdGVuIHN0b3JlZCBhcyBhIGRhdGEgZnJhbWUsIHdoaWNoIGlzIGxpa2UgYSBzcHJlYWRzaGVldCwgd2l0aCByb3dzIGFzIG9ic2VydmF0aW9ucyBhbmQgY29sdW1ucyBhcyB2YXJpYWJsZXMuCgpUbyBtYW51YWxseSBjcmVhdGUgYSBkYXRhIGZyYW1lLCB1c2UgdGhlIGBkYXRhLmZyYW1lKClgIGZ1bmN0aW9uLgoKYGBge3J9CmRhdGEuZnJhbWUoYm9udXMgPSBjKDIsIDMsIDEpLCNpbiBtaWxsaW9ucyAKICAgICAgICAgICBhY3RpdmVfcm9zdGVyID0gYygieWVzIiwgIm5vIiwgInllcyIpLCAKICAgICAgICAgICBzYWxhcnkgPSBjKDEuNSwgMi41LCAxKSkjaW4gbWlsbGlvbnMgCmBgYAoKTW9zdCBvZnRlbiB5b3Ugd2lsbCBiZSB1c2luZyBkYXRhIGZyYW1lcyBsb2FkZWQgZnJvbSBhIGZpbGUuIEZvciBleGFtcGxlLCBsb2FkIHRoZSByZXN1bHRzIG9mIGEgZmFu4oCZcyBzdXJ2ZXkuIFRoZSBmdW5jdGlvbiBsb2FkIG9yIHJlYWQudGFibGUgY2FuIGJlIHVzZWQgZm9yIHRoaXMuCgojIEhvdyB0byBNYWtlIGEgUmFuZG9tIFNhbXBsZQoKVG8gcmFuZG9tbHkgc2VsZWN0IGEgc2FtcGxlIHVzZSB0aGUgZnVuY3Rpb24gc2FtcGxlKCkuIFRoZSBmb2xsb3dpbmcgY29kZSBzZWxlY3RzIDUgbnVtYmVycyBiZXR3ZWVuIDEgYW5kIDEwIGF0IHJhbmRvbSAod2l0aG91dCBkdXBsaWNhdGlvbikKCmBgYHtyfQpzYW1wbGUoMToxMCwgc2l6ZT01KQoKYGBgCgoqIFRoZSBmaXJzdCBhcmd1bWVudCBnaXZlcyB0aGUgdmVjdG9yIG9mIGRhdGEgdG8gc2VsZWN0IGVsZW1lbnRzIGZyb20uCiogVGhlIHNlY29uZCBhcmd1bWVudCAoc2l6ZT0pIGdpdmVzIHRoZSBzaXplIG9mIHRoZSBzYW1wbGUgdG8gc2VsZWN0LgoKVGFraW5nIGEgc2ltcGxlIHJhbmRvbSBzYW1wbGUgZnJvbSBhIGRhdGEgZnJhbWUgaXMgb25seSBzbGlnaHRseSBtb3JlIGNvbXBsaWNhdGVkLCBoYXZpbmcgdHdvIHN0ZXBzOgoKMS4gVXNlIHNhbXBsZSgpIHRvIHNlbGVjdCBhIHNhbXBsZSBvZiBzaXplIG4gZnJvbSBhIHZlY3RvciBvZiB0aGUgcm93IG51bWJlcnMgb2YgdGhlIGRhdGEgZnJhbWUuCjIuIFVzZSB0aGUgaW5kZXggb3BlcmF0b3IgWyB0byBzZWxlY3QgdGhvc2Ugcm93cyBmcm9tIHRoZSBkYXRhIGZyYW1lLgoKQ29uc2lkZXIgdGhlIGZvbGxvd2luZyBleGFtcGxlIHdpdGggZmFrZSBkYXRhLiBGaXJzdCwgbWFrZSB1cCBhIGRhdGEgZnJhbWUgd2l0aCB0d28gY29sdW1ucy4gKExFVFRFUlMgaXMgYSBjaGFyYWN0ZXIgdmVjdG9yIG9mIGxlbmd0aCAyNiB3aXRoIGNhcGl0YWwgbGV0dGVycyDDosKAwpxBw6LCgMKdIHRvIMOiwoDCnFrDosKAwp07IExFVFRFUlMgaXMgYXV0b21hdGljYWxseSBkZWZpbmVkIGFuZCBwcmUtbG9hZGVkIGluIFIpCgpgYGB7cn0KYmFyIDwtIGRhdGEuZnJhbWUodmFyMSA9IExFVFRFUlNbMToxMF0sIHZhcjIgPSAxOjEwKQojIENoZWNrIGRhdGEgZnJhbWUKYmFyCmBgYAoKU3VwcG9zZSB5b3Ugd2FudCB0byBzZWxlY3QgYSByYW5kb20gc2FtcGxlIG9mIHNpemUgNS4gRmlyc3QsIGRlZmluZSBhIHZhcmlhYmxlIG4gd2l0aCB0aGUgc2l6ZSBvZiB0aGUgc2FtcGxlLCBpLmUuIDUKCmBgYHtyfQpuIDwtIDUKCmBgYAoKTm93LCBzZWxlY3QgYSBzYW1wbGUgb2Ygc2l6ZSA1IGZyb20gdGhlIHZlY3RvciB3aXRoIDEgdG8gMTAgKHRoZSBudW1iZXIgb2Ygcm93cyBpbiBgYmFyYCkuIFVzZSB0aGUgZnVuY3Rpb24gYG5yb3coKWAgdG8gZmluZCB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gYGJhcmAgaW5zdGVhZCBvZiBtYW51YWxseSBlbnRlcmluZyB0aGF0IG51bWJlci4KClVzZSBgOmAgdG8gY3JlYXRlIGEgdmVjdG9yIHdpdGggYWxsIHRoZSBpbnRlZ2VycyBiZXR3ZWVuIDEgYW5kIHRoZSBudW1iZXIgb2Ygcm93cyBpbiBiYXIuCgpgYGB7cn0Kc2FtcGxlcm93cyA8LSBzYW1wbGUoMTpucm93KGJhciksIHNpemU9bikgCiMgcHJpbnQgc2FtcGxlIHJvd3MKc2FtcGxlcm93cwpgYGAKClRoZSB2YXJpYWJsZSBzYW1wbGVyb3dzIGNvbnRhaW5zIHRoZSByb3dzIG9mIGJhciB3aGljaCBtYWtlIGEgcmFuZG9tIHNhbXBsZSBmcm9tIGFsbCB0aGUgcm93cyBpbiBiYXIuIEV4dHJhY3QgdGhvc2Ugcm93cyBmcm9tIGJhciB3aXRoCgpgYGB7cn0KIyBleHRyYWN0IHJvd3MKYmFyc2FtcGxlIDwtIGJhcltzYW1wbGVyb3dzLCBdCiMgcHJpbnQgc2FtcGxlCnByaW50KGJhcnNhbXBsZSkKYGBgCgpgYGB7cn0KYmFyW3NhbXBsZSgxOm5yb3coYmFyKSwgbiksIF0KCmBgYAoKI1VzaW5nIFRhYmxlcwoKVGhlIHRhYmxlKCkgY29tbWFuZCBhbGxvd3MgdXMgdG8gbG9vayBhdCB0YWJsZXMuIEl0cyBzaW1wbGVzdCB1c2FnZSBsb29rcyBsaWtlIHRhYmxlKHgpIHdoZXJlIHggaXMgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZS4KCkZvciBleGFtcGxlLCBhIHN1cnZleSBhc2tzIHBlb3BsZSBpZiB0aGV5IHN1cHBvcnQgdGhlIGhvbWUgdGVhbSBvciBub3QuIFRoZSBkYXRhIGlzCgpZZXMsIE5vLCBObywgWWVzLCBZZXMKCldlIGNhbiBlbnRlciB0aGlzIGludG8gUiB3aXRoIHRoZSBjKCkgY29tbWFuZCwgYW5kIHN1bW1hcml6ZSB3aXRoIHRoZSB0YWJsZSgpIGNvbW1hbmQgYXMgZm9sbG93cwoKYGBge3J9CnggPC0gYygiWWVzIiwiTm8iLCJObyIsIlllcyIsIlllcyIpIAp0YWJsZSh4KQpgYGAKCiNOdW1lcmljYWwgbWVhc3VyZXMgb2YgY2VudGVyIGFuZCBzcHJlYWQKClN1cHBvc2UsIE1MQiBUZWFtc+KAmSBDRU9zIHllYXJseSBjb21wZW5zYXRpb25zIGFyZSBzYW1wbGVkIGFuZCB0aGUgZm9sbG93aW5nIGFyZSBmb3VuZCAoaW4gbWlsbGlvbnMpCgoxMiAuNCA1IDIgNTAgOCAzIDEgNCAwLjI1CgpgYGB7cn0Kc2FscyA8LSBjKDEyLCAuNCwgNSwgMiwgNTAsIDgsIDMsIDEsIDQsIDAuMjUpCiMgdGhlIGF2ZXJhZ2UKbWVhbihzYWxzKSAKYGBgCgpgYGB7cn0KIyB0aGUgdmFyaWFuY2UKdmFyKHNhbHMpCmBgYAoKYGBge3J9CiMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbgpzZChzYWxzKQpgYGAKCmBgYHtyfQojIHRoZSBtZWRpYW4KbWVkaWFuKHNhbHMpCmBgYAoKYGBge3J9CiMgVHVrZXkncyBmaXZlIG51bWJlciBzdW1tYXJ5LCB1c2VmdWxsIGZvciBib3hwbG90cwojIGZpdmUgbnVtYmVyczogbWluLCBsb3dlciBoaW5nZSwgbWVkaWFuLCB1cHBlciBoaW5nZSwgbWF4CmZpdmVudW0oc2FscykKYGBgCgpgYGB7cn0KIyBzdW1tYXJ5IHN0YXRpc3RpY3MKc3VtbWFyeShzYWxzKQpgYGAKCiMgSG93IGFib3V0IHRoZSBtb2RlPwoKSW4gUiB3ZSBjYW4gd3JpdGUgb3VyIG93biBmdW5jdGlvbnMsIGFuZCBhIGZpcnN0IGV4YW1wbGUgb2YgYSBmdW5jdGlvbiBpcyBzaG93biBiZWxvdyBpbiBvcmRlciB0byBjb21wdXRlIHRoZSBtb2RlIG9mIGEgdmVjdG9yIG9mIG9ic2VydmF0aW9ucyB4CgpgYGB7cn0KIyBGdW5jdGlvbiB0byBmaW5kIHRoZSBtb2RlLCBpLmUuIG1vc3QgZnJlcXVlbnQgdmFsdWUKZ2V0TW9kZSA8LSBmdW5jdGlvbih4KSB7CiAgICAgdXggPC0gdW5pcXVlKHgpCiAgICAgdXhbd2hpY2gubWF4KHRhYnVsYXRlKG1hdGNoKHgsIHV4KSkpXQogfQpgYGAKCkFzIGFuIGV4YW1wbGUsIHdlIGNhbiB1c2UgdGhlIGZ1bmN0aW9uIGRlZmluZWQgYWJvdmUgdG8gZmluZCB0aGUgbW9zdCBmcmVxdWVudCB2YWx1ZSBvZiB0aGUgbnVtYmVyIG9mIHBpdGNoZXNfYnlfaW5uaW5ncwoKYGBge3J9CiMgTW9zdCBmcmVxdWVudCB2YWx1ZSBpbiBwaXRjaGVzX2J5X2lubmluZ3MKZ2V0TW9kZShwaXRjaGVzX2J5X2lubmluZ3MpCmBgYAoKIyNRdWVzdGlvbl83OiBGaW5kIHRoZSBtb3N0IGZyZXF1ZW50IHZhbHVlIG9mIGhpdHNfcGVyXzlpbm5pbmdzLgoKYGBge3J9CmdldE1vZGUoaGl0c19wZXJfOWlubmluZ3MpCmdldE1vZGUoc3RyaWtlc19ieV9pbm5pbmdzKQpgYGAKCmBgYHtyfQojUXVlc3Rpb25fODogU3VtbWFyaXplIHRoZSBmb2xsb3dpbmcgc3VydmV5IHdpdGggdGhlIGB0YWJsZSgpYCBjb21tYW5kOgojV2hhdCBpcyB5b3VyIGZhdm9yaXRlIGRheSBvZiB0aGUgd2VlayB0byB3YXRjaCBiYXNlYmFsbD8gQSB0b3RhbCBvZiAxMCBmYW5zIHN1Ym1pdHRlZCB0aGlzIHN1cnZleS4KI1NhdHVyZGF5LCBTYXR1cmRheSwgU3VuZGF5LCBNb25kYXksIFNhdHVyZGF5LFR1ZXNkYXksIFN1bmRheSwgRnJpZGF5LCBGcmlkYXksIE1vbmRheQpnYW1lX2RheTwtYygiU2F0dXJkYXkiLCAiU2F0dXJkYXkiLCAiU3VuZGF5IiwgIk1vbmRheSIsICJTYXR1cmRheSIsIlR1ZXNkYXkiLCAiU3VuZGF5IiwgIkZyaWRheSIsICJGcmlkYXkiLCAiTW9uZGF5IikKCnRhYmxlKGdhbWVfZGF5KQpgYGAKCiMjUXVlc3Rpb25fOTogV2hhdCBpcyB0aGUgbW9zdCBmcmVxdWVudCBhbnN3ZXIgcmVjb3JkZWQgaW4gdGhlIHN1cnZleT8gVXNlIHRoZSBnZXRNb2RlIGZ1bmN0aW9uIHRvIGNvbXB1dGUgcmVzdWx0cy4gCgpgYGB7cn0KZ2V0TW9kZShnYW1lX2RheSkKCmBgYAoK