This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

plot(cars)

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

Chapter 1 to 3: You can do arithmetic and use # for comments

2*2
[1] 4
2+2
[1] 4
x <-c(1:10)
x
 [1]  1  2  3  4  5  6  7  8  9 10
# doing complicated math examples 
10^2+3*60/8-3
[1] 119.5
5^3*(6-2)/(61-3+4)
[1] 8.064516
2^(2+1)-4+64^((-2)^(2.25-1/4))
[1] 16777220
# Logarithms 
log(x=243,base=3)
[1] 5
# Exponentials
exp(x=3)
[1] 20.08554
log(x=20.08554)
[1] 3

Lesson 2: Assigning objects and Vectors

# you can use either <- or = sign
x <-3
y =3
x+y
[1] 6
myvec <- c(1,2,1,42)
myvec
[1]  1  2  1 42
# Then create a second vector
myvec2 <- c(2,3,4,5)
myvec2
[1] 2 3 4 5
# now create a third vector by appending both myvec and myvec2 together
myvec3 <-c(myvec,myvec2)
myvec3
[1]  1  2  1 42  2  3  4  5
# creating sequences with the : colon 
3:27
 [1]  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
foo <- 5.3
bar <-foo:(-47+1.5)
bar
 [1]   5.3   4.3   3.3   2.3   1.3   0.3  -0.7  -1.7  -2.7  -3.7  -4.7  -5.7  -6.7  -7.7  -8.7  -9.7 -10.7 -11.7
[19] -12.7 -13.7 -14.7 -15.7 -16.7 -17.7 -18.7 -19.7 -20.7 -21.7 -22.7 -23.7 -24.7 -25.7 -26.7 -27.7 -28.7 -29.7
[37] -30.7 -31.7 -32.7 -33.7 -34.7 -35.7 -36.7 -37.7 -38.7 -39.7 -40.7 -41.7 -42.7 -43.7 -44.7
# we can also use the seq command which provides more options
seq(from=3, to=27, by=4)
[1]  3  7 11 15 19 23 27
# instead of by you can also use length.out
seq(from=3, to=27, length.out = 40)
 [1]  3.000000  3.615385  4.230769  4.846154  5.461538  6.076923  6.692308  7.307692  7.923077  8.538462  9.153846
[12]  9.769231 10.384615 11.000000 11.615385 12.230769 12.846154 13.461538 14.076923 14.692308 15.307692 15.923077
[23] 16.538462 17.153846 17.769231 18.384615 19.000000 19.615385 20.230769 20.846154 21.461538 22.076923 22.692308
[34] 23.307692 23.923077 24.538462 25.153846 25.769231 26.384615 27.000000
# Repetition with rep command
rep(x=1,times=4)
[1] 1 1 1 1
rep(x=c(3,62,8.3), times=3)
[1]  3.0 62.0  8.3  3.0 62.0  8.3  3.0 62.0  8.3
rep(x=c(3,62,8.3), each=2)
[1]  3.0  3.0 62.0 62.0  8.3  8.3
rep(x=c(3,62,8.3),times=3, each=2)
 [1]  3.0  3.0 62.0 62.0  8.3  8.3  3.0  3.0 62.0 62.0  8.3  8.3  3.0  3.0 62.0 62.0  8.3  8.3
# sort function
sort(x=c(2.5,-1,-10, 3.44),decreasing = FALSE)
[1] -10.00  -1.00   2.50   3.44
sort(x=c(2.5,-1,-10, 3.44),decreasing = TRUE)
[1]   3.44   2.50  -1.00 -10.00
# finding a vector with length
length(x=c(2.5,-1,-10, 3.44))
[1] 4
length(x=5:13)
[1] 9
# Subsetting or how to address specific elements of an array
myvec3
[1]  1  2  1 42  2  3  4  5
length(myvec3)
[1] 8
myvec3[4]
[1] 42
myvec3[5]
[1] 2
myvec3[4]+myvec3[5]
[1] 44
# Vector-Oriented behavior
foo <-5.5:0.5
foo
[1] 5.5 4.5 3.5 2.5 1.5 0.5
foo-c(2,4,6,8,10,12)
[1]   3.5   0.5  -2.5  -5.5  -8.5 -11.5
# why vectors? Because it is faster adding each element by 3
qux <-3
foo+qux
[1] 8.5 7.5 6.5 5.5 4.5 3.5
sum(foo)
[1] 18
# Vector oriented behavior also applies to overwriting multiple elements
foo
[1] 5.5 4.5 3.5 2.5 1.5 0.5
foo[c(1,3,5,6)]-c(-99,99)
[1] 104.5 -95.5 100.5 -98.5
# from vectors to Matrix (2D) to Arrays (xD)
# use matrix command to create matrix
A <-matrix(data=c(1,2,3,4),nrow=2, ncol = 2)
A
     [,1] [,2]
[1,]    1    3
[2,]    2    4
# you can fill a matrix by row or column using the byrow=true|false
A <- matrix(data = c(1,2,3,4,5,6),nrow = 2, ncol = 3,byrow = FALSE)
A
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
B <- matrix(data = c(1,2,3,4,5,6),nrow = 2, ncol = 3,byrow = TRUE)
B
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
# you can also use rbind anc cbind to create matrix
# rbind creates by row
# cbind creates by column
A <-rbind(1:3,4:6)
A
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
B <-cbind(1:3,4:6)
B
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
# then get its dimensions using the dim command
dim(A)
[1] 2 3
dim(B)
[1] 3 2
# you can also refer to each subelement by the [] notation
A
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
nrow(A)
[1] 2
ncol(A)
[1] 3
dim(A)[2]
[1] 3
# subsetting of a matrix using []
A
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
A[1,2]
[1] 2
# to extract an entire column
A
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
A[,2]
[1] 2 5
# to extract an entire row
A[1,]
[1] 1 2 3
# you can also extract multiple rows or columns
A
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
A[1:2,]
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
A[,1:2]
     [,1] [,2]
[1,]    1    2
[2,]    4    5
# you can omit rows and columns in matrix by using the negative sign
A
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
A[,-2]
     [,1] [,2]
[1,]    1    3
[2,]    4    6

To overwrite particular elements, or entire rows or columsn, you identify the elecments to be replaced and then assign the new values, as you did with vectors.

The new elements acan be a single avlue, a vector of the same length or a vector whose length evenly divides the number of elements to be replaced.

# copy matrix A to B
B <- A
B
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
# overwrite the 2nd row of B with the sequence 1,2,3
B[2,]<-1:3
B
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    1    2    3
# overwrite 2nd column of the first and 3rd rows with 900
B
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    1    2    3
B[-2,2]<-900
B
     [,1] [,2] [,3]
[1,]    1  900    3
[2,]    1    2    3

Matrix Operations and Algebra

# Matrix Transpose
A<-rbind(c(2,5,2),c(6,1,4))
A
     [,1] [,2] [,3]
[1,]    2    5    2
[2,]    6    1    4
t(A)
     [,1] [,2]
[1,]    2    6
[2,]    5    1
[3,]    2    4

Identity Matrix is a square matrix mxm with ones on the diagonal and zeros elsewhere. A quick way to generate an identity matrix is with the use of the diag() command

A <- diag(x=3)
A
     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    1    0
[3,]    0    0    1

Scalar Multiplication of a Matrix Multiplication of any matrix A by a scalar values (a) results in a matrix in which every individual element is multipled by (a)

A <-rbind(c(2,5,2),c(6,1,4))
A
     [,1] [,2] [,3]
[1,]    2    5    2
[2,]    6    1    4
a<-2
a*A
     [,1] [,2] [,3]
[1,]    4   10    4
[2,]   12    2    8

Matrix Addition and Subtraction Additions and substractions of any two matrices of the SAME size is also performed in an element wise fashion.

A <-rbind(c(2,5,2),c(6,1,4))
A
     [,1] [,2] [,3]
[1,]    2    5    2
[2,]    6    1    4
B <- rbind(c(-2,3,6),c(8.1,8.2,-9.8))
B
     [,1] [,2] [,3]
[1,] -2.0  3.0  6.0
[2,]  8.1  8.2 -9.8
A-B
     [,1] [,2] [,3]
[1,]  4.0  2.0 -4.0
[2,] -2.1 -7.2 13.8

Matrix Multiplication In order to multiply two matrics (mxn) and (pxq) n must be equal to p the result is mxq matrix

A <-rbind(c(2,5,2),c(6,1,4))
dim(A)
[1] 2 3
B <-cbind(c(3,-1,1),c(-3,1,5))
dim(B)
[1] 3 2
A
     [,1] [,2] [,3]
[1,]    2    5    2
[2,]    6    1    4
B
     [,1] [,2]
[1,]    3   -3
[2,]   -1    1
[3,]    1    5
A %*% B
     [,1] [,2]
[1,]    3    9
[2,]   21    3

the matrix multiplication is non commutative. reversing the order will give different results:

B %*% A
     [,1] [,2] [,3]
[1,]  -12   12   -6
[2,]    4   -4    2
[3,]   32   10   22

Chapter 4 Non-Numeric Values Logical Values are TRUE (1) or FALSE(0). Here logical values can be added:

TRUE+TRUE
[1] 2
FALSE-TRUE
[1] -1

Relational Operators: (==, !=, >,<,>=,<=) Multiple comparisons (& | !)

Concat function

qux <-c("awesome","R","is")
length(x=qux)
[1] 3
qux
[1] "awesome" "R"       "is"     
cat(qux[2],qux[3],"totally",qux[1],"!")
R is totally awesome !

Using the substring function Substr() function

foo <-"This is a character string!"
substr(x=foo,start=21, stop=27)
[1] "string!"

Factors are R’s way of representing data points tha tfit in only one of a finite number of distinct categories (like nominal values ie sex=male or female)

sex.char <-c("Male","Female","Male","Female")
sex.char
[1] "Male"   "Female" "Male"   "Female"
sex.char.fac<-factor(x=sex.char)
sex.char.fac
[1] Male   Female Male   Female
Levels: Female Male
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiANCg0KYGBge3J9DQpwbG90KGNhcnMpDQpgYGANCg0KQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLg0KDQpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4NCg0KDQpDaGFwdGVyIDEgdG8gMzogWW91IGNhbiBkbyBhcml0aG1ldGljIGFuZCB1c2UgIyBmb3IgY29tbWVudHMNCmBgYHtyfQ0KIyB0aGlzIGlzIGEgY29tbWVudA0KIyBmb2xsb3dlZCBieSBtYXRoIA0KMioyDQoyKzINCiMgZm9sbG93ZWQgYnkgQXJyYXkgT3BzbW9kZSh4KQ0KDQpgYGANCg0KYGBge3J9DQojIGRvaW5nIGNvbXBsaWNhdGVkIG1hdGggZXhhbXBsZXMgDQoxMF4yKzMqNjAvOC0zDQo1XjMqKDYtMikvKDYxLTMrNCkNCjJeKDIrMSktNCs2NF4oKC0yKV4oMi4yNS0xLzQpKQ0KDQoNCg0KYGBgDQoNCmBgYHtyfQ0KIyBMb2dhcml0aG1zIA0KbG9nKHg9MjQzLGJhc2U9MykNCg0KIyBFeHBvbmVudGlhbHMNCmV4cCh4PTMpDQoNCmxvZyh4PTIwLjA4NTU0KQ0KDQpgYGANCkxlc3NvbiAyOiBBc3NpZ25pbmcgb2JqZWN0cyBhbmQgVmVjdG9ycw0KDQpgYGB7cn0NCiMgeW91IGNhbiB1c2UgZWl0aGVyIDwtIG9yID0gc2lnbg0KeCA8LTMNCnkgPTMNCngreQ0KDQpgYGANCmBgYHtyfQ0KIyBjcmVhdGUgYSB2ZWN0b3INCm15dmVjIDwtIGMoMSwyLDEsNDIpDQpteXZlYw0KDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyBUaGVuIGNyZWF0ZSBhIHNlY29uZCB2ZWN0b3INCm15dmVjMiA8LSBjKDIsMyw0LDUpDQpteXZlYzINCg0KIyBub3cgY3JlYXRlIGEgdGhpcmQgdmVjdG9yIGJ5IGFwcGVuZGluZyBib3RoIG15dmVjIGFuZCBteXZlYzIgdG9nZXRoZXINCm15dmVjMyA8LWMobXl2ZWMsbXl2ZWMyKQ0KbXl2ZWMzDQpgYGANCmBgYHtyfQ0KIyBjcmVhdGluZyBzZXF1ZW5jZXMgd2l0aCB0aGUgOiBjb2xvbiANCiMgbWVhbnMgc3RhcnQgZnJvbSAzLCBhbmQgaW5jcmVtZW50IGJ5IDEgdW50aWwgeW91IGdldCB0byAyNw0KMzoyNw0KDQpgYGANCmBgYHtyfQ0KZm9vIDwtIDUuMw0KYmFyIDwtZm9vOigtNDcrMS41KQ0KYmFyDQpgYGANCmBgYHtyfQ0KIyB3ZSBjYW4gYWxzbyB1c2UgdGhlIHNlcSBjb21tYW5kIHdoaWNoIHByb3ZpZGVzIG1vcmUgb3B0aW9ucw0Kc2VxKGZyb209MywgdG89MjcsIGJ5PTQpDQoNCiMgaW5zdGVhZCBvZiBieSB5b3UgY2FuIGFsc28gdXNlIGxlbmd0aC5vdXQgdG8gcHJpbnQgb3V0IGV4YWN0eSA0MCBudW1iZXJzIGZyb20gMyB0byAyNw0Kc2VxKGZyb209MywgdG89MjcsIGxlbmd0aC5vdXQgPSA0MCkNCmBgYA0KDQpgYGB7cn0NCiMgUmVwZXRpdGlvbiB3aXRoIHJlcCBjb21tYW5kDQpyZXAoeD0xLHRpbWVzPTQpDQpyZXAoeD1jKDMsNjIsOC4zKSwgdGltZXM9MykNCnJlcCh4PWMoMyw2Miw4LjMpLCBlYWNoPTIpDQpyZXAoeD1jKDMsNjIsOC4zKSx0aW1lcz0zLCBlYWNoPTIpDQpgYGANCg0KYGBge3J9DQojIHNvcnQgZnVuY3Rpb24NCnNvcnQoeD1jKDIuNSwtMSwtMTAsIDMuNDQpLGRlY3JlYXNpbmcgPSBGQUxTRSkNCnNvcnQoeD1jKDIuNSwtMSwtMTAsIDMuNDQpLGRlY3JlYXNpbmcgPSBUUlVFKQ0KDQoNCmBgYA0KYGBge3J9DQojIGZpbmRpbmcgYSB2ZWN0b3Igd2l0aCBsZW5ndGgNCmxlbmd0aCh4PWMoMi41LC0xLC0xMCwgMy40NCkpDQpsZW5ndGgoeD01OjEzKQ0KDQpgYGANCmBgYHtyfQ0KIyBTdWJzZXR0aW5nIG9yIGhvdyB0byBhZGRyZXNzIHNwZWNpZmljIGVsZW1lbnRzIG9mIGFuIGFycmF5DQojIHVzZSBbXSB0byBzcGVjaWZ5IHRoZSBudGggZWxlbWVudCBvZiBlYWNoIGFycmF5DQpteXZlYzMNCmxlbmd0aChteXZlYzMpDQpteXZlYzNbNF0NCm15dmVjM1s1XQ0KbXl2ZWMzWzRdK215dmVjM1s1XQ0KDQpgYGANCmBgYHtyfQ0KIyBWZWN0b3ItT3JpZW50ZWQgYmVoYXZpb3INCmZvbyA8LTUuNTowLjUNCmZvbw0KZm9vLWMoMiw0LDYsOCwxMCwxMikNCg0KYGBgDQpgYGB7cn0NCiMgd2h5IHZlY3RvcnM/IEJlY2F1c2UgaXQgaXMgZmFzdGVyIGFkZGluZyBlYWNoIGVsZW1lbnQgYnkgMw0KcXV4IDwtMw0KZm9vK3F1eA0Kc3VtKGZvbykNCmBgYA0KYGBge3J9DQojIFZlY3RvciBvcmllbnRlZCBiZWhhdmlvciBhbHNvIGFwcGxpZXMgdG8gb3ZlcndyaXRpbmcgbXVsdGlwbGUgZWxlbWVudHMNCmZvbw0KZm9vW2MoMSwzLDUsNildLWMoLTk5LDk5KQ0KDQojIG90aGVyIGZ1bmN0aW9uczogc3FydCwgcHJvZA0KYGBgDQoNCmBgYHtyfQ0KIyBmcm9tIHZlY3RvcnMgdG8gTWF0cml4ICgyRCkgdG8gQXJyYXlzICh4RCkNCiMgdXNlIG1hdHJpeCBjb21tYW5kIHRvIGNyZWF0ZSBtYXRyaXgNCkEgPC1tYXRyaXgoZGF0YT1jKDEsMiwzLDQpLG5yb3c9MiwgbmNvbCA9IDIpDQpBDQpgYGANCmBgYHtyfQ0KIyB5b3UgY2FuIGZpbGwgYSBtYXRyaXggYnkgcm93IG9yIGNvbHVtbiB1c2luZyB0aGUgYnlyb3c9dHJ1ZXxmYWxzZQ0KQSA8LSBtYXRyaXgoZGF0YSA9IGMoMSwyLDMsNCw1LDYpLG5yb3cgPSAyLCBuY29sID0gMyxieXJvdyA9IEZBTFNFKQ0KQQ0KQiA8LSBtYXRyaXgoZGF0YSA9IGMoMSwyLDMsNCw1LDYpLG5yb3cgPSAyLCBuY29sID0gMyxieXJvdyA9IFRSVUUpDQpCDQpgYGANCmBgYHtyfQ0KIyB5b3UgY2FuIGFsc28gdXNlIHJiaW5kIGFuYyBjYmluZCB0byBjcmVhdGUgbWF0cml4DQojIHJiaW5kIGNyZWF0ZXMgYnkgcm93DQojIGNiaW5kIGNyZWF0ZXMgYnkgY29sdW1uDQpBIDwtcmJpbmQoMTozLDQ6NikNCkENCkIgPC1jYmluZCgxOjMsNDo2KQ0KQg0KIyB0aGVuIGdldCBpdHMgZGltZW5zaW9ucyB1c2luZyB0aGUgZGltIGNvbW1hbmQNCmRpbShBKQ0KZGltKEIpDQoNCmBgYA0KYGBge3J9DQojIHlvdSBjYW4gYWxzbyByZWZlciB0byBlYWNoIHN1YmVsZW1lbnQgYnkgdGhlIFtdIG5vdGF0aW9uDQpBDQpucm93KEEpDQpuY29sKEEpDQpkaW0oQSlbMl0NCmBgYA0KDQpgYGB7cn0NCiMgc3Vic2V0dGluZyBvZiBhIG1hdHJpeCB1c2luZyBbXQ0KQQ0KQVsxLDJdDQoNCmBgYA0KYGBge3J9DQojIHRvIGV4dHJhY3QgYW4gZW50aXJlIGNvbHVtbg0KQQ0KQVssMl0NCiMgdG8gZXh0cmFjdCBhbiBlbnRpcmUgcm93DQpBWzEsXQ0KYGBgDQoNCmBgYHtyfQ0KIyB5b3UgY2FuIGFsc28gZXh0cmFjdCBtdWx0aXBsZSByb3dzIG9yIGNvbHVtbnMNCkENCkFbMToyLF0NCkFbLDE6Ml0NCmBgYA0KYGBge3J9DQojIHlvdSBjYW4gb21pdCByb3dzIGFuZCBjb2x1bW5zIGluIG1hdHJpeCBieSB1c2luZyB0aGUgbmVnYXRpdmUgc2lnbg0KQQ0KIyB0byBzaG93IG9ubHkgY29sdW1uIDEgYW5kIDMgDQpBWywtMl0NCg0KYGBgDQpUbyBvdmVyd3JpdGUgcGFydGljdWxhciBlbGVtZW50cywgb3IgZW50aXJlIHJvd3Mgb3IgY29sdW1zbiwgeW91IGlkZW50aWZ5IHRoZSBlbGVjbWVudHMgdG8gYmUgcmVwbGFjZWQgYW5kIHRoZW4gYXNzaWduIHRoZSBuZXcgdmFsdWVzLCBhcyB5b3UgZGlkIHdpdGggdmVjdG9ycy4gDQoNClRoZSBuZXcgZWxlbWVudHMgYWNhbiBiZSBhIHNpbmdsZSBhdmx1ZSwgYSB2ZWN0b3Igb2YgdGhlIHNhbWUgbGVuZ3RoIG9yIGEgdmVjdG9yIHdob3NlIGxlbmd0aCBldmVubHkgZGl2aWRlcyB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIGJlIHJlcGxhY2VkLg0KYGBge3J9DQojIGNvcHkgbWF0cml4IEEgdG8gQg0KQiA8LSBBDQpCDQojIG92ZXJ3cml0ZSB0aGUgMm5kIHJvdyBvZiBCIHdpdGggdGhlIHNlcXVlbmNlIDEsMiwzDQpCWzIsXTwtMTozDQpCDQpgYGANCg0KYGBge3J9DQojIG92ZXJ3cml0ZSAybmQgY29sdW1uIG9mIHRoZSBmaXJzdCBhbmQgM3JkIHJvd3Mgd2l0aCA5MDANCkINCkJbLTIsMl08LTkwMA0KQg0KDQpgYGANCg0KTWF0cml4IE9wZXJhdGlvbnMgYW5kIEFsZ2VicmENCmBgYHtyfQ0KIyBNYXRyaXggVHJhbnNwb3NlIHVzaW5nIHQoKQ0KQTwtcmJpbmQoYygyLDUsMiksYyg2LDEsNCkpDQpBDQp0KEEpDQoNCmBgYA0KDQpJZGVudGl0eSBNYXRyaXggaXMgYSBzcXVhcmUgbWF0cml4IG14bSB3aXRoIG9uZXMgb24gdGhlIGRpYWdvbmFsIGFuZCB6ZXJvcyBlbHNld2hlcmUuDQpBIHF1aWNrIHdheSB0byBnZW5lcmF0ZSBhbiBpZGVudGl0eSBtYXRyaXggaXMgd2l0aCB0aGUgdXNlIG9mIHRoZSBkaWFnKCkgY29tbWFuZA0KYGBge3J9DQpBIDwtIGRpYWcoeD0zKQ0KQQ0KDQpgYGANClNjYWxhciBNdWx0aXBsaWNhdGlvbiBvZiBhIE1hdHJpeA0KTXVsdGlwbGljYXRpb24gb2YgYW55IG1hdHJpeCBBIGJ5IGEgc2NhbGFyIHZhbHVlcyAoYSkgcmVzdWx0cyBpbiBhIG1hdHJpeCBpbiB3aGljaCBldmVyeSBpbmRpdmlkdWFsIGVsZW1lbnQgaXMgbXVsdGlwbGVkIGJ5IChhKQ0KDQpgYGB7cn0NCkEgPC1yYmluZChjKDIsNSwyKSxjKDYsMSw0KSkNCkENCmE8LTINCmEqQQ0KDQpgYGANCg0KTWF0cml4IEFkZGl0aW9uIGFuZCBTdWJ0cmFjdGlvbg0KQWRkaXRpb25zIGFuZCBzdWJzdHJhY3Rpb25zIG9mIGFueSB0d28gbWF0cmljZXMgb2YgdGhlIFNBTUUgc2l6ZSBpcyBhbHNvIHBlcmZvcm1lZCBpbiBhbiBlbGVtZW50IHdpc2UgZmFzaGlvbi4NCmBgYHtyfQ0KQSA8LXJiaW5kKGMoMiw1LDIpLGMoNiwxLDQpKQ0KQQ0KQiA8LSByYmluZChjKC0yLDMsNiksYyg4LjEsOC4yLC05LjgpKQ0KQg0KQS1CDQoNCmBgYA0KTWF0cml4IE11bHRpcGxpY2F0aW9uDQpJbiBvcmRlciB0byBtdWx0aXBseSB0d28gbWF0cmljcyAobXhuKSBhbmQgKHB4cSkNCm4gbXVzdCBiZSBlcXVhbCB0byBwDQp0aGUgcmVzdWx0IGlzIG14cSBtYXRyaXgNCg0KYGBge3J9DQpBIDwtcmJpbmQoYygyLDUsMiksYyg2LDEsNCkpDQpkaW0oQSkNCkIgPC1jYmluZChjKDMsLTEsMSksYygtMywxLDUpKQ0KZGltKEIpDQoNCmBgYA0KYGBge3J9DQpBDQpCDQpBICUqJSBCDQpgYGANCg0KdGhlIG1hdHJpeCBtdWx0aXBsaWNhdGlvbiBpcyBub24gY29tbXV0YXRpdmUuDQpyZXZlcnNpbmcgdGhlIG9yZGVyIHdpbGwgZ2l2ZSBkaWZmZXJlbnQgcmVzdWx0czoNCmBgYHtyfQ0KQiAlKiUgQQ0KDQpgYGANCkNoYXB0ZXIgNCBOb24tTnVtZXJpYyBWYWx1ZXMNCkxvZ2ljYWwgVmFsdWVzIGFyZSBUUlVFICgxKSBvciBGQUxTRSgwKS4gDQpIZXJlIGxvZ2ljYWwgdmFsdWVzIGNhbiBiZSBhZGRlZDoNCmBgYHtyfQ0KVFJVRStUUlVFDQpGQUxTRS1UUlVFDQoNCmBgYA0KUmVsYXRpb25hbCBPcGVyYXRvcnM6ICg9PSwgIT0sID4sPCw+PSw8PSkNCk11bHRpcGxlIGNvbXBhcmlzb25zICgmIHwgISkNCg0KQ29uY2F0IGZ1bmN0aW9uDQpgYGB7cn0NCnF1eCA8LWMoImF3ZXNvbWUiLCJSIiwiaXMiKQ0KbGVuZ3RoKHg9cXV4KQ0KcXV4DQpjYXQocXV4WzJdLHF1eFszXSwidG90YWxseSIscXV4WzFdLCIhIikNCg0KYGBgDQpVc2luZyB0aGUgc3Vic3RyaW5nIGZ1bmN0aW9uDQpTdWJzdHIoKSBmdW5jdGlvbg0KYGBge3J9DQpmb28gPC0iVGhpcyBpcyBhIGNoYXJhY3RlciBzdHJpbmchIg0Kc3Vic3RyKHg9Zm9vLHN0YXJ0PTIxLCBzdG9wPTI3KQ0KDQpgYGANCkZhY3RvcnMgYXJlIFIncyB3YXkgb2YgcmVwcmVzZW50aW5nIGRhdGEgcG9pbnRzIHRoYSB0Zml0IGluIG9ubHkgb25lIG9mIGEgZmluaXRlIG51bWJlciBvZiBkaXN0aW5jdCBjYXRlZ29yaWVzIChsaWtlIG5vbWluYWwgdmFsdWVzIGllIHNleD1tYWxlIG9yIGZlbWFsZSkNCg0KYGBge3J9DQpzZXguY2hhciA8LWMoIk1hbGUiLCJGZW1hbGUiLCJNYWxlIiwiRmVtYWxlIikNCnNleC5jaGFyDQpzZXguY2hhci5mYWM8LWZhY3Rvcih4PXNleC5jaGFyKQ0Kc2V4LmNoYXIuZmFjDQoNCg0KYGBgDQoNCg==