#Addition
2+3
[1] 5
#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(10)
[1] 1
log10(100)
[1] 2
log(10,base=5)
[1] 1.430677
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
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?
#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)/(AB+BB+HBP+SF)
OBP
[1] 0.35
Often you will want to test whether something is less than, greater
than or equal to something.
3 == 8# Does 3 equals 8? FALSE
[1] FALSE
3 != 8# Is 3 different from 8? TRUE
[1] TRUE
3 <= 8# Is 3 less than or equal to 8? TRUE
[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
ls()
[1] "AB" "BA" "bar" "barsample"
[5] "Batting_Average" "BB" "game_day" "getMode"
[9] "H" "HBP" "hits_per_9innings" "n"
[13] "OBP" "On_Base_Percentage" "pitches_by_innings" "player_positions"
[17] "runs_per_9innings" "sals" "samplerows" "SF"
[21] "strikes_by_innings" "Total_Bases" "x"
rm(Total_Bases)
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(1, 2, 3, 4, 5)
hits_per_9innings <- c(1, 2, 3, 4, 5)
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+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] 1
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] 5
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] 2 10 8 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] 10 2 3 8 1
The variable sample rows 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
10 J 10
2 B 2
3 C 3
8 H 8
1 A 1
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 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
# 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] 1
#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"
LS0tCnRpdGxlOiAiQWN0aXZpdHkgNCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CiNBZGRpdGlvbgoyKzMKCmBgYAoKCmBgYHtyfQojRGl2aXNpb24KMi8zCmBgYAoKCmBgYHtyfQojRXhwb25lbnRpYXRpb24KMl4zCmBgYAoKCmBgYHtyfQojU3F1YXJlIHJvb3QKc3FydCgyKQpgYGAKCgpgYGB7cn0KI0xvZ2FyaXRobXMKbG9nKDIpCmBgYAoKCmBgYHtyfQojUXVlc3Rpb25fMTogQ29tcHV0ZSB0aGUgbG9nIGJhc2UgNSBvZiAxMCBhbmQgdGhlIGxvZyBvZiAxMC4KbG9nMTAoMTApCmxvZzEwKDEwMCkKbG9nKDEwLGJhc2U9NSkKCmBgYAoKQ29tcHV0aW5nIHNvbWUgb2ZmZW5zaXZlIG1ldHJpY3MgaW4gQmFzZWJhbGwKYGBge3J9CiNCYXR0aW5nIEF2ZXJhZ2U9KE5vLiBvZiBIaXRzKS8oTm8uIG9mIEF0IEJhdHMpCiNXaGF0IGlzIHRoZSBiYXR0aW5nIGF2ZXJhZ2Ugb2YgYSBwbGF5ZXIgdGhhdCBiYXRzIDI5IGhpdHMgaW4gMTEyIGF0IGJhdHM/CkJBPSgyOSkvKDExMikKQkEKYGBgCgoKYGBge3J9CkJBCkJhdHRpbmdfQXZlcmFnZT1yb3VuZChCQSxkaWdpdHMgPSAzKQpCYXR0aW5nX0F2ZXJhZ2UKYGBgCgoKYGBge3J9CiNRdWVzdGlvbl8yOldoYXQgaXMgdGhlIGJhdHRpbmcgYXZlcmFnZSBvZiBhIHBsYXllciB0aGF0IGJhdHMgNDIgaGl0cyBpbiAyMTIgYXQgYmF0cz8KCiNPbiBCYXNlIFBlcmNlbnRhZ2UKI09CUD0oSCtCQitIQlApLyhBdCBCYXRzK0JCK0hCUCtTRikKI0xldCB1cyBjb21wdXRlIHRoZSBPQlAgZm9yIGEgcGxheWVyIHdpdGggdGhlIGZvbGxvd2luZyBnZW5lcmFsIHN0YXRzCiNBQj01MTUsSD0xNzIsQkI9ODQsSEJQPTUsU0Y9NgpPQlA9KDE3Mis4NCs1KS8oNTE1Kzg0KzUrNikKT0JQCmBgYAoKCmBgYHtyfQpPbl9CYXNlX1BlcmNlbnRhZ2U9cm91bmQoT0JQLGRpZ2l0cyA9IDMpCk9uX0Jhc2VfUGVyY2VudGFnZQpgYGAKCgpgYGB7cn0KI1F1ZXN0aW9uXzM6Q29tcHV0ZSB0aGUgT0JQIGZvciBhIHBsYXllciB3aXRoIHRoZSBmb2xsb3dpbmcgZ2VuZXJhbCBzdGF0czoKQUI9NTY1Ckg9MTU2CkJCPTY1CkhCUD0zClNGPTcKCk9CUD0oSCtCQitIQlApLyhBQitCQitIQlArU0YpCk9CUApgYGAKCk9mdGVuIHlvdSB3aWxsIHdhbnQgdG8gdGVzdCB3aGV0aGVyIHNvbWV0aGluZyBpcyBsZXNzIHRoYW4sIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBzb21ldGhpbmcuCgoKYGBge3J9CjMgPT0gOCMgRG9lcyAzIGVxdWFscyA4PyBGQUxTRQpgYGAKCgpgYGB7cn0KMyAhPSA4IyBJcyAzIGRpZmZlcmVudCBmcm9tIDg/IFRSVUUKYGBgCgoKYGBge3J9CjMgPD0gOCMgSXMgMyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gOD8gVFJVRQpgYGAKCgpgYGB7cn0KMz40CmBgYAoKVGhlIGxvZ2ljYWwgb3BlcmF0b3JzIGFyZSAmIGZvciBsb2dpY2FsIEFORCwgfCBmb3IgbG9naWNhbCBPUiwgYW5kICEgZm9yIE5PVC4gVGhlc2UgYXJlIHNvbWUgZXhhbXBsZXM6CgpgYGB7cn0KIyBMb2dpY2FsIERpc2p1bmN0aW9uIChvcikKRkFMU0UgfCBGQUxTRSAjIEZhbHNlIE9SIEZhbHNlCmBgYAoKCmBgYHtyfQojIExvZ2ljYWwgQ29uanVuY3Rpb24gKGFuZCkKVFJVRSAmIEZBTFNFICNUcnVlIEFORCBGYWxzZQpgYGAKCgpgYGB7cn0KIyBOZWdhdGlvbgohIEZBTFNFICMgTm90IEZhbHNlCmBgYAoKCmBgYHtyfQojIENvbWJpbmF0aW9uIG9mIHN0YXRlbWVudHMKMiA8IDMgfCAxID09IDUgIyAyPDMgaXMgVHJ1ZSwgMT09NSBpcyBGYWxzZSwgVHJ1ZSBPUiBGYWxzZSBpcyBUcnVlCmBgYAoKQXNzaWduaW5nIFZhbHVlcyB0byBWYXJpYWJsZXMKSW4gUiwgeW91IGNyZWF0ZSBhIHZhcmlhYmxlIGFuZCBhc3NpZ24gaXQgYSB2YWx1ZSB1c2luZyA8LSBhcyBmb2xsb3dzCgpgYGB7cn0KVG90YWxfQmFzZXMgPC0gNiArIDUKVG90YWxfQmFzZXMqMwpgYGAKCgpgYGB7cn0KbHMoKQpgYGAKCgpgYGB7cn0Kcm0oVG90YWxfQmFzZXMpCmBgYAoKVmVjdG9ycwpUaGUgYmFzaWMgdHlwZSBvZiBvYmplY3QgaW4gUiBpcyBhIHZlY3Rvciwgd2hpY2ggaXMgYW4gb3JkZXJlZCBsaXN0IG9mIHZhbHVlcyBvZiB0aGUgc2FtZSB0eXBlLiBZb3UgY2FuIGNyZWF0ZSBhIHZlY3RvciB1c2luZyB0aGUgYygpIGZ1bmN0aW9uIChhcyBpbiDigJxjb25jYXRlbmF0ZeKAnSkuCgpgYGB7cn0KcGl0Y2hlc19ieV9pbm5pbmdzIDwtIGMoMTIsIDE1LCAxMCwgMjAsIDEwKSAKcGl0Y2hlc19ieV9pbm5pbmdzCmBgYAoKCmBgYHtyfQpzdHJpa2VzX2J5X2lubmluZ3MgPC0gYyg5LCAxMiwgNiwgMTQsIDkpCnN0cmlrZXNfYnlfaW5uaW5ncwpgYGAKCgpgYGB7cn0KI1F1ZXN0aW9uXzQ6IERlZmluZSB0d28gdmVjdG9ycyxydW5zX3Blcl85aW5uaW5ncyBhbmQgaGl0c19wZXJfOWlubmluZ3MsIGVhY2ggd2l0aCBmaXZlIGVsZW1lbnRzLiAKcnVuc19wZXJfOWlubmluZ3MgPC0gYygxLCAyLCAzLCA0LCA1KQoKaGl0c19wZXJfOWlubmluZ3MgPC0gYygxLCAyLCAzLCA0LCA1KQpgYGAKClRoZXJlIGFyZSBhbHNvIHNvbWUgZnVuY3Rpb25zIHRoYXQgd2lsbCBjcmVhdGUgdmVjdG9ycyB3aXRoIHJlZ3VsYXIgcGF0dGVybnMsIGxpa2UgcmVwZWF0ZWQgZWxlbWVudHMuCgpgYGB7cn0KIyByZXBsaWNhdGUgZnVuY3Rpb24KcmVwKDIsIDUpCmBgYAoKCmBgYHtyfQpyZXAoMSw0KQpgYGAKCgpgYGB7cn0KIyBjb25zZWN1dGl2ZSBudW1iZXJzCjE6NQpgYGAKCgpgYGB7cn0KMjoxMApgYGAKCgpgYGB7cn0KIyBzZXF1ZW5jZSBmcm9tIDEgdG8gMTAgd2l0aCBhIHN0ZXAgb2YgMgpzZXEoMSwgMTAsIGJ5PTIpCmBgYAoKCmBgYHtyfQpzZXEoMiwxMyxieT0zKQpgYGAKCk1hbnkgZnVuY3Rpb25zIGFuZCBvcGVyYXRvcnMgbGlrZSArIG9yIC0gd2lsbCB3b3JrIG9uIGFsbCBlbGVtZW50cyBvZiB0aGUgdmVjdG9yLgoKYGBge3J9CiMgYWRkIHZlY3RvcnMKcGl0Y2hlc19ieV9pbm5pbmdzK3N0cmlrZXNfYnlfaW5uaW5ncwpgYGAKCgpgYGB7cn0KIyBjb21wYXJlIHZlY3RvcnMKcGl0Y2hlc19ieV9pbm5pbmdzID09IHN0cmlrZXNfYnlfaW5uaW5ncwpgYGAKCgpgYGB7cn0KIyBmaW5kIGxlbmd0aCBvZiB2ZWN0b3IKbGVuZ3RoKHBpdGNoZXNfYnlfaW5uaW5ncykKYGBgCgoKYGBge3J9CiMgZmluZCBtaW5pbXVtIHZhbHVlIGluIHZlY3RvcgptaW4ocGl0Y2hlc19ieV9pbm5pbmdzKQpgYGAKCgoKYGBge3J9CiMgZmluZCBhdmVyYWdlIHZhbHVlIGluIHZlY3RvcgptZWFuKHBpdGNoZXNfYnlfaW5uaW5ncykKYGBgCgpZb3UgY2FuIGFjY2VzcyBwYXJ0cyBvZiBhIHZlY3RvciBieSB1c2luZyBbLiBSZWNhbGwgd2hhdCB0aGUgdmFsdWUgaXMgb2YgdGhlIHZlY3RvciBwaXRjaGVzX2J5X2lubmluZ3MuCgpgYGB7cn0KcGl0Y2hlc19ieV9pbm5pbmdzCmBgYAoKCmBgYHtyfQojIElmIHlvdSB3YW50IHRvIGdldCB0aGUgZmlyc3QgZWxlbWVudDoKcGl0Y2hlc19ieV9pbm5pbmdzWzFdCmBgYAoKCmBgYHtyfQojUXVlc3Rpb25fNTogR2V0IHRoZSBmaXJzdCBlbGVtZW50IG9mIGhpdHNfcGVyXzlpbm5pbmdzLgoKaGl0c19wZXJfOWlubmluZ3NbMV0KYGBgCgpJZiB5b3Ugd2FudCB0byBnZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBwaXRjaGVzX2J5X2lubmluZ3Mgd2l0aG91dCBleHBsaWNpdGx5IHR5cGluZyB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIG9mIHBpdGNoZXNfYnlfaW5uaW5ncywgbWFrZSB1c2Ugb2YgdGhlIGxlbmd0aCBmdW5jdGlvbiwgd2hpY2ggY2FsY3VsYXRlcyB0aGUgbGVuZ3RoIG9mIGEgdmVjdG9yOgoKYGBge3J9CnBpdGNoZXNfYnlfaW5uaW5nc1tsZW5ndGgocGl0Y2hlc19ieV9pbm5pbmdzKV0KYGBgCgoKYGBge3J9CiNRdWVzdGlvbl82OiBHZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBoaXRzX3Blcl85aW5uaW5ncy4KaGl0c19wZXJfOWlubmluZ3NbbGVuZ3RoKGhpdHNfcGVyXzlpbm5pbmdzKV0KYGBgCgpZb3UgY2FuIGFsc28gZXh0cmFjdCBtdWx0aXBsZSB2YWx1ZXMgZnJvbSBhIHZlY3Rvci4gRm9yIGluc3RhbmNlIHRvIGdldCB0aGUgMm5kIHRocm91Z2ggNHRoIHZhbHVlcyB1c2UKCmBgYHtyfQpwaXRjaGVzX2J5X2lubmluZ3NbYygyLCAzLCA0KV0KYGBgCgpWZWN0b3JzIGNhbiBhbHNvIGJlIHN0cmluZ3Mgb3IgbG9naWNhbCB2YWx1ZXMKCmBgYHtyfQpwbGF5ZXJfcG9zaXRpb25zIDwtIGMoImNhdGNoZXIiLCAicGl0Y2hlciIsICJpbmZpZWxkZXJzIiwgIm91dGZpZWxkZXJzIikKYGBgCgpEYXRhIEZyYW1lcwpJbiBzdGF0aXN0aWNhbCBhcHBsaWNhdGlvbnMsIGRhdGEgaXMgb2Z0ZW4gc3RvcmVkIGFzIGEgZGF0YSBmcmFtZSwgd2hpY2ggaXMgbGlrZSBhIHNwcmVhZHNoZWV0LCB3aXRoIHJvd3MgYXMgb2JzZXJ2YXRpb25zIGFuZCBjb2x1bW5zIGFzIHZhcmlhYmxlcy4KClRvIG1hbnVhbGx5IGNyZWF0ZSBhIGRhdGEgZnJhbWUsIHVzZSB0aGUgZGF0YS5mcmFtZSgpIGZ1bmN0aW9uLgoKYGBge3J9CmRhdGEuZnJhbWUoYm9udXMgPSBjKDIsIDMsIDEpLCNpbiBtaWxsaW9ucyAKICAgICAgICAgICBhY3RpdmVfcm9zdGVyID0gYygieWVzIiwgIm5vIiwgInllcyIpLCAKICAgICAgICAgICBzYWxhcnkgPSBjKDEuNSwgMi41LCAxKSkjaW4gbWlsbGlvbnMgCmBgYAoKTW9zdCBvZnRlbiB5b3Ugd2lsbCBiZSB1c2luZyBkYXRhIGZyYW1lcyBsb2FkZWQgZnJvbSBhIGZpbGUuIEZvciBleGFtcGxlLCBsb2FkIHRoZSByZXN1bHRzIG9mIGEgZmFu4oCZcyBzdXJ2ZXkuIFRoZSBmdW5jdGlvbiBsb2FkIG9yIHJlYWQudGFibGUgY2FuIGJlIHVzZWQgZm9yIHRoaXMuCgpIb3cgdG8gTWFrZSBhIFJhbmRvbSBTYW1wbGUKVG8gcmFuZG9tbHkgc2VsZWN0IGEgc2FtcGxlIHVzZSB0aGUgZnVuY3Rpb24gc2FtcGxlKCkuIFRoZSBmb2xsb3dpbmcgY29kZSBzZWxlY3RzIDUgbnVtYmVycyBiZXR3ZWVuIDEgYW5kIDEwIGF0IHJhbmRvbSAod2l0aG91dCBkdXBsaWNhdGlvbikKCmBgYHtyfQpzYW1wbGUoMToxMCwgc2l6ZT01KQpgYGAKClRoZSBmaXJzdCBhcmd1bWVudCBnaXZlcyB0aGUgdmVjdG9yIG9mIGRhdGEgdG8gc2VsZWN0IGVsZW1lbnRzIGZyb20uClRoZSBzZWNvbmQgYXJndW1lbnQgKHNpemU9KSBnaXZlcyB0aGUgc2l6ZSBvZiB0aGUgc2FtcGxlIHRvIHNlbGVjdC4KVGFraW5nIGEgc2ltcGxlIHJhbmRvbSBzYW1wbGUgZnJvbSBhIGRhdGEgZnJhbWUgaXMgb25seSBzbGlnaHRseSBtb3JlIGNvbXBsaWNhdGVkLCBoYXZpbmcgdHdvIHN0ZXBzOgoKVXNlIHNhbXBsZSgpIHRvIHNlbGVjdCBhIHNhbXBsZSBvZiBzaXplIG4gZnJvbSBhIHZlY3RvciBvZiB0aGUgcm93IG51bWJlcnMgb2YgdGhlIGRhdGEgZnJhbWUuClVzZSB0aGUgaW5kZXggb3BlcmF0b3IgWyB0byBzZWxlY3QgdGhvc2Ugcm93cyBmcm9tIHRoZSBkYXRhIGZyYW1lLgpDb25zaWRlciB0aGUgZm9sbG93aW5nIGV4YW1wbGUgd2l0aCBmYWtlIGRhdGEuIEZpcnN0LCBtYWtlIHVwIGEgZGF0YSBmcmFtZSB3aXRoIHR3byBjb2x1bW5zLiAoTEVUVEVSUyBpcyBhIGNoYXJhY3RlciB2ZWN0b3Igb2YgbGVuZ3RoIDI2IHdpdGggY2FwaXRhbCBsZXR0ZXJzIMOiwoDCnEHDosKAwp0gdG8gw6LCgMKcWsOiwoDCnTsgTEVUVEVSUyBpcyBhdXRvbWF0aWNhbGx5IGRlZmluZWQgYW5kIHByZS1sb2FkZWQgaW4gUikKCmBgYHtyfQpiYXIgPC0gZGF0YS5mcmFtZSh2YXIxID0gTEVUVEVSU1sxOjEwXSwgdmFyMiA9IDE6MTApCiMgQ2hlY2sgZGF0YSBmcmFtZQpiYXIKYGBgCgpTdXBwb3NlIHlvdSB3YW50IHRvIHNlbGVjdCBhIHJhbmRvbSBzYW1wbGUgb2Ygc2l6ZSA1LiBGaXJzdCwgZGVmaW5lIGEgdmFyaWFibGUgbiB3aXRoIHRoZSBzaXplIG9mIHRoZSBzYW1wbGUsIGkuZS4gNQoKYGBge3J9Cm4gPC0gNQpgYGAKCk5vdywgc2VsZWN0IGEgc2FtcGxlIG9mIHNpemUgNSBmcm9tIHRoZSB2ZWN0b3Igd2l0aCAxIHRvIDEwICh0aGUgbnVtYmVyIG9mIHJvd3MgaW4gYmFyKS4gVXNlIHRoZSBmdW5jdGlvbiBucm93KCkgdG8gZmluZCB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gYmFyIGluc3RlYWQgb2YgbWFudWFsbHkgZW50ZXJpbmcgdGhhdCBudW1iZXIuCgpVc2UgOiB0byBjcmVhdGUgYSB2ZWN0b3Igd2l0aCBhbGwgdGhlIGludGVnZXJzIGJldHdlZW4gMSBhbmQgdGhlIG51bWJlciBvZiByb3dzIGluIGJhci4KCmBgYHtyfQpzYW1wbGVyb3dzIDwtIHNhbXBsZSgxOm5yb3coYmFyKSwgc2l6ZT1uKSAKIyBwcmludCBzYW1wbGUgcm93cwpzYW1wbGVyb3dzCmBgYAoKVGhlIHZhcmlhYmxlIHNhbXBsZSByb3dzIGNvbnRhaW5zIHRoZSByb3dzIG9mIGJhciB3aGljaCBtYWtlIGEgcmFuZG9tIHNhbXBsZSBmcm9tIGFsbCB0aGUgcm93cyBpbiBiYXIuIEV4dHJhY3QgdGhvc2Ugcm93cyBmcm9tIGJhciB3aXRoCgpgYGB7cn0KIyBleHRyYWN0IHJvd3MKYmFyc2FtcGxlIDwtIGJhcltzYW1wbGVyb3dzLCBdCiMgcHJpbnQgc2FtcGxlCnByaW50KGJhcnNhbXBsZSkKYGBgCgpUaGUgY29kZSBhYm92ZSBjcmVhdGVzIGEgbmV3IGRhdGEgZnJhbWUgY2FsbGVkIGJhcnNhbXBsZSB3aXRoIGEgcmFuZG9tIHNhbXBsZSBvZiByb3dzIGZyb20gYmFyLgpJbiBhIHNpbmdsZSBsaW5lIG9mIGNvZGU6CgpgYGB7cn0KYmFyW3NhbXBsZSgxOm5yb3coYmFyKSwgbiksIF0KYGBgCgpVc2luZyBUYWJsZXMKVGhlIHRhYmxlKCkgY29tbWFuZCBhbGxvd3MgdXMgdG8gbG9vayBhdCB0YWJsZXMuIEl0cyBzaW1wbGVzdCB1c2FnZSBsb29rcyBsaWtlIHRhYmxlKHgpIHdoZXJlIHggaXMgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZS4KCkZvciBleGFtcGxlLCBhIHN1cnZleSBhc2tzIHBlb3BsZSBpZiB0aGV5IHN1cHBvcnQgdGhlIGhvbWUgdGVhbSBvciBub3QuIFRoZSBkYXRhIGlzCgpZZXMsIE5vLCBObywgWWVzLCBZZXMKCldlIGNhbiBlbnRlciB0aGlzIGludG8gUiB3aXRoIHRoZSBjKCkgY29tbWFuZCwgYW5kIHN1bW1hcml6ZSB3aXRoIHRoZSB0YWJsZSgpIGNvbW1hbmQgYXMgZm9sbG93cwoKYGBge3J9CnggPC0gYygiWWVzIiwiTm8iLCJObyIsIlllcyIsIlllcyIpIAp0YWJsZSh4KQpgYGAKCk51bWVyaWNhbCBtZWFzdXJlcyBvZiBjZW50ZXIgYW5kIHNwcmVhZApTdXBwb3NlLCBNTEIgVGVhbXPigJkgQ0VPcyB5ZWFybHkgY29tcGVuc2F0aW9ucyBhcmUgc2FtcGxlZCBhbmQgdGhlIGZvbGxvd2luZyBhcmUgZm91bmQgKGluIG1pbGxpb25zKQoKMTIgLjQgNSAyIDUwIDggMyAxIDQgMC4yNQoKYGBge3J9CnNhbHMgPC0gYygxMiwgLjQsIDUsIDIsIDUwLCA4LCAzLCAxLCA0LCAwLjI1KQojIHRoZSBhdmVyYWdlCm1lYW4oc2FscykgCmBgYAoKCmBgYHtyfQojIHRoZSB2YXJpYW5jZQp2YXIoc2FscykKYGBgCgoKYGBge3J9CiMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbgpzZChzYWxzKQpgYGAKCgpgYGB7cn0KIyB0aGUgbWVkaWFuCm1lZGlhbihzYWxzKQpgYGAKCgpgYGB7cn0KIyBUdWtleSdzIGZpdmUgbnVtYmVyIHN1bW1hcnksIHVzZWZ1bGwgZm9yIGJveHBsb3RzCiMgZml2ZSBudW1iZXJzOiBtaW4sIGxvd2VyIGhpbmdlLCBtZWRpYW4sIHVwcGVyIGhpbmdlLCBtYXgKZml2ZW51bShzYWxzKQpgYGAKCgpgYGB7cn0KIyBzdW1tYXJ5IHN0YXRpc3RpY3MKc3VtbWFyeShzYWxzKQpgYGAKCkhvdyBhYm91dCB0aGUgbW9kZT8KSW4gUiB3ZSBjYW4gd3JpdGUgb3VyIG93biBmdW5jdGlvbnMsIGFuZCBhIGZpcnN0IGV4YW1wbGUgb2YgYSBmdW5jdGlvbiBpcyBzaG93biBiZWxvdyBpbiBvcmRlciB0byBjb21wdXRlIHRoZSBtb2RlIG9mIGEgdmVjdG9yIG9mIG9ic2VydmF0aW9ucwoKYGBge3J9CiMgRnVuY3Rpb24gdG8gZmluZCB0aGUgbW9kZSwgaS5lLiBtb3N0IGZyZXF1ZW50IHZhbHVlCmdldE1vZGUgPC0gZnVuY3Rpb24oeCkgewogICAgIHV4IDwtIHVuaXF1ZSh4KQogICAgIHV4W3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LCB1eCkpKV0KIH0KYGBgCgpBcyBhbiBleGFtcGxlLCB3ZSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBkZWZpbmVkIGFib3ZlIHRvIGZpbmQgdGhlIG1vc3QgZnJlcXVlbnQgdmFsdWUgb2YgdGhlIG51bWJlciBvZiBwaXRjaGVzX2J5X2lubmluZ3MKCmBgYHtyfQojIE1vc3QgZnJlcXVlbnQgdmFsdWUgaW4gcGl0Y2hlc19ieV9pbm5pbmdzCmdldE1vZGUocGl0Y2hlc19ieV9pbm5pbmdzKQpgYGAKCgpgYGB7cn0KI1F1ZXN0aW9uXzc6IEZpbmQgdGhlIG1vc3QgZnJlcXVlbnQgdmFsdWUgb2YgaGl0c19wZXJfOWlubmluZ3MuCmdldE1vZGUoaGl0c19wZXJfOWlubmluZ3MpCmBgYAoKCmBgYHtyfQojUXVlc3Rpb25fODogU3VtbWFyaXplIHRoZSBmb2xsb3dpbmcgc3VydmV5IHdpdGggdGhlIGB0YWJsZSgpYCBjb21tYW5kOgojV2hhdCBpcyB5b3VyIGZhdm9yaXRlIGRheSBvZiB0aGUgd2VlayB0byB3YXRjaCBiYXNlYmFsbD8gQSB0b3RhbCBvZiAxMCBmYW5zIHN1Ym1pdHRlZCB0aGlzIHN1cnZleS4KI1NhdHVyZGF5LCBTYXR1cmRheSwgU3VuZGF5LCBNb25kYXksIFNhdHVyZGF5LFR1ZXNkYXksIFN1bmRheSwgRnJpZGF5LCBGcmlkYXksIE1vbmRheQpnYW1lX2RheTwtYygiU2F0dXJkYXkiLCAiU2F0dXJkYXkiLCAiU3VuZGF5IiwgIk1vbmRheSIsICJTYXR1cmRheSIsIlR1ZXNkYXkiLCAiU3VuZGF5IiwgIkZyaWRheSIsICJGcmlkYXkiLCAiTW9uZGF5IikKCnRhYmxlKGdhbWVfZGF5KQpgYGAKCgpgYGB7cn0KI1F1ZXN0aW9uXzk6IFdoYXQgaXMgdGhlIG1vc3QgZnJlcXVlbnQgYW5zd2VyIHJlY29yZGVkIGluIHRoZSBzdXJ2ZXk/IFVzZSB0aGUgZ2V0TW9kZSBmdW5jdGlvbiB0byBjb21wdXRlIHJlc3VsdHMuIApnZXRNb2RlKGdhbWVfZGF5KQpgYGAKCgoKCgoK