R in One Post

Learn R For Free

Featured image R in One Post

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==