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.

# log base 5 of 10
log(10, base = 5)
[1] 1.430677
# natural log of 10
log(10)
[1] 2.302585

Computing some offensive metrics in Baseball

Batting Average

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_2 <- 42 / 212
BA_2
[1] 0.1981132
Batting_Average_2 <- round(BA_2, digits = 3)
Batting_Average_2
[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_2 <- (156 + 65 + 3) / (565 + 65 + 3 + 7)
OBP_2
[1] 0.35
On_Base_Percentage_2 <- round(OBP_2, digits = 3)
On_Base_Percentage_2
[1] 0.35

Logical comparisons

Often you will want to test whether something is less than, greater than, or equal to something.

3 == 8 # Does 3 equal 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 # 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"                   "BA_2"                 "bar"                  "barsample"           
 [5] "Batting_Average"      "Batting_Average_2"    "course"               "hits_per_9innings"   
 [9] "n"                    "name"                 "OBP"                  "OBP_2"               
[13] "On_Base_Percentage"   "On_Base_Percentage_2" "pitches_by_innings"   "runs_per_9innings"   
[17] "samplerows"           "scores"               "strikes_by_innings"   "students"            
[21] "teams"                "Total_Bases"          "x"                    "y"                   

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 it 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(4, 3, 5, 2, 6)
hits_per_9innings <- c(8, 7, 10, 6, 9)

runs_per_9innings
[1] 4 3 5 2 6
hits_per_9innings
[1]  8  7 10  6  9

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] 8

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] 9

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")
player_positions
[1] "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] 4 6 8 2 5

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:

  1. Use sample() to select a sample of size n from a vector of the row numbers of the data frame.
  2. 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]  3  6  8  1 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)
   var1 var2
3     C    3
6     F    6
8     H    8
1     A    1
10    J   10

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, 0.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, useful 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] 8

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"
LS0tCnRpdGxlOiAiQWN0aXZpdHkgNDogRmlyc3QgU3RlcHMgd2l0aCBSIgphdXRob3I6ICJKdWxpbyBIZXJuYW5kZXoiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAotLS0KCiMgQWRkaXRpb24KCmBgYHtyfQoyIC0gMwpgYGAKCiMgRGl2aXNpb24KCmBgYHtyfQoyIC8gMwpgYGAKCiMgRXhwb25lbnRpYXRpb24KCmBgYHtyfQoyXjMKYGBgCgojIFNxdWFyZSByb290CgpgYGB7cn0Kc3FydCgyKQpgYGAKCiMgTG9nYXJpdGhtcwoKYGBge3J9CmxvZygyKQpgYGAKCiMgUXVlc3Rpb24gMQoKQ29tcHV0ZSB0aGUgbG9nIGJhc2UgNSBvZiAxMCBhbmQgdGhlIGxvZyBvZiAxMC4KCmBgYHtyfQojIGxvZyBiYXNlIDUgb2YgMTAKbG9nKDEwLCBiYXNlID0gNSkKCiMgbmF0dXJhbCBsb2cgb2YgMTAKbG9nKDEwKQpgYGAKCiMgQ29tcHV0aW5nIHNvbWUgb2ZmZW5zaXZlIG1ldHJpY3MgaW4gQmFzZWJhbGwKCiMjIEJhdHRpbmcgQXZlcmFnZQoKQmF0dGluZyBBdmVyYWdlID0gTm8uIG9mIEhpdHMgLyBOby4gb2YgQXQgQmF0cwoKV2hhdCBpcyB0aGUgYmF0dGluZyBhdmVyYWdlIG9mIGEgcGxheWVyIHRoYXQgYmF0cyAyOSBoaXRzIGluIDExMiBhdCBiYXRzPwoKYGBge3J9CkJBIDwtIDI5IC8gMTEyCkJBCgpCYXR0aW5nX0F2ZXJhZ2UgPC0gcm91bmQoQkEsIGRpZ2l0cyA9IDMpCkJhdHRpbmdfQXZlcmFnZQpgYGAKCiMgUXVlc3Rpb24gMgoKV2hhdCBpcyB0aGUgYmF0dGluZyBhdmVyYWdlIG9mIGEgcGxheWVyIHRoYXQgYmF0cyA0MiBoaXRzIGluIDIxMiBhdCBiYXRzPwoKYGBge3J9CkJBXzIgPC0gNDIgLyAyMTIKQkFfMgoKQmF0dGluZ19BdmVyYWdlXzIgPC0gcm91bmQoQkFfMiwgZGlnaXRzID0gMykKQmF0dGluZ19BdmVyYWdlXzIKYGBgCgojIyBPbiBCYXNlIFBlcmNlbnRhZ2UKCk9CUCA9IChIICsgQkIgKyBIQlApIC8gKEF0IEJhdHMgKyBCQiArIEhCUCArIFNGKQoKTGV0IHVzIGNvbXB1dGUgdGhlIE9CUCBmb3IgYSBwbGF5ZXIgd2l0aCB0aGUgZm9sbG93aW5nIGdlbmVyYWwgc3RhdHM6CgpBQiA9IDUxNSwgSCA9IDE3MiwgQkIgPSA4NCwgSEJQID0gNSwgU0YgPSA2CgpgYGB7cn0KT0JQIDwtICgxNzIgKyA4NCArIDUpIC8gKDUxNSArIDg0ICsgNSArIDYpCk9CUAoKT25fQmFzZV9QZXJjZW50YWdlIDwtIHJvdW5kKE9CUCwgZGlnaXRzID0gMykKT25fQmFzZV9QZXJjZW50YWdlCmBgYAoKIyBRdWVzdGlvbiAzCgpDb21wdXRlIHRoZSBPQlAgZm9yIGEgcGxheWVyIHdpdGggdGhlIGZvbGxvd2luZyBnZW5lcmFsIHN0YXRzOgoKQUIgPSA1NjUsIEggPSAxNTYsIEJCID0gNjUsIEhCUCA9IDMsIFNGID0gNwoKYGBge3J9Ck9CUF8yIDwtICgxNTYgKyA2NSArIDMpIC8gKDU2NSArIDY1ICsgMyArIDcpCk9CUF8yCgpPbl9CYXNlX1BlcmNlbnRhZ2VfMiA8LSByb3VuZChPQlBfMiwgZGlnaXRzID0gMykKT25fQmFzZV9QZXJjZW50YWdlXzIKYGBgCgojIExvZ2ljYWwgY29tcGFyaXNvbnMKCk9mdGVuIHlvdSB3aWxsIHdhbnQgdG8gdGVzdCB3aGV0aGVyIHNvbWV0aGluZyBpcyBsZXNzIHRoYW4sIGdyZWF0ZXIgdGhhbiwgb3IgZXF1YWwgdG8gc29tZXRoaW5nLgoKYGBge3J9CjMgPT0gOCAjIERvZXMgMyBlcXVhbCA4PwozICE9IDggIyBJcyAzIGRpZmZlcmVudCBmcm9tIDg/CjMgPD0gOCAjIElzIDMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIDg/CjMgPiA0CmBgYAoKVGhlIGxvZ2ljYWwgb3BlcmF0b3JzIGFyZSBgJmAgZm9yIGxvZ2ljYWwgQU5ELCBgfGAgZm9yIGxvZ2ljYWwgT1IsIGFuZCBgIWAgZm9yIE5PVC4gVGhlc2UgYXJlIHNvbWUgZXhhbXBsZXM6CgpgYGB7cn0KIyBMb2dpY2FsIERpc2p1bmN0aW9uIChvcikKRkFMU0UgfCBGQUxTRSAjIEZhbHNlIE9SIEZhbHNlCgojIExvZ2ljYWwgQ29uanVuY3Rpb24gKGFuZCkKVFJVRSAmIEZBTFNFICMgVHJ1ZSBBTkQgRmFsc2UKCiMgTmVnYXRpb24KIUZBTFNFICMgTm90IEZhbHNlCgojIENvbWJpbmF0aW9uIG9mIHN0YXRlbWVudHMKMiA8IDMgfCAxID09IDUgIyBUcnVlIE9SIEZhbHNlIGlzIFRydWUKYGBgCgojIEFzc2lnbmluZyBWYWx1ZXMgdG8gVmFyaWFibGVzCgpJbiBSLCB5b3UgY3JlYXRlIGEgdmFyaWFibGUgYW5kIGFzc2lnbiBpdCBhIHZhbHVlIHVzaW5nIGA8LWAgYXMgZm9sbG93czoKCmBgYHtyfQpUb3RhbF9CYXNlcyA8LSA2ICsgNQpUb3RhbF9CYXNlcyAqIDMKYGBgCgpUbyBzZWUgdGhlIHZhcmlhYmxlcyB0aGF0IGFyZSBjdXJyZW50bHkgZGVmaW5lZCwgdXNlIGBscygpYCBhcyBpbiDigJxsaXN04oCdLgoKYGBge3J9CmxzKCkKYGBgCgpUbyBkZWxldGUgYSB2YXJpYWJsZSwgdXNlIGBybSgpYCBhcyBpbiDigJxyZW1vdmXigJ0uCgpgYGB7cn0Kcm0oVG90YWxfQmFzZXMpCmBgYAoKRWl0aGVyIGA8LWAgb3IgYD1gIGNhbiBiZSB1c2VkIHRvIGFzc2lnbiBhIHZhbHVlIHRvIGEgdmFyaWFibGUsIGJ1dCBJIHByZWZlciBgPC1gIGJlY2F1c2UgaXQgaXMgbGVzcyBsaWtlbHkgdG8gYmUgY29uZnVzZWQgd2l0aCB0aGUgbG9naWNhbCBvcGVyYXRvciBgPT1gLgoKIyBWZWN0b3JzCgpUaGUgYmFzaWMgdHlwZSBvZiBvYmplY3QgaW4gUiBpcyBhIHZlY3Rvciwgd2hpY2ggaXMgYW4gb3JkZXJlZCBsaXN0IG9mIHZhbHVlcyBvZiB0aGUgc2FtZSB0eXBlLiBZb3UgY2FuIGNyZWF0ZSBhIHZlY3RvciB1c2luZyB0aGUgYGMoKWAgZnVuY3Rpb24sIGFzIGluIOKAnGNvbmNhdGVuYXRl4oCdLgoKYGBge3J9CnBpdGNoZXNfYnlfaW5uaW5ncyA8LSBjKDEyLCAxNSwgMTAsIDIwLCAxMCkKcGl0Y2hlc19ieV9pbm5pbmdzCgpzdHJpa2VzX2J5X2lubmluZ3MgPC0gYyg5LCAxMiwgNiwgMTQsIDkpCnN0cmlrZXNfYnlfaW5uaW5ncwpgYGAKCiMgUXVlc3Rpb24gNAoKRGVmaW5lIHR3byB2ZWN0b3JzLCBgcnVuc19wZXJfOWlubmluZ3NgIGFuZCBgaGl0c19wZXJfOWlubmluZ3NgLCBlYWNoIHdpdGggZml2ZSBlbGVtZW50cy4KCmBgYHtyfQpydW5zX3Blcl85aW5uaW5ncyA8LSBjKDQsIDMsIDUsIDIsIDYpCmhpdHNfcGVyXzlpbm5pbmdzIDwtIGMoOCwgNywgMTAsIDYsIDkpCgpydW5zX3Blcl85aW5uaW5ncwpoaXRzX3Blcl85aW5uaW5ncwpgYGAKClRoZXJlIGFyZSBhbHNvIHNvbWUgZnVuY3Rpb25zIHRoYXQgd2lsbCBjcmVhdGUgdmVjdG9ycyB3aXRoIHJlZ3VsYXIgcGF0dGVybnMsIGxpa2UgcmVwZWF0ZWQgZWxlbWVudHMuCgpgYGB7cn0KIyByZXBsaWNhdGUgZnVuY3Rpb24KcmVwKDIsIDUpCnJlcCgxLCA0KQoKIyBjb25zZWN1dGl2ZSBudW1iZXJzCjE6NQoyOjEwCgojIHNlcXVlbmNlIGZyb20gMSB0byAxMCB3aXRoIGEgc3RlcCBvZiAyCnNlcSgxLCAxMCwgYnkgPSAyKQpzZXEoMiwgMTMsIGJ5ID0gMykKYGBgCgpNYW55IGZ1bmN0aW9ucyBhbmQgb3BlcmF0b3JzIGxpa2UgYCtgIG9yIGAtYCB3aWxsIHdvcmsgb24gYWxsIGVsZW1lbnRzIG9mIHRoZSB2ZWN0b3IuCgpgYGB7cn0KIyBhZGQgdmVjdG9ycwpwaXRjaGVzX2J5X2lubmluZ3MgKyBzdHJpa2VzX2J5X2lubmluZ3MKCiMgY29tcGFyZSB2ZWN0b3JzCnBpdGNoZXNfYnlfaW5uaW5ncyA9PSBzdHJpa2VzX2J5X2lubmluZ3MKCiMgZmluZCBsZW5ndGggb2YgdmVjdG9yCmxlbmd0aChwaXRjaGVzX2J5X2lubmluZ3MpCgojIGZpbmQgbWluaW11bSB2YWx1ZSBpbiB2ZWN0b3IKbWluKHBpdGNoZXNfYnlfaW5uaW5ncykKCiMgZmluZCBhdmVyYWdlIHZhbHVlIGluIHZlY3RvcgptZWFuKHBpdGNoZXNfYnlfaW5uaW5ncykKYGBgCgpZb3UgY2FuIGFjY2VzcyBwYXJ0cyBvZiBhIHZlY3RvciBieSB1c2luZyBgW2AuIFJlY2FsbCB3aGF0IHRoZSB2YWx1ZSBpcyBvZiB0aGUgdmVjdG9yIGBwaXRjaGVzX2J5X2lubmluZ3NgLgoKYGBge3J9CnBpdGNoZXNfYnlfaW5uaW5ncwoKIyBJZiB5b3Ugd2FudCB0byBnZXQgdGhlIGZpcnN0IGVsZW1lbnQ6CnBpdGNoZXNfYnlfaW5uaW5nc1sxXQpgYGAKCiMgUXVlc3Rpb24gNQoKR2V0IHRoZSBmaXJzdCBlbGVtZW50IG9mIGBoaXRzX3Blcl85aW5uaW5nc2AuCgpgYGB7cn0KaGl0c19wZXJfOWlubmluZ3NbMV0KYGBgCgpJZiB5b3Ugd2FudCB0byBnZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBgcGl0Y2hlc19ieV9pbm5pbmdzYCB3aXRob3V0IGV4cGxpY2l0bHkgdHlwaW5nIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgb2YgYHBpdGNoZXNfYnlfaW5uaW5nc2AsIG1ha2UgdXNlIG9mIHRoZSBgbGVuZ3RoKClgIGZ1bmN0aW9uLCB3aGljaCBjYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgYSB2ZWN0b3I6CgpgYGB7cn0KcGl0Y2hlc19ieV9pbm5pbmdzW2xlbmd0aChwaXRjaGVzX2J5X2lubmluZ3MpXQpgYGAKCiMgUXVlc3Rpb24gNgoKR2V0IHRoZSBsYXN0IGVsZW1lbnQgb2YgYGhpdHNfcGVyXzlpbm5pbmdzYC4KCmBgYHtyfQpoaXRzX3Blcl85aW5uaW5nc1tsZW5ndGgoaGl0c19wZXJfOWlubmluZ3MpXQpgYGAKCllvdSBjYW4gYWxzbyBleHRyYWN0IG11bHRpcGxlIHZhbHVlcyBmcm9tIGEgdmVjdG9yLiBGb3IgaW5zdGFuY2UsIHRvIGdldCB0aGUgMm5kIHRocm91Z2ggNHRoIHZhbHVlcyB1c2U6CgpgYGB7cn0KcGl0Y2hlc19ieV9pbm5pbmdzW2MoMiwgMywgNCldCmBgYAoKVmVjdG9ycyBjYW4gYWxzbyBiZSBzdHJpbmdzIG9yIGxvZ2ljYWwgdmFsdWVzLgoKYGBge3J9CnBsYXllcl9wb3NpdGlvbnMgPC0gYygiY2F0Y2hlciIsICJwaXRjaGVyIiwgImluZmllbGRlcnMiLCAib3V0ZmllbGRlcnMiKQpwbGF5ZXJfcG9zaXRpb25zCmBgYAoKIyBEYXRhIEZyYW1lcwoKSW4gc3RhdGlzdGljYWwgYXBwbGljYXRpb25zLCBkYXRhIGlzIG9mdGVuIHN0b3JlZCBhcyBhIGRhdGEgZnJhbWUsIHdoaWNoIGlzIGxpa2UgYSBzcHJlYWRzaGVldCwgd2l0aCByb3dzIGFzIG9ic2VydmF0aW9ucyBhbmQgY29sdW1ucyBhcyB2YXJpYWJsZXMuCgpUbyBtYW51YWxseSBjcmVhdGUgYSBkYXRhIGZyYW1lLCB1c2UgdGhlIGBkYXRhLmZyYW1lKClgIGZ1bmN0aW9uLgoKYGBge3J9CmRhdGEuZnJhbWUoCiAgYm9udXMgPSBjKDIsIDMsIDEpLCAjIGluIG1pbGxpb25zCiAgYWN0aXZlX3Jvc3RlciA9IGMoInllcyIsICJubyIsICJ5ZXMiKSwKICBzYWxhcnkgPSBjKDEuNSwgMi41LCAxKSAjIGluIG1pbGxpb25zCikKYGBgCgpNb3N0IG9mdGVuIHlvdSB3aWxsIGJlIHVzaW5nIGRhdGEgZnJhbWVzIGxvYWRlZCBmcm9tIGEgZmlsZS4gRm9yIGV4YW1wbGUsIGxvYWQgdGhlIHJlc3VsdHMgb2YgYSBmYW7igJlzIHN1cnZleS4gVGhlIGZ1bmN0aW9uIGBsb2FkKClgIG9yIGByZWFkLnRhYmxlKClgIGNhbiBiZSB1c2VkIGZvciB0aGlzLgoKIyBIb3cgdG8gTWFrZSBhIFJhbmRvbSBTYW1wbGUKClRvIHJhbmRvbWx5IHNlbGVjdCBhIHNhbXBsZSB1c2UgdGhlIGZ1bmN0aW9uIGBzYW1wbGUoKWAuIFRoZSBmb2xsb3dpbmcgY29kZSBzZWxlY3RzIDUgbnVtYmVycyBiZXR3ZWVuIDEgYW5kIDEwIGF0IHJhbmRvbSwgd2l0aG91dCBkdXBsaWNhdGlvbi4KCmBgYHtyfQpzYW1wbGUoMToxMCwgc2l6ZSA9IDUpCmBgYAoKVGhlIGZpcnN0IGFyZ3VtZW50IGdpdmVzIHRoZSB2ZWN0b3Igb2YgZGF0YSB0byBzZWxlY3QgZWxlbWVudHMgZnJvbS4gVGhlIHNlY29uZCBhcmd1bWVudCwgYHNpemU9YCwgZ2l2ZXMgdGhlIHNpemUgb2YgdGhlIHNhbXBsZSB0byBzZWxlY3QuCgpUYWtpbmcgYSBzaW1wbGUgcmFuZG9tIHNhbXBsZSBmcm9tIGEgZGF0YSBmcmFtZSBpcyBvbmx5IHNsaWdodGx5IG1vcmUgY29tcGxpY2F0ZWQsIGhhdmluZyB0d28gc3RlcHM6CgoxLiBVc2UgYHNhbXBsZSgpYCB0byBzZWxlY3QgYSBzYW1wbGUgb2Ygc2l6ZSBgbmAgZnJvbSBhIHZlY3RvciBvZiB0aGUgcm93IG51bWJlcnMgb2YgdGhlIGRhdGEgZnJhbWUuCjIuIFVzZSB0aGUgaW5kZXggb3BlcmF0b3IgYFtgIHRvIHNlbGVjdCB0aG9zZSByb3dzIGZyb20gdGhlIGRhdGEgZnJhbWUuCgpDb25zaWRlciB0aGUgZm9sbG93aW5nIGV4YW1wbGUgd2l0aCBmYWtlIGRhdGEuIEZpcnN0LCBtYWtlIHVwIGEgZGF0YSBmcmFtZSB3aXRoIHR3byBjb2x1bW5zLiBgTEVUVEVSU2AgaXMgYSBjaGFyYWN0ZXIgdmVjdG9yIG9mIGxlbmd0aCAyNiB3aXRoIGNhcGl0YWwgbGV0dGVycyDigJxB4oCdIHRvIOKAnFrigJ07IGBMRVRURVJTYCBpcyBhdXRvbWF0aWNhbGx5IGRlZmluZWQgYW5kIHByZS1sb2FkZWQgaW4gUi4KCmBgYHtyfQpiYXIgPC0gZGF0YS5mcmFtZSh2YXIxID0gTEVUVEVSU1sxOjEwXSwgdmFyMiA9IDE6MTApCgojIENoZWNrIGRhdGEgZnJhbWUKYmFyCmBgYAoKU3VwcG9zZSB5b3Ugd2FudCB0byBzZWxlY3QgYSByYW5kb20gc2FtcGxlIG9mIHNpemUgNS4gRmlyc3QsIGRlZmluZSBhIHZhcmlhYmxlIGBuYCB3aXRoIHRoZSBzaXplIG9mIHRoZSBzYW1wbGUsIGkuZS4gNS4KCmBgYHtyfQpuIDwtIDUKYGBgCgpOb3csIHNlbGVjdCBhIHNhbXBsZSBvZiBzaXplIDUgZnJvbSB0aGUgdmVjdG9yIHdpdGggMSB0byAxMCwgdGhlIG51bWJlciBvZiByb3dzIGluIGBiYXJgLiBVc2UgdGhlIGZ1bmN0aW9uIGBucm93KClgIHRvIGZpbmQgdGhlIG51bWJlciBvZiByb3dzIGluIGBiYXJgIGluc3RlYWQgb2YgbWFudWFsbHkgZW50ZXJpbmcgdGhhdCBudW1iZXIuCgpVc2UgYDpgIHRvIGNyZWF0ZSBhIHZlY3RvciB3aXRoIGFsbCB0aGUgaW50ZWdlcnMgYmV0d2VlbiAxIGFuZCB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gYGJhcmAuCgpgYGB7cn0Kc2FtcGxlcm93cyA8LSBzYW1wbGUoMTpucm93KGJhciksIHNpemUgPSBuKQoKIyBwcmludCBzYW1wbGUgcm93cwpzYW1wbGVyb3dzCmBgYAoKVGhlIHZhcmlhYmxlIGBzYW1wbGVyb3dzYCBjb250YWlucyB0aGUgcm93cyBvZiBgYmFyYCB3aGljaCBtYWtlIGEgcmFuZG9tIHNhbXBsZSBmcm9tIGFsbCB0aGUgcm93cyBpbiBgYmFyYC4gRXh0cmFjdCB0aG9zZSByb3dzIGZyb20gYGJhcmAgd2l0aDoKCmBgYHtyfQojIGV4dHJhY3Qgcm93cwpiYXJzYW1wbGUgPC0gYmFyW3NhbXBsZXJvd3MsIF0KCiMgcHJpbnQgc2FtcGxlCnByaW50KGJhcnNhbXBsZSkKYGBgCgpUaGUgY29kZSBhYm92ZSBjcmVhdGVzIGEgbmV3IGRhdGEgZnJhbWUgY2FsbGVkIGBiYXJzYW1wbGVgIHdpdGggYSByYW5kb20gc2FtcGxlIG9mIHJvd3MgZnJvbSBgYmFyYC4KCkluIGEgc2luZ2xlIGxpbmUgb2YgY29kZToKCmBgYHtyfQpiYXJbc2FtcGxlKDE6bnJvdyhiYXIpLCBuKSwgXQpgYGAKCiMgVXNpbmcgVGFibGVzCgpUaGUgYHRhYmxlKClgIGNvbW1hbmQgYWxsb3dzIHVzIHRvIGxvb2sgYXQgdGFibGVzLiBJdHMgc2ltcGxlc3QgdXNhZ2UgbG9va3MgbGlrZSBgdGFibGUoeClgIHdoZXJlIGB4YCBpcyBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlLgoKRm9yIGV4YW1wbGUsIGEgc3VydmV5IGFza3MgcGVvcGxlIGlmIHRoZXkgc3VwcG9ydCB0aGUgaG9tZSB0ZWFtIG9yIG5vdC4gVGhlIGRhdGEgaXM6CgpZZXMsIE5vLCBObywgWWVzLCBZZXMKCldlIGNhbiBlbnRlciB0aGlzIGludG8gUiB3aXRoIHRoZSBgYygpYCBjb21tYW5kLCBhbmQgc3VtbWFyaXplIHdpdGggdGhlIGB0YWJsZSgpYCBjb21tYW5kIGFzIGZvbGxvd3M6CgpgYGB7cn0KeCA8LSBjKCJZZXMiLCAiTm8iLCAiTm8iLCAiWWVzIiwgIlllcyIpCnRhYmxlKHgpCmBgYAoKIyBOdW1lcmljYWwgbWVhc3VyZXMgb2YgY2VudGVyIGFuZCBzcHJlYWQKClN1cHBvc2UgTUxCIFRlYW1z4oCZIENFT3MgeWVhcmx5IGNvbXBlbnNhdGlvbnMgYXJlIHNhbXBsZWQgYW5kIHRoZSBmb2xsb3dpbmcgYXJlIGZvdW5kLCBpbiBtaWxsaW9uczoKCjEyLCAwLjQsIDUsIDIsIDUwLCA4LCAzLCAxLCA0LCAwLjI1CgpgYGB7cn0Kc2FscyA8LSBjKDEyLCAuNCwgNSwgMiwgNTAsIDgsIDMsIDEsIDQsIDAuMjUpCgojIHRoZSBhdmVyYWdlCm1lYW4oc2FscykKCiMgdGhlIHZhcmlhbmNlCnZhcihzYWxzKQoKIyB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uCnNkKHNhbHMpCgojIHRoZSBtZWRpYW4KbWVkaWFuKHNhbHMpCgojIFR1a2V5J3MgZml2ZSBudW1iZXIgc3VtbWFyeSwgdXNlZnVsIGZvciBib3hwbG90cwojIGZpdmUgbnVtYmVyczogbWluLCBsb3dlciBoaW5nZSwgbWVkaWFuLCB1cHBlciBoaW5nZSwgbWF4CmZpdmVudW0oc2FscykKCiMgc3VtbWFyeSBzdGF0aXN0aWNzCnN1bW1hcnkoc2FscykKYGBgCgojIEhvdyBhYm91dCB0aGUgbW9kZT8KCkluIFIgd2UgY2FuIHdyaXRlIG91ciBvd24gZnVuY3Rpb25zLCBhbmQgYSBmaXJzdCBleGFtcGxlIG9mIGEgZnVuY3Rpb24gaXMgc2hvd24gYmVsb3cgaW4gb3JkZXIgdG8gY29tcHV0ZSB0aGUgbW9kZSBvZiBhIHZlY3RvciBvZiBvYnNlcnZhdGlvbnMgYHhgLgoKYGBge3J9CiMgRnVuY3Rpb24gdG8gZmluZCB0aGUgbW9kZSwgaS5lLiBtb3N0IGZyZXF1ZW50IHZhbHVlCmdldE1vZGUgPC0gZnVuY3Rpb24oeCkgewogIHV4IDwtIHVuaXF1ZSh4KQogIHV4W3doaWNoLm1heCh0YWJ1bGF0ZShtYXRjaCh4LCB1eCkpKV0KfQpgYGAKCkFzIGFuIGV4YW1wbGUsIHdlIGNhbiB1c2UgdGhlIGZ1bmN0aW9uIGRlZmluZWQgYWJvdmUgdG8gZmluZCB0aGUgbW9zdCBmcmVxdWVudCB2YWx1ZSBvZiB0aGUgbnVtYmVyIG9mIGBwaXRjaGVzX2J5X2lubmluZ3NgLgoKYGBge3J9CiMgTW9zdCBmcmVxdWVudCB2YWx1ZSBpbiBwaXRjaGVzX2J5X2lubmluZ3MKZ2V0TW9kZShwaXRjaGVzX2J5X2lubmluZ3MpCmBgYAoKIyBRdWVzdGlvbiA3CgpGaW5kIHRoZSBtb3N0IGZyZXF1ZW50IHZhbHVlIG9mIGBoaXRzX3Blcl85aW5uaW5nc2AuCgpgYGB7cn0KZ2V0TW9kZShoaXRzX3Blcl85aW5uaW5ncykKYGBgCgojIFF1ZXN0aW9uIDgKClN1bW1hcml6ZSB0aGUgZm9sbG93aW5nIHN1cnZleSB3aXRoIHRoZSBgdGFibGUoKWAgY29tbWFuZDoKCldoYXQgaXMgeW91ciBmYXZvcml0ZSBkYXkgb2YgdGhlIHdlZWsgdG8gd2F0Y2ggYmFzZWJhbGw/IEEgdG90YWwgb2YgMTAgZmFucyBzdWJtaXR0ZWQgdGhpcyBzdXJ2ZXkuCgpTYXR1cmRheSwgU2F0dXJkYXksIFN1bmRheSwgTW9uZGF5LCBTYXR1cmRheSwgVHVlc2RheSwgU3VuZGF5LCBGcmlkYXksIEZyaWRheSwgTW9uZGF5CgpgYGB7cn0KZ2FtZV9kYXkgPC0gYygKICAiU2F0dXJkYXkiLCAiU2F0dXJkYXkiLCAiU3VuZGF5IiwgIk1vbmRheSIsICJTYXR1cmRheSIsCiAgIlR1ZXNkYXkiLCAiU3VuZGF5IiwgIkZyaWRheSIsICJGcmlkYXkiLCAiTW9uZGF5IgopCgp0YWJsZShnYW1lX2RheSkKYGBgCgojIFF1ZXN0aW9uIDkKCldoYXQgaXMgdGhlIG1vc3QgZnJlcXVlbnQgYW5zd2VyIHJlY29yZGVkIGluIHRoZSBzdXJ2ZXk/IFVzZSB0aGUgYGdldE1vZGUoKWAgZnVuY3Rpb24gdG8gY29tcHV0ZSByZXN1bHRzLgoKYGBge3J9CmdldE1vZGUoZ2FtZV9kYXkpCmBgYAo=