19 min to read
R in One Post
Learn R For Free
Getting Started
This tutorial is desgined for the beginner who has some computer programming experience. Remember rule number one in Programming
Dont Panic
Download RStudion Here https://www.rstudio.com/products/rstudio/download/
Storing Values
Types of variables
integer <- 1
double <- 5.0
character <- "A"
string <- "ABCDEFGHIJKLMNOQRSTUVWXYZ"
boolean <- TRUE
data <- list(12,3.14,"Henry","Bernreuter")
data_1 <- list(dozen = 12, pi = 3.14, user = "henry", happy = TRUE )
print(double)
[1] 5
print(integer)
[1] 1
print(character)
[1] "A"
print(string)
[1] "ABCDEFGHIJKLMNOQRSTUVWXYZ"
print(data)
[[1]]
[1] 12
[[2]]
[1] 3.14
[[3]]
[1] "Henry"
[[4]]
[1] "Bernreuter"
print(data_1)
$`dozen`
[1] 12
$pi
[1] 3.14
$user
[1] "henry"
$happy
[1] TRUE
data_1$user
[1] "henry"
vector_months <- c("Jan","Feb","Mar","Apr")
vector_months[1]
[1] "Jan"
Performing operations
#Addition
2+2
[1] 4
#Subtraction
2-2
[1] 0
#Division
2/2
[1] 1
#Multiplcation
2*2
[1] 4
#Exponent
3^2
[1] 9
#Modulus
22%%7
[1] 1
Testing Conditions
#Equaliy: 0 equals 0
0 == 0
[1] TRUE
#InEquality: 1 does not equal 0
1 != 0
[1] TRUE
#Greater Than: 1 is greater than 0
1 > 0
[1] TRUE
#Less Than: 0 is less than 1
0 < 1
[1] TRUE
#Less Than or Egual to: 0 is less than or equal to 1
0 <= 1
[1] TRUE
#Logical NOT: TRU does not equal TRUE
!TRUE
[1] FALSE
#Logical AND: TRUE and TRUE equals TRUE
TRUE && TRUE
[1] TRUE
#Logical OR: TRUE OR FALSE equals TRUE
TRUE || TRUE
[1] TRUE
Employing Functions
R has many built in functions. You have already seen the print() function
name = "Henry Bernreuter"
print(name)
[1] "Henry Bernreuter"
#Absolute Value
abs(-1)
[1] 1
#Square Root
sqrt(2)
[1] 1.414214
#Integer rounded up
ceiling(4.4)
[1] 5
#Integer rounded down
floor(4.6)
[1] 4
#Truncated
trunc(22/7)
[1] 3
#Round to the nearest number X to N siginficate digits
round(22/7, digits = 3 )
[1] 3.143
#Nearest number to X to n decimal places
signif(22/7, digits = 7)
[1] 3.142857
#Trigonometry
#cosign
cos(0)
[1] 1
#sin
sin(0)
[1] 0
#tangent
tan(0)
[1] 0
#arccos
acos(0)
[1] 1.570796
#arcsin
asin(0)
[1] 0
#arctan
atan(0)
[1] 0
#logarithm
log(10)
[1] 2.302585
#exponent
exp(0)
[1] 1
#String Functions
substr(string,0,25)
[1] "ABCDEFGHIJKLMNOQRSTUVWXYZ"
substr(string,0,3)
[1] "ABC"
#Make a string all uppercase
toupper(string)
[1] "ABCDEFGHIJKLMNOQRSTUVWXYZ"
#make a sting all lower
tolower(string)
[1] "abcdefghijklmnoqrstuvwxyz"
#substute one character for another in a string
sub('ABC','123',string)
[1] "123DEFGHIJKLMNOQRSTUVWXYZ"
#current date and time of computer
# %e = day number
# %a = shorten day name %A = full day name
# %b = shorten month name %B = full month name
# %H = hour number (00 - 23)
# %M = minute number(00-59)
# %y = Year number 4-digit
format(Sys.time(), "%A %b %d %X %Y")
[1] "Tuesday Jul 23 12:50:05 PM 2019"
#built in constants
print(LETTERS)
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y"
[26] "Z"
print(letters)
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y"
[26] "z"
print(month.name)
[1] "January" "February" "March" "April" "May" "June" "July" "August"
[9] "September" "October" "November" "December"
print(month.abb)
[1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
#Concatenate And Print
#is useful for producing output in user-defined functions.
#It converts its arguments to character vectors
#concatenates them to a single character vector
#appends the given sep function string(s) to each element and then outputs them.
half.year = month.abb[1:6]
cat("Constant", half.year)
Constant Jan Feb Mar Apr May Jun
#create a random number wih runif() function
random = runif(10)
random
[1] 0.8594901 0.2222176 0.6988373 0.7076233 0.8870411 0.2806615 0.3656753 0.7706948 0.6509018 0.4191367
#Creat a sample of number in a range
lottery_numbers = c(1:59)
cat("The winning lottery numbers are:", sample(lottery_numbers,6))
The winning lottery numbers are: 50 1 16 37 57 49
#random normally distrubieted numbers
rnorm(10)
[1] -2.08473016 0.03460206 0.57954210 1.56998413 0.44054716 -0.32980232 0.10264708 0.50898951
[9] -1.20265356 0.53597390
#randome generated numbers with a mean and standard deviation
normalNumbers = rnorm(10, mean = 1,sd = 1)
#To get the mean
mean(normalNumbers)
[1] 0.9155609
#To get the median
median(normalNumbers)
[1] 0.8837336
#To get the standard deviation
sd(normalNumbers)
[1] 0.8256223
#To get the qualtile
quantile(normalNumbers)
0% 25% 50% 75% 100%
-0.03241776 0.14866118 0.88373356 1.64802192 2.12232888
#To get the sum
sum(normalNumbers)
[1] 9.155609
#To get the range
range(normalNumbers)
[1] -0.03241776 2.12232888
#to get the max
max(normalNumbers)
[1] 2.122329
#to get the min
min(normalNumbers)
[1] -0.03241776
#First Plot
plot(1:10,normalNumbers,type = "o")
Create new functions with loops
#For Loops
half.year = month.abb[1:6]
for (month in half.year){
print(paste("The months of the year are", month))
}
[1] "The months of the year are Jan"
[1] "The months of the year are Feb"
[1] "The months of the year are Mar"
[1] "The months of the year are Apr"
[1] "The months of the year are May"
[1] "The months of the year are Jun"
#While loop
i = 1
while (i < 6) {
print(i)
i = i+1
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
#The standard function syntax is
# Function name = function(arg1, arg2, arg3)
#{
# statement to be executed
# return(object)
#}
f2c = function(degrees){
result = ((degrees -32)* 5/9)
return(result)
}
cat("Body Temperature 98.6F =",f2c(98.6), "C")
Body Temperature 98.6F = 37 C
Building matrices
data = seq(1:32)
table = matrix(data, nrow = 4, ncol = 8)
print(table)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 5 9 13 17 21 25 29
[2,] 2 6 10 14 18 22 26 30
[3,] 3 7 11 15 19 23 27 31
[4,] 4 8 12 16 20 24 28 32
#Retrieve a cell value
cat("Cell 4,5 Contains", table[4,5])
Cell 4,5 Contains 20
#Replace the value with another value
table[4,5] = 10
cat("Cell 4,5 now Contains", table[4,5])
Cell 4,5 now Contains 10
#Spiral Matrix using a loop
i <- 1
j <- 1
i.start = 1
j.start <- 1
i.max <- 10
j.max <- 10
run <- 1
map <- matrix("MT",nrow = 10,ncol = 10)
while(i <= i.max & j <= j.max){
while (j <= j.max){
if(map[i,j] == "MT"){ #horizontal to the right
map[i,j] = run
run = run +1
j = j +1
}
}
j = j -1
while (i <= i.max) {
if(map[i,j] != "MT") i = i+1 #next row
else if(map[i,j] == "MT"){ #vertical to the bottom
map[i,j] = run
run = run +1
i = i+1
}
}
i = i -1
while(j <= j.max & j >= j.start){
if(map[i,j] != "MT") j = j-1 #previous column
else if (map[i,j] == "MT"){
map[i,j] = run
run = run +1
j = j -1
}
}
i = i -1
j = j.start #reset
while(i<= i.max & i > i.start){
if(map[i,j] == "MT"){
map[i,j] = run
i = i -1
}
}
i = i +1
j = j +1
i.start = i.start +1
j.start = j.start +1
i.max = i.max -1
j.max = j.max -1
}
map
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
[2,] "29" "29" "30" "31" "32" "33" "34" "35" "36" "11"
[3,] "29" "51" "51" "52" "53" "54" "55" "56" "37" "12"
[4,] "29" "51" "67" "67" "68" "69" "70" "57" "38" "13"
[5,] "29" "51" "67" "77" "77" "78" "71" "58" "39" "14"
[6,] "29" "51" "67" "77" "80" "79" "72" "59" "40" "15"
[7,] "29" "51" "67" "76" "75" "74" "73" "60" "41" "16"
[8,] "29" "51" "66" "65" "64" "63" "62" "61" "42" "17"
[9,] "29" "50" "49" "48" "47" "46" "45" "44" "43" "18"
[10,] "28" "27" "26" "25" "24" "23" "22" "21" "20" "19"
Plots
##Plotting matrices
### Make matrix with three vectors
ny = c(3.8,5.5,9.9,15.7,21.5,26.3)
la = c(19.5,19.4,19.7,20.8,21.3,22.7)
fw = c(13.7,15.4,20.0,24.6,28.5,32.7)
### bind all the vectors into a table
table = cbind(ny,la,fw)
### Change the names of the rows
colnames(table) = c("New York","Los Angeles","Fort Worth")
### Cahnge the names of the cloumns
rownames(table) = month.abb[1:6]
### Check to see what it looks like
table
New York Los Angeles Fort Worth
Jan 3.8 19.5 13.7
Feb 5.5 19.4 15.4
Mar 9.9 19.7 20.0
Apr 15.7 20.8 24.6
May 21.5 21.3 28.5
Jun 26.3 22.7 32.7
###Plot with matplot function
### types : "p" = points "l" eguals lines "b" = both
### pch : eguals type of characters
### col : equals colors
matplot(table, type = "b", pch = 15:17, col = 2:4)
Data Frames
#Use the build in data frame know as mtcars
mtcars
#Extract frame subets
edge = mtcars[c(1,2,3),]
edge
# Retrieve a column from the table (column slice)
my_data1 <- mtcars$mpg
my_data2 <- mtcars[, 1] # retrieve a column by index. Column indices start from 1, not 0.
my_data3 <- mtcars[, c("mpg", "cyl", "hp")] # retrieve multiple columns by names
my_data1
[1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4 14.7 32.4 30.4 33.9
[21] 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7 15.0 21.4
my_data2
[1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4 14.7 32.4 30.4 33.9
[21] 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7 15.0 21.4
my_data3
#create new dataframes
newdataMTcars = mtcars[c(1,2,3,4,5,6)]
nextdataMtcars = mtcars[c(7,8,9,10)]
#Statistic Funciton in Dataframes
mean(mtcars$mpg)
[1] 20.09062
median(mtcars$mpg)
[1] 19.2
range(mtcars$mpg)
[1] 10.4 33.9
sd(mtcars$mpg)
[1] 6.026948
More Plots
qqnorm(mtcars$mpg)
qqline(mtcars$mpg)
qqplot(mtcars$mpg, mtcars$hp)
LS0tDQp0aXRsZTogIlIgaW4gT25lIFBvc3QiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCiNHZXR0aW5nIFN0YXJ0ZWQNClRoaXMgdHV0b3JpYWwgaXMgZGVzZ2luZWQgZm9yIHRoZSBiZWdpbm5lciB3aG8gaGFzIHNvbWUgY29tcHV0ZXIgcHJvZ3JhbW1pbmcgZXhwZXJpZW5jZS4gDQpSZW1lbWJlciBydWxlIG51bWJlciBvbmUgaW4gUHJvZ3JhbW1pbmcgDQoNCiNEb250IFBhbmljDQpEb3dubG9hZCBSU3R1ZGlvbiBIZXJlIGh0dHBzOi8vd3d3LnJzdHVkaW8uY29tL3Byb2R1Y3RzL3JzdHVkaW8vZG93bmxvYWQvDQoNCg0KI1N0b3JpbmcgVmFsdWVzDQpUeXBlcyBvZiB2YXJpYWJsZXMNCmBgYHtyfQ0KaW50ZWdlciA8LSAxDQpkb3VibGUgPC0gNS4wDQpjaGFyYWN0ZXIgPC0gIkEiDQpzdHJpbmcgPC0gIkFCQ0RFRkdISUpLTE1OT1FSU1RVVldYWVoiDQpib29sZWFuIDwtIFRSVUUNCmRhdGEgPC0gbGlzdCgxMiwzLjE0LCJIZW5yeSIsIkJlcm5yZXV0ZXIiKQ0KZGF0YV8xIDwtIGxpc3QoZG96ZW4gPSAxMiwgcGkgPSAzLjE0LCB1c2VyID0gImhlbnJ5IiwgaGFwcHkgPSBUUlVFICkNCnByaW50KGRvdWJsZSkNCnByaW50KGludGVnZXIpDQpwcmludChjaGFyYWN0ZXIpDQpwcmludChzdHJpbmcpDQpwcmludChkYXRhKQ0KcHJpbnQoZGF0YV8xKQ0KZGF0YV8xJHVzZXINCnZlY3Rvcl9tb250aHMgPC0gYygiSmFuIiwiRmViIiwiTWFyIiwiQXByIikNCnZlY3Rvcl9tb250aHNbMV0NCg0KYGBgDQojUGVyZm9ybWluZyBvcGVyYXRpb25zDQpgYGB7cn0NCiNBZGRpdGlvbg0KMisyDQojU3VidHJhY3Rpb24NCjItMg0KI0RpdmlzaW9uDQoyLzINCiNNdWx0aXBsY2F0aW9uDQoyKjINCiNFeHBvbmVudA0KM14yDQojTW9kdWx1cw0KMjIlJTcgDQoNCmBgYA0KI1Rlc3RpbmcgQ29uZGl0aW9ucw0KYGBge3J9DQojRXF1YWxpeTogMCBlcXVhbHMgMA0KMCA9PSAwDQojSW5FcXVhbGl0eTogMSBkb2VzIG5vdCBlcXVhbCAwDQoxICE9IDANCiNHcmVhdGVyIFRoYW46IDEgaXMgZ3JlYXRlciB0aGFuIDANCjEgPiAwDQojTGVzcyBUaGFuOiAwIGlzIGxlc3MgdGhhbiAxDQowIDwgMQ0KI0xlc3MgVGhhbiBvciBFZ3VhbCB0bzogMCBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gMQ0KMCA8PSAxDQojTG9naWNhbCBOT1Q6IFRSVSBkb2VzIG5vdCBlcXVhbCBUUlVFDQohVFJVRQ0KI0xvZ2ljYWwgQU5EOiBUUlVFIGFuZCBUUlVFIGVxdWFscyBUUlVFDQpUUlVFICYmIFRSVUUNCiNMb2dpY2FsIE9SOiBUUlVFIE9SIEZBTFNFIGVxdWFscyBUUlVFDQpUUlVFIHx8IFRSVUUNCg0KYGBgDQojRW1wbG95aW5nIEZ1bmN0aW9ucw0KIyNSIGhhcyBtYW55IGJ1aWx0IGluIGZ1bmN0aW9ucy4gWW91IGhhdmUgYWxyZWFkeSBzZWVuIHRoZSBwcmludCgpIGZ1bmN0aW9uDQpgYGB7cn0NCg0KbmFtZSA9ICJIZW5yeSBCZXJucmV1dGVyIg0KcHJpbnQobmFtZSkNCg0KI0Fic29sdXRlIFZhbHVlDQphYnMoLTEpDQoNCiNTcXVhcmUgUm9vdA0Kc3FydCgyKQ0KDQojSW50ZWdlciByb3VuZGVkIHVwDQpjZWlsaW5nKDQuNCkNCg0KI0ludGVnZXIgcm91bmRlZCBkb3duDQpmbG9vcig0LjYpDQoNCiNUcnVuY2F0ZWQNCnRydW5jKDIyLzcpDQoNCiNSb3VuZCB0byB0aGUgbmVhcmVzdCBudW1iZXIgWCB0byBOIHNpZ2luZmljYXRlIGRpZ2l0cw0Kcm91bmQoMjIvNywgZGlnaXRzID0gMyApDQoNCiNOZWFyZXN0IG51bWJlciB0byBYIHRvIG4gZGVjaW1hbCBwbGFjZXMNCnNpZ25pZigyMi83LCBkaWdpdHMgPSA3KQ0KDQojVHJpZ29ub21ldHJ5DQoNCiNjb3NpZ24NCmNvcygwKQ0KI3Npbg0Kc2luKDApDQojdGFuZ2VudA0KdGFuKDApDQojYXJjY29zDQphY29zKDApDQojYXJjc2luDQphc2luKDApDQojYXJjdGFuDQphdGFuKDApDQojbG9nYXJpdGhtDQpsb2coMTApDQojZXhwb25lbnQNCmV4cCgwKQ0KDQojU3RyaW5nIEZ1bmN0aW9ucw0Kc3Vic3RyKHN0cmluZywwLDI1KQ0Kc3Vic3RyKHN0cmluZywwLDMpDQoNCiNNYWtlIGEgc3RyaW5nIGFsbCB1cHBlcmNhc2UNCnRvdXBwZXIoc3RyaW5nKQ0KI21ha2UgYSBzdGluZyBhbGwgbG93ZXINCnRvbG93ZXIoc3RyaW5nKQ0KDQojc3Vic3R1dGUgb25lIGNoYXJhY3RlciBmb3IgYW5vdGhlciBpbiBhIHN0cmluZw0Kc3ViKCdBQkMnLCcxMjMnLHN0cmluZykNCg0KI2N1cnJlbnQgZGF0ZSBhbmQgdGltZSBvZiBjb21wdXRlciANCiMgJWUgPSBkYXkgbnVtYmVyDQojICVhID0gc2hvcnRlbiBkYXkgbmFtZSAlQSA9IGZ1bGwgZGF5IG5hbWUNCiMgJWIgPSBzaG9ydGVuIG1vbnRoIG5hbWUgJUIgPSBmdWxsIG1vbnRoIG5hbWUNCiMgJUggPSBob3VyIG51bWJlciAoMDAgLSAyMykNCiMgJU0gPSBtaW51dGUgbnVtYmVyKDAwLTU5KQ0KIyAleSA9IFllYXIgbnVtYmVyIDQtZGlnaXQNCmZvcm1hdChTeXMudGltZSgpLCAiJUEgJWIgJWQgJVggJVkiKQ0KDQojYnVpbHQgaW4gY29uc3RhbnRzDQpwcmludChMRVRURVJTKQ0KcHJpbnQobGV0dGVycykNCnByaW50KG1vbnRoLm5hbWUpDQpwcmludChtb250aC5hYmIpDQoNCiNDb25jYXRlbmF0ZSBBbmQgUHJpbnQgDQojaXMgdXNlZnVsIGZvciBwcm9kdWNpbmcgb3V0cHV0IGluIHVzZXItZGVmaW5lZCBmdW5jdGlvbnMuDQojSXQgY29udmVydHMgaXRzIGFyZ3VtZW50cyB0byBjaGFyYWN0ZXIgdmVjdG9ycw0KI2NvbmNhdGVuYXRlcyB0aGVtIHRvIGEgc2luZ2xlIGNoYXJhY3RlciB2ZWN0b3INCiNhcHBlbmRzIHRoZSBnaXZlbiBzZXAgZnVuY3Rpb24gc3RyaW5nKHMpIHRvIGVhY2ggZWxlbWVudCBhbmQgdGhlbiBvdXRwdXRzIHRoZW0uDQoNCmhhbGYueWVhciA9IG1vbnRoLmFiYlsxOjZdDQpjYXQoIkNvbnN0YW50IiwgaGFsZi55ZWFyKQ0KDQojY3JlYXRlIGEgcmFuZG9tIG51bWJlciB3aWggcnVuaWYoKSBmdW5jdGlvbg0KcmFuZG9tID0gcnVuaWYoMTApDQpyYW5kb20NCg0KI0NyZWF0IGEgc2FtcGxlIG9mIG51bWJlciBpbiBhIHJhbmdlDQpsb3R0ZXJ5X251bWJlcnMgPSBjKDE6NTkpDQpjYXQoIlRoZSB3aW5uaW5nIGxvdHRlcnkgbnVtYmVycyBhcmU6Iiwgc2FtcGxlKGxvdHRlcnlfbnVtYmVycyw2KSkNCg0KI3JhbmRvbSBub3JtYWxseSBkaXN0cnViaWV0ZWQgbnVtYmVycyANCnJub3JtKDEwKQ0KDQojcmFuZG9tZSBnZW5lcmF0ZWQgbnVtYmVycyB3aXRoIGEgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uDQpub3JtYWxOdW1iZXJzID0gcm5vcm0oMTAsIG1lYW4gPSAxLHNkID0gMSkNCg0KI1RvIGdldCB0aGUgbWVhbg0KbWVhbihub3JtYWxOdW1iZXJzKQ0KDQojVG8gZ2V0IHRoZSBtZWRpYW4NCm1lZGlhbihub3JtYWxOdW1iZXJzKQ0KI1RvIGdldCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uDQpzZChub3JtYWxOdW1iZXJzKQ0KI1RvIGdldCB0aGUgcXVhbHRpbGUNCnF1YW50aWxlKG5vcm1hbE51bWJlcnMpDQojVG8gZ2V0IHRoZSBzdW0NCnN1bShub3JtYWxOdW1iZXJzKQ0KI1RvIGdldCB0aGUgcmFuZ2UNCnJhbmdlKG5vcm1hbE51bWJlcnMpDQojdG8gZ2V0IHRoZSBtYXgNCm1heChub3JtYWxOdW1iZXJzKQ0KI3RvIGdldCB0aGUgbWluDQptaW4obm9ybWFsTnVtYmVycykNCg0KI0ZpcnN0IFBsb3QgDQpwbG90KDE6MTAsbm9ybWFsTnVtYmVycyx0eXBlID0gIm8iKQ0KDQoNCg0KYGBgDQojQ3JlYXRlIG5ldyBmdW5jdGlvbnMgd2l0aCBsb29wcw0KYGBge3J9DQojRm9yIExvb3BzDQpoYWxmLnllYXIgPSBtb250aC5hYmJbMTo2XQ0KZm9yIChtb250aCBpbiBoYWxmLnllYXIpew0KICBwcmludChwYXN0ZSgiVGhlIG1vbnRocyBvZiB0aGUgeWVhciBhcmUiLCBtb250aCkpDQp9DQoNCiNXaGlsZSBsb29wDQppID0gMQ0Kd2hpbGUgKGkgPCA2KSB7DQpwcmludChpKQ0KaSA9IGkrMQ0KfQ0KI1RoZSBzdGFuZGFyZCBmdW5jdGlvbiBzeW50YXggaXMNCiMgIEZ1bmN0aW9uIG5hbWUgPSBmdW5jdGlvbihhcmcxLCBhcmcyLCBhcmczKQ0KI3sNCiMgIHN0YXRlbWVudCB0byBiZSBleGVjdXRlZA0KIyAgcmV0dXJuKG9iamVjdCkNCiN9DQoNCmYyYyA9IGZ1bmN0aW9uKGRlZ3JlZXMpew0KICByZXN1bHQgPSAoKGRlZ3JlZXMgLTMyKSogNS85KQ0KICByZXR1cm4ocmVzdWx0KQ0KfQ0KY2F0KCJCb2R5IFRlbXBlcmF0dXJlIDk4LjZGID0iLGYyYyg5OC42KSwgIkMiKQ0KDQpgYGANCiNCdWlsZGluZyBtYXRyaWNlcw0KYGBge3J9DQpkYXRhID0gc2VxKDE6MzIpDQp0YWJsZSA9IG1hdHJpeChkYXRhLCBucm93ID0gNCwgbmNvbCA9IDgpDQpwcmludCh0YWJsZSkNCg0KI1JldHJpZXZlIGEgY2VsbCB2YWx1ZQ0KY2F0KCJDZWxsIDQsNSBDb250YWlucyIsIHRhYmxlWzQsNV0pDQoNCiNSZXBsYWNlIHRoZSB2YWx1ZSB3aXRoIGFub3RoZXIgdmFsdWUNCnRhYmxlWzQsNV0gPSAxMA0KY2F0KCJDZWxsIDQsNSBub3cgQ29udGFpbnMiLCB0YWJsZVs0LDVdKQ0KDQoNCg0KI1NwaXJhbCBNYXRyaXggdXNpbmcgYSBsb29wDQppIDwtIDENCmogPC0gMQ0KaS5zdGFydCA9IDENCmouc3RhcnQgPC0gMQ0KaS5tYXggPC0gMTANCmoubWF4IDwtIDEwDQpydW4gPC0gMQ0KbWFwIDwtIG1hdHJpeCgiTVQiLG5yb3cgPSAxMCxuY29sID0gMTApDQoNCndoaWxlKGkgPD0gaS5tYXggJiBqIDw9IGoubWF4KXsNCiAgDQogIHdoaWxlIChqIDw9IGoubWF4KXsNCiAgICBpZihtYXBbaSxqXSA9PSAiTVQiKXsgI2hvcml6b250YWwgdG8gdGhlIHJpZ2h0DQogICAgICBtYXBbaSxqXSA9IHJ1bg0KICAgICAgcnVuID0gcnVuICsxDQogICAgICBqID0gaiArMQ0KICAgIH0NCiAgfQ0KICANCiAgaiA9IGogLTENCiAgDQogIHdoaWxlIChpIDw9IGkubWF4KSB7DQogICAgaWYobWFwW2ksal0gIT0gIk1UIikgaSA9IGkrMSAjbmV4dCByb3cNCiAgICBlbHNlIGlmKG1hcFtpLGpdID09ICJNVCIpeyAjdmVydGljYWwgdG8gdGhlIGJvdHRvbQ0KICAgICAgbWFwW2ksal0gPSBydW4NCiAgICAgIHJ1biA9IHJ1biArMQ0KICAgICAgaSA9IGkrMQ0KICAgIH0NCiAgfQ0KICANCiAgaSA9IGkgLTENCiAgDQogIHdoaWxlKGogPD0gai5tYXggJiBqID49IGouc3RhcnQpew0KICAgIGlmKG1hcFtpLGpdICE9ICJNVCIpIGogPSBqLTEgI3ByZXZpb3VzIGNvbHVtbg0KICAgIGVsc2UgaWYgKG1hcFtpLGpdID09ICJNVCIpew0KICAgICAgbWFwW2ksal0gPSBydW4NCiAgICAgIHJ1biA9IHJ1biArMSANCiAgICAgIGogPSBqIC0xDQogICAgfQ0KICB9ICANCiAgDQogIGkgPSBpIC0xDQogIGogPSBqLnN0YXJ0ICNyZXNldA0KICANCiAgd2hpbGUoaTw9IGkubWF4ICYgaSA+IGkuc3RhcnQpew0KICAgIGlmKG1hcFtpLGpdID09ICJNVCIpew0KICAgICAgbWFwW2ksal0gPSBydW4NCiAgICAgIGkgPSBpIC0xDQogICAgfQ0KICB9IA0KICANCiAgaSA9IGkgKzEgDQogIGogPSBqICsxDQogIGkuc3RhcnQgPSBpLnN0YXJ0ICsxDQogIGouc3RhcnQgPSBqLnN0YXJ0ICsxDQogIGkubWF4ID0gaS5tYXggLTENCiAgai5tYXggPSBqLm1heCAtMQ0KICANCn0NCg0KDQptYXANCmBgYA0KI1Bsb3RzDQpgYGB7cn0NCiMjUGxvdHRpbmcgbWF0cmljZXMNCiMjIyBNYWtlIG1hdHJpeCB3aXRoIHRocmVlIHZlY3RvcnMgDQpueSA9IGMoMy44LDUuNSw5LjksMTUuNywyMS41LDI2LjMpDQpsYSA9IGMoMTkuNSwxOS40LDE5LjcsMjAuOCwyMS4zLDIyLjcpDQpmdyA9IGMoMTMuNywxNS40LDIwLjAsMjQuNiwyOC41LDMyLjcpDQojIyMgYmluZCBhbGwgdGhlIHZlY3RvcnMgaW50byBhIHRhYmxlDQp0YWJsZSA9IGNiaW5kKG55LGxhLGZ3KQ0KIyMjIENoYW5nZSB0aGUgbmFtZXMgb2YgdGhlIHJvd3MNCmNvbG5hbWVzKHRhYmxlKSA9IGMoIk5ldyBZb3JrIiwiTG9zIEFuZ2VsZXMiLCJGb3J0IFdvcnRoIikNCiMjIyBDYWhuZ2UgdGhlIG5hbWVzIG9mIHRoZSBjbG91bW5zDQpyb3duYW1lcyh0YWJsZSkgPSBtb250aC5hYmJbMTo2XQ0KIyMjIENoZWNrIHRvIHNlZSB3aGF0IGl0IGxvb2tzIGxpa2UNCnRhYmxlDQoNCg0KIyMjUGxvdCB3aXRoIG1hdHBsb3QgZnVuY3Rpb24NCiMjIyB0eXBlcyA6ICJwIiA9IHBvaW50cyAibCIgZWd1YWxzIGxpbmVzICJiIiA9IGJvdGgNCiMjIyBwY2ggOiBlZ3VhbHMgdHlwZSBvZiBjaGFyYWN0ZXJzDQojIyMgY29sIDogZXF1YWxzIGNvbG9ycw0KbWF0cGxvdCh0YWJsZSwgdHlwZSA9ICJiIiwgcGNoID0gMTU6MTcsIGNvbCA9IDI6NCkNCg0KDQpgYGANCiNEYXRhIEZyYW1lcw0KYGBge3J9DQojVXNlIHRoZSBidWlsZCBpbiBkYXRhIGZyYW1lIGtub3cgYXMgbXRjYXJzDQptdGNhcnMNCg0KI0V4dHJhY3QgZnJhbWUgc3ViZXRzDQplZGdlID0gbXRjYXJzW2MoMSwyLDMpLF0NCmVkZ2UNCg0KIyBSZXRyaWV2ZSBhIGNvbHVtbiBmcm9tIHRoZSB0YWJsZSAoY29sdW1uIHNsaWNlKQ0KbXlfZGF0YTEgPC0gbXRjYXJzJG1wZw0KbXlfZGF0YTIgPC0gbXRjYXJzWywgMV0gIyByZXRyaWV2ZSBhIGNvbHVtbiBieSBpbmRleC4gQ29sdW1uIGluZGljZXMgc3RhcnQgZnJvbSAxLCBub3QgMC4NCm15X2RhdGEzIDwtIG10Y2Fyc1ssIGMoIm1wZyIsICJjeWwiLCAiaHAiKV0gIyByZXRyaWV2ZSBtdWx0aXBsZSBjb2x1bW5zIGJ5IG5hbWVzDQpteV9kYXRhMQ0KbXlfZGF0YTINCm15X2RhdGEzDQoNCiNjcmVhdGUgbmV3IGRhdGFmcmFtZXMNCm5ld2RhdGFNVGNhcnMgPSBtdGNhcnNbYygxLDIsMyw0LDUsNildDQpuZXh0ZGF0YU10Y2FycyA9IG10Y2Fyc1tjKDcsOCw5LDEwKV0NCg0KI1N0YXRpc3RpYyBGdW5jaXRvbiBpbiBEYXRhZnJhbWVzDQptZWFuKG10Y2FycyRtcGcpDQoNCm1lZGlhbihtdGNhcnMkbXBnKQ0KDQpyYW5nZShtdGNhcnMkbXBnKQ0KDQpzZChtdGNhcnMkbXBnKQ0KDQoNCmBgYA0KDQojTW9yZSBQbG90cw0KYGBge3J9DQpwbG90KG10Y2FycyRtcGcsIG10Y2FycyRjeWwpDQpgYGANCmBgYHtyfQ0KaGlzdChtdGNhcnMkZGlzcCkNCmBgYA0KYGBge3J9DQpkb3RjaGFydChtdGNhcnMkbXBnLGxhYmVscz1yb3cubmFtZXMobXRjYXJzKSwgY2V4PTAuNywgeGxhYj0iTWlsZXMgUGVyIEdhbGxvbiIpDQpgYGANCmBgYHtyfQ0KcXFub3JtKG10Y2FycyRtcGcpDQpxcWxpbmUobXRjYXJzJG1wZykNCg0KcXFwbG90KG10Y2FycyRtcGcsIG10Y2FycyRocCkNCmBgYA0KYGBge3J9DQpiYXJwbG90KG10Y2FycyRocCkNCmBgYA0KDQoNCg==