Vector Element Names

The elements of a vector can optionally be given names. For example, say we have a 50-element vector showing the population of each state in the United States. We could name each element according to its state name, such as “Montana” and “New Jersey”. This in turn might lead to naming points in plots, and so on.

x <- c(896,254,85641)
names(x)
NULL

-> Null since there are no ‘headers’ specified

# Please create a vector x1 and follow the steps of this exercise.
x1 <- c(856123,97845,984561)

We can assign or query vector element names via the names() function:

names(x) <- c("a","b","ab")
names(x)
[1] "a"  "b"  "ab"

-> with ‘headers’ being defined, the names function returns those assigned ‘headers’

x
    a     b    ab 
  896   254 85641 

-> x now conatains headers with respective values

We can remove the names from a vector by assigning NULL:

names(x) <- NULL
x
[1]   896   254 85641

-> ‘headers’ are removed by assigning NULL to names

We can even reference elements of the vector by name:

x <- c(1,2,4)
names(x) <- c("a","b","ab")
x["b"]
b 
2 

-> returns the element (2) with the ‘header’ b within x

MATRICES AND ARRAYS

A matrix is a vector with two additional attributes: the number of rows and the number of columns. Since matrices are vectors, they also have modes, such as numeric and character.

Cretaing Matrices

y<-matrix(c(1,2,3,4),nrow=2,ncol=2)
y
     [,1] [,2]
[1,]    1    3
[2,]    2    4

-> creates 2-dimensional matrix with two rows and two columns

#Please create a matrix y1 and follow the steps below
y1 <- matrix(c(852,258,456,159), nrow=2, ncol=2)
y1
     [,1] [,2]
[1,]  852  456
[2,]  258  159

Since we specified the matrix entries in the preceding example, and there were four of them, we did not need to specify both ncol and nrow; just nrow or ncol would have been enough. Having four elements in all, in two rows, implies two columns:

y <- matrix(c(1,2,3,4),nrow=2)
y
     [,1] [,2]
[1,]    1    3
[2,]    2    4

Note that when we then print out y, R shows us its notation for rows and columns. For instance, [,2] means the entirety of column 2, as can be seen in this check:

y[,2]
[1] 3 4

-> returns column 2

Another way to build y is to specify elements individually:

y <- matrix(nrow=2,ncol=2)
y
     [,1] [,2]
[1,]   NA   NA
[2,]   NA   NA

-> creates empty matrix with 2 rows and 2 columns

y[1,1] <- 1
y[2,1] <- 2
y[1,2] <- 3
y[2,2] <- 4
y
     [,1] [,2]
[1,]    1    3
[2,]    2    4

-> assigns values to specific locations within the matrix

Note that we do need to warn R ahead of time that y will be a matrix and give the number of rows and columns.

Though internal storage of a matrix is in column-major order, you can set the byrow argument in matrix() to true to indicate that the data is coming in row-major order. Here’s an example of using byrow:

m <- matrix(c(1,2,3,4,5,6),nrow=2,byrow=T)
m
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
#Create a matrix m1 and recreate a similar case scenario to the one above.
m1 <- matrix(c(195,2745,335,4719,5371,6195),nrow=2,byrow=T)
m1
     [,1] [,2] [,3]
[1,]  195 2745  335
[2,] 4719 5371 6195

-> have the matrix created in row-major order

General Matrix Operations

Performing Linear Algebra Operations on Matrices

You can perform various linear algebra operations on matrices, such as matrix multiplication, matrix scalar multiplication, and matrix addition. Using y from the preceding example, here is how to perform those three operations:

y %*% y # mathematical matrix multiplication
     [,1] [,2]
[1,]    7   15
[2,]   10   22
3*y # mathematical multiplication of matrix by scalar
     [,1] [,2]
[1,]    3    9
[2,]    6   12
y+y # mathematical matrix addition
     [,1] [,2]
[1,]    2    6
[2,]    4    8
y1 %*% y1 # mathematical matrix multiplication
       [,1]   [,2]
[1,] 843552 461016
[2,] 260838 142929
3*y1 # mathematical multiplication of matrix by scalar
     [,1] [,2]
[1,] 2556 1368
[2,]  774  477
y1+y1 # mathematical matrix addition
     [,1] [,2]
[1,] 1704  912
[2,]  516  318

Matrix Indexing

Let us say that we have a matrix z:

z <- matrix(nrow=4,ncol=3)
z[1,1] <- 1
z[2,1] <- 2
z[1,2] <- 1
z[2,2] <- 1
z[3,1] <- 3
z[3,2] <- 0
z[3,3] <- 1
z[1,3] <- 1
z[2,3] <- 0
z[4,1] <- 4
z[4,2] <- 0
z[4,3] <- 0
z
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    1    0
[3,]    3    0    1
[4,]    4    0    0

-> 2-dimensional matrix with four rows and three columns

Let us obtain the submatrix of z consisting of all elements with column numbers 2 and 3 and any row number. This extracts the second and third columns.

z[,2:3]
     [,1] [,2]
[1,]    1    1
[2,]    1    0
[3,]    0    1
[4,]    0    0

-> extracts last two columns and all four rows

Let us now extract rows instead of columns.

#Create amatrix z1 and recreate a similar case scenario. 
z1 <- matrix(nrow=4,ncol=3)
z1[1,1] <- 18852
z1[2,1] <- 20235
z1[1,2] <- 156122
z1[2,2] <- 1651
z1[3,1] <- 35631
z1[3,2] <- 231
z1[3,3] <- 123165
z1[1,3] <- 1856213
z1[2,3] <- 213165
z1[4,1] <- 4565161
z1[4,2] <- 5613121
z1[4,3] <- 32198
z1
        [,1]    [,2]    [,3]
[1,]   18852  156122 1856213
[2,]   20235    1651  213165
[3,]   35631     231  123165
[4,] 4565161 5613121   32198
z1[2:1,]
      [,1]   [,2]    [,3]
[1,] 20235   1651  213165
[2,] 18852 156122 1856213

-> returns the second and first rows for all three columns of matrix z1

Adding and Deleting Matrix Rows and Columns Technically, matrices are of fixed length and dimensions, so we cannot add or delete rows or columns. However, matrices can be reassigned, and thus we can achieve the same effect as if we had directly done additions or deletions.

Changing the Size of a Matrix

x<-c(1,12,5,13,16,8)
x
[1]  1 12  5 13 16  8
x <- c(x,20) # append 20
x
[1]  1 12  5 13 16  8 20

-> appends 20 to the existing x vector

x <- c(x[1:3],20,x[4:6]) # insert 20
x
[1]  1 12  5 20 13 16  8

-> inserts 20 between the 3rd and 4th elemnt of x

x <- x[-2:-4] # delete elements 2 through 4
x
[1]  1 13 16  8

-> deletes elements 2 through 4

Analogous operations can be used to change the size of a matrix. For instance, the rbind() (row bind) and cbind() (column bind) functions let you add rows or columns to a matrix.

one<-c(1,1,1,1)
one
[1] 1 1 1 1
z
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    3    0    1
cbind(one,z)
     one      
[1,]   1 1 1 1
[2,]   1 2 1 0
[3,]   1 3 0 1
[4,]   1 4 0 0

Here, cbind() creates a new matrix by combining a column of 1s with the columns of z. We choose to get a quick printout, but we could have assigned the result to z (or another variable), as follows:

cbind(z,one)
           one
[1,] 1 1 1   1
[2,] 2 1 0   1
[3,] 3 0 1   1
[4,] 4 0 0   1

-> binds one to the end of z

z <- cbind(one,z)

-> binds z to end of one and assigns new matrix to z

Note, too, that we could have relied on recycling:

cbind(1,z)
       one      
[1,] 1   1 1 1 1
[2,] 1   1 2 1 0
[3,] 1   1 3 0 1
[4,] 1   1 4 0 0

-> adds column of ones to beginning of z

You can also use the rbind() and cbind() functions as a quick way to create small matrices. Here’s an example:

q <- cbind(c(1,2),c(3,4))
q
     [,1] [,2]
[1,]    1    3
[2,]    2    4

-> creates new matrix with cbind function

You can delete rows or columns by reassignment, too:

m <- matrix(1:6,nrow=3)
m
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

-> reassigns matrix to m and, therefore, deletes old, unused values

z <- z[c(1,3),]
z
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    3    0    1

-> returns first and thrid row of z

LS0tDQp0aXRsZTogIkFjdGl2aXR5IDYiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoqKlZlY3RvciBFbGVtZW50IE5hbWVzKioNCg0KVGhlIGVsZW1lbnRzIG9mIGEgdmVjdG9yIGNhbiBvcHRpb25hbGx5IGJlIGdpdmVuIG5hbWVzLiBGb3IgZXhhbXBsZSwgc2F5IHdlIGhhdmUgYSA1MC1lbGVtZW50IHZlY3RvciBzaG93aW5nIHRoZSBwb3B1bGF0aW9uIG9mIGVhY2ggc3RhdGUgaW4gdGhlIFVuaXRlZCBTdGF0ZXMuIFdlIGNvdWxkIG5hbWUgZWFjaCBlbGVtZW50IGFjY29yZGluZyB0byBpdHMgc3RhdGUgbmFtZSwgc3VjaCBhcyAiTW9udGFuYSIgYW5kICJOZXcgSmVyc2V5Ii4gVGhpcyBpbiB0dXJuIG1pZ2h0IGxlYWQgdG8gbmFtaW5nIHBvaW50cyBpbiBwbG90cywgYW5kIHNvIG9uLg0KDQpgYGB7cn0NCnggPC0gYyg4OTYsMjU0LDg1NjQxKQ0KbmFtZXMoeCkNCmBgYA0KLT4gTnVsbCBzaW5jZSB0aGVyZSBhcmUgbm8gJ2hlYWRlcnMnIHNwZWNpZmllZA0KDQpgYGB7cn0NCiMgUGxlYXNlIGNyZWF0ZSBhIHZlY3RvciB4MSBhbmQgZm9sbG93IHRoZSBzdGVwcyBvZiB0aGlzIGV4ZXJjaXNlLg0KeDEgPC0gYyg4NTYxMjMsOTc4NDUsOTg0NTYxKQ0KYGBgDQoNCg0KDQpXZSBjYW4gYXNzaWduIG9yIHF1ZXJ5IHZlY3RvciBlbGVtZW50IG5hbWVzIHZpYSB0aGUgbmFtZXMoKSBmdW5jdGlvbjoNCg0KYGBge3J9DQpuYW1lcyh4KSA8LSBjKCJhIiwiYiIsImFiIikNCm5hbWVzKHgpDQpgYGANCi0+IHdpdGggJ2hlYWRlcnMnIGJlaW5nIGRlZmluZWQsIHRoZSBuYW1lcyBmdW5jdGlvbiByZXR1cm5zIHRob3NlIGFzc2lnbmVkICdoZWFkZXJzJw0KDQoNCmBgYHtyfQ0KeA0KYGBgDQotPiB4IG5vdyBjb25hdGFpbnMgaGVhZGVycyB3aXRoIHJlc3BlY3RpdmUgdmFsdWVzDQoNCg0KV2UgY2FuIHJlbW92ZSB0aGUgbmFtZXMgZnJvbSBhIHZlY3RvciBieSBhc3NpZ25pbmcgTlVMTDoNCg0KYGBge3J9DQpuYW1lcyh4KSA8LSBOVUxMDQp4DQpgYGANCi0+ICdoZWFkZXJzJyBhcmUgcmVtb3ZlZCBieSBhc3NpZ25pbmcgTlVMTCB0byBuYW1lcw0KDQpXZSBjYW4gZXZlbiByZWZlcmVuY2UgZWxlbWVudHMgb2YgdGhlIHZlY3RvciBieSBuYW1lOg0KDQpgYGB7cn0NCnggPC0gYygxLDIsNCkNCm5hbWVzKHgpIDwtIGMoImEiLCJiIiwiYWIiKQ0KeFsiYiJdDQpgYGANCi0+IHJldHVybnMgdGhlIGVsZW1lbnQgKDIpIHdpdGggdGhlICdoZWFkZXInIGIgd2l0aGluIHgNCg0KDQoNCioqTUFUUklDRVMgQU5EIEFSUkFZUyoqDQoNCkEgbWF0cml4IGlzIGEgdmVjdG9yIHdpdGggdHdvIGFkZGl0aW9uYWwgYXR0cmlidXRlczogdGhlIG51bWJlciBvZiByb3dzIGFuZCB0aGUgbnVtYmVyIG9mIGNvbHVtbnMuIFNpbmNlIG1hdHJpY2VzIGFyZSB2ZWN0b3JzLA0KdGhleSBhbHNvIGhhdmUgbW9kZXMsIHN1Y2ggYXMgbnVtZXJpYyBhbmQgY2hhcmFjdGVyLg0KDQoqKkNyZXRhaW5nIE1hdHJpY2VzKioNCg0KDQpgYGB7cn0NCnk8LW1hdHJpeChjKDEsMiwzLDQpLG5yb3c9MixuY29sPTIpDQp5DQpgYGANCi0+IGNyZWF0ZXMgMi1kaW1lbnNpb25hbCBtYXRyaXggd2l0aCB0d28gcm93cyBhbmQgdHdvIGNvbHVtbnMNCg0KDQpgYGB7cn0NCiNQbGVhc2UgY3JlYXRlIGEgbWF0cml4IHkxIGFuZCBmb2xsb3cgdGhlIHN0ZXBzIGJlbG93DQp5MSA8LSBtYXRyaXgoYyg4NTIsMjU4LDQ1NiwxNTkpLCBucm93PTIsIG5jb2w9MikNCnkxDQpgYGANCg0KU2luY2Ugd2Ugc3BlY2lmaWVkIHRoZSBtYXRyaXggZW50cmllcyBpbiB0aGUgcHJlY2VkaW5nIGV4YW1wbGUsIGFuZCB0aGVyZSB3ZXJlIGZvdXIgb2YgdGhlbSwgd2UgZGlkIG5vdCBuZWVkIHRvIHNwZWNpZnkgYm90aCBuY29sIGFuZCBucm93OyBqdXN0IG5yb3cgb3IgbmNvbCB3b3VsZCBoYXZlIGJlZW4gZW5vdWdoLiBIYXZpbmcgZm91ciBlbGVtZW50cyBpbiBhbGwsIGluIHR3byByb3dzLCBpbXBsaWVzIHR3byBjb2x1bW5zOg0KDQpgYGB7cn0NCnkgPC0gbWF0cml4KGMoMSwyLDMsNCksbnJvdz0yKQ0KeQ0KYGBgDQoNCg0KTm90ZSB0aGF0IHdoZW4gd2UgdGhlbiBwcmludCBvdXQgeSwgUiBzaG93cyB1cyBpdHMgbm90YXRpb24gZm9yIHJvd3MgYW5kIGNvbHVtbnMuIEZvciBpbnN0YW5jZSwgWywyXSBtZWFucyB0aGUgZW50aXJldHkgb2YgY29sdW1uIDIsIGFzIGNhbiBiZSBzZWVuIGluIHRoaXMgY2hlY2s6DQoNCmBgYHtyfQ0KeVssMl0NCmBgYA0KLT4gcmV0dXJucyBjb2x1bW4gMg0KDQoNCkFub3RoZXIgd2F5IHRvIGJ1aWxkIHkgaXMgdG8gc3BlY2lmeSBlbGVtZW50cyBpbmRpdmlkdWFsbHk6DQoNCg0KYGBge3J9DQp5IDwtIG1hdHJpeChucm93PTIsbmNvbD0yKQ0KeQ0KYGBgDQotPiBjcmVhdGVzIGVtcHR5IG1hdHJpeCB3aXRoIDIgcm93cyBhbmQgMiBjb2x1bW5zDQoNCg0KYGBge3J9DQp5WzEsMV0gPC0gMQ0KeVsyLDFdIDwtIDINCnlbMSwyXSA8LSAzDQp5WzIsMl0gPC0gNA0KeQ0KYGBgDQotPiBhc3NpZ25zIHZhbHVlcyB0byBzcGVjaWZpYyBsb2NhdGlvbnMgd2l0aGluIHRoZSBtYXRyaXgNCg0KDQpOb3RlIHRoYXQgd2UgZG8gbmVlZCB0byB3YXJuIFIgYWhlYWQgb2YgdGltZSB0aGF0IHkgd2lsbCBiZSBhIG1hdHJpeCBhbmQgZ2l2ZSB0aGUgbnVtYmVyIG9mIHJvd3MgYW5kIGNvbHVtbnMuDQoNClRob3VnaCBpbnRlcm5hbCBzdG9yYWdlIG9mIGEgbWF0cml4IGlzIGluIGNvbHVtbi1tYWpvciBvcmRlciwgeW91IGNhbiBzZXQgdGhlIGJ5cm93IGFyZ3VtZW50IGluIG1hdHJpeCgpIHRvIHRydWUgdG8gaW5kaWNhdGUgdGhhdCB0aGUgZGF0YSBpcyBjb21pbmcgaW4gcm93LW1ham9yIG9yZGVyLiBIZXJl4oCZcyBhbiBleGFtcGxlIG9mIHVzaW5nIGJ5cm93Og0KDQpgYGB7cn0NCm0gPC0gbWF0cml4KGMoMSwyLDMsNCw1LDYpLG5yb3c9MixieXJvdz1UKQ0KbQ0KYGBgDQoNCmBgYHtyfQ0KI0NyZWF0ZSBhIG1hdHJpeCBtMSBhbmQgcmVjcmVhdGUgYSBzaW1pbGFyIGNhc2Ugc2NlbmFyaW8gdG8gdGhlIG9uZSBhYm92ZS4NCm0xIDwtIG1hdHJpeChjKDE5NSwyNzQ1LDMzNSw0NzE5LDUzNzEsNjE5NSksbnJvdz0yLGJ5cm93PVQpDQptMQ0KYGBgDQotPiBoYXZlIHRoZSBtYXRyaXggY3JlYXRlZCBpbiByb3ctbWFqb3Igb3JkZXINCg0KDQoNCioqR2VuZXJhbCBNYXRyaXggT3BlcmF0aW9ucyoqDQoNClBlcmZvcm1pbmcgTGluZWFyIEFsZ2VicmEgT3BlcmF0aW9ucyBvbiBNYXRyaWNlcw0KDQpZb3UgY2FuIHBlcmZvcm0gdmFyaW91cyBsaW5lYXIgYWxnZWJyYSBvcGVyYXRpb25zIG9uIG1hdHJpY2VzLCBzdWNoIGFzIG1hdHJpeCBtdWx0aXBsaWNhdGlvbiwgbWF0cml4IHNjYWxhciBtdWx0aXBsaWNhdGlvbiwgYW5kIG1hdHJpeCBhZGRpdGlvbi4gVXNpbmcgeSBmcm9tIHRoZSBwcmVjZWRpbmcgZXhhbXBsZSwgaGVyZSBpcyBob3cgdG8gcGVyZm9ybSB0aG9zZSB0aHJlZSBvcGVyYXRpb25zOg0KDQpgYGB7cn0NCnkgJSolIHkgIyBtYXRoZW1hdGljYWwgbWF0cml4IG11bHRpcGxpY2F0aW9uDQpgYGANCg0KYGBge3J9DQozKnkgIyBtYXRoZW1hdGljYWwgbXVsdGlwbGljYXRpb24gb2YgbWF0cml4IGJ5IHNjYWxhcg0KYGBgDQoNCg0KDQpgYGB7cn0NCnkreSAjIG1hdGhlbWF0aWNhbCBtYXRyaXggYWRkaXRpb24NCmBgYA0KDQpgYGB7cn0NCnkxICUqJSB5MSAjIG1hdGhlbWF0aWNhbCBtYXRyaXggbXVsdGlwbGljYXRpb24NCmBgYA0KDQpgYGB7cn0NCjMqeTEgIyBtYXRoZW1hdGljYWwgbXVsdGlwbGljYXRpb24gb2YgbWF0cml4IGJ5IHNjYWxhcg0KYGBgDQoNCg0KDQpgYGB7cn0NCnkxK3kxICMgbWF0aGVtYXRpY2FsIG1hdHJpeCBhZGRpdGlvbg0KYGBgDQoNCg0KKipNYXRyaXggSW5kZXhpbmcqKg0KDQpMZXQgdXMgc2F5IHRoYXQgd2UgaGF2ZSBhIG1hdHJpeCB6Og0KDQpgYGB7cn0NCnogPC0gbWF0cml4KG5yb3c9NCxuY29sPTMpDQp6WzEsMV0gPC0gMQ0KelsyLDFdIDwtIDINCnpbMSwyXSA8LSAxDQp6WzIsMl0gPC0gMQ0KelszLDFdIDwtIDMNCnpbMywyXSA8LSAwDQp6WzMsM10gPC0gMQ0KelsxLDNdIDwtIDENCnpbMiwzXSA8LSAwDQp6WzQsMV0gPC0gNA0Kels0LDJdIDwtIDANCnpbNCwzXSA8LSAwDQpgYGANCg0KDQpgYGB7cn0NCnoNCmBgYA0KLT4gMi1kaW1lbnNpb25hbCBtYXRyaXggd2l0aCBmb3VyIHJvd3MgYW5kIHRocmVlIGNvbHVtbnMNCg0KDQpMZXQgdXMgb2J0YWluIHRoZSBzdWJtYXRyaXggb2YgeiBjb25zaXN0aW5nIG9mIGFsbCBlbGVtZW50cyB3aXRoIGNvbHVtbiBudW1iZXJzIDIgYW5kIDMgYW5kIGFueSByb3cgbnVtYmVyLiBUaGlzIGV4dHJhY3RzIHRoZSBzZWNvbmQgYW5kIHRoaXJkIGNvbHVtbnMuDQoNCmBgYHtyfQ0KelssMjozXQ0KYGBgDQotPiBleHRyYWN0cyBsYXN0IHR3byBjb2x1bW5zIGFuZCBhbGwgZm91ciByb3dzDQoNCg0KTGV0IHVzIG5vdyBleHRyYWN0IHJvd3MgaW5zdGVhZCBvZiBjb2x1bW5zLg0KDQoNCmBgYHtyfQ0KI0NyZWF0ZSBhbWF0cml4IHoxIGFuZCByZWNyZWF0ZSBhIHNpbWlsYXIgY2FzZSBzY2VuYXJpby4gDQp6MSA8LSBtYXRyaXgobnJvdz00LG5jb2w9MykNCnoxWzEsMV0gPC0gMTg4NTINCnoxWzIsMV0gPC0gMjAyMzUNCnoxWzEsMl0gPC0gMTU2MTIyDQp6MVsyLDJdIDwtIDE2NTENCnoxWzMsMV0gPC0gMzU2MzENCnoxWzMsMl0gPC0gMjMxDQp6MVszLDNdIDwtIDEyMzE2NQ0KejFbMSwzXSA8LSAxODU2MjEzDQp6MVsyLDNdIDwtIDIxMzE2NQ0KejFbNCwxXSA8LSA0NTY1MTYxDQp6MVs0LDJdIDwtIDU2MTMxMjENCnoxWzQsM10gPC0gMzIxOTgNCmBgYA0KDQoNCmBgYHtyfQ0KejENCmBgYA0KDQoNCmBgYHtyfQ0KejFbMjoxLF0NCmBgYA0KLT4gcmV0dXJucyB0aGUgc2Vjb25kIGFuZCBmaXJzdCByb3dzIGZvciBhbGwgdGhyZWUgY29sdW1ucyBvZiBtYXRyaXggejENCg0KDQoqKkFkZGluZyBhbmQgRGVsZXRpbmcgTWF0cml4IFJvd3MgYW5kIENvbHVtbnMqKg0KVGVjaG5pY2FsbHksIG1hdHJpY2VzIGFyZSBvZiBmaXhlZCBsZW5ndGggYW5kIGRpbWVuc2lvbnMsIHNvIHdlIGNhbm5vdCBhZGQgb3IgZGVsZXRlIHJvd3Mgb3IgY29sdW1ucy4gSG93ZXZlciwgbWF0cmljZXMgY2FuIGJlIHJlYXNzaWduZWQsIGFuZCB0aHVzIHdlIGNhbiBhY2hpZXZlIHRoZSBzYW1lIGVmZmVjdCBhcyBpZiB3ZSBoYWQgZGlyZWN0bHkgZG9uZSBhZGRpdGlvbnMgb3IgZGVsZXRpb25zLg0KDQpDaGFuZ2luZyB0aGUgU2l6ZSBvZiBhIE1hdHJpeA0KDQpgYGB7cn0NCng8LWMoMSwxMiw1LDEzLDE2LDgpDQp4DQpgYGANCg0KDQpgYGB7cn0NCnggPC0gYyh4LDIwKSAjIGFwcGVuZCAyMA0KeA0KYGBgDQotPiBhcHBlbmRzIDIwIHRvIHRoZSBleGlzdGluZyB4IHZlY3Rvcg0KDQoNCmBgYHtyfQ0KeCA8LSBjKHhbMTozXSwyMCx4WzQ6Nl0pICMgaW5zZXJ0IDIwDQp4DQpgYGANCi0+IGluc2VydHMgMjAgYmV0d2VlbiB0aGUgM3JkIGFuZCA0dGggZWxlbW50IG9mIHgNCg0KDQpgYGB7cn0NCnggPC0geFstMjotNF0gIyBkZWxldGUgZWxlbWVudHMgMiB0aHJvdWdoIDQNCngNCmBgYA0KLT4gZGVsZXRlcyBlbGVtZW50cyAyIHRocm91Z2ggNA0KDQoNCkFuYWxvZ291cyBvcGVyYXRpb25zIGNhbiBiZSB1c2VkIHRvIGNoYW5nZSB0aGUgc2l6ZSBvZiBhIG1hdHJpeC4gRm9yIGluc3RhbmNlLCB0aGUgcmJpbmQoKSAocm93IGJpbmQpIGFuZCBjYmluZCgpIChjb2x1bW4gYmluZCkgZnVuY3Rpb25zIGxldCB5b3UgYWRkIHJvd3Mgb3IgY29sdW1ucyB0byBhIG1hdHJpeC4NCg0KDQoNCmBgYHtyfQ0Kb25lPC1jKDEsMSwxLDEpDQpvbmUNCmBgYA0KDQpgYGB7cn0NCnoNCmBgYA0KDQpgYGB7cn0NCmNiaW5kKG9uZSx6KQ0KYGBgDQoNCkhlcmUsIGNiaW5kKCkgY3JlYXRlcyBhIG5ldyBtYXRyaXggYnkgY29tYmluaW5nIGEgY29sdW1uIG9mIDFzIHdpdGggdGhlIGNvbHVtbnMgb2Ygei4gV2UgY2hvb3NlIHRvIGdldCBhIHF1aWNrIHByaW50b3V0LCBidXQgd2UgY291bGQgaGF2ZSBhc3NpZ25lZCB0aGUgcmVzdWx0IHRvIHogKG9yIGFub3RoZXIgdmFyaWFibGUpLCBhcyBmb2xsb3dzOg0KDQoNCmBgYHtyfQ0KY2JpbmQoeixvbmUpDQpgYGANCi0+IGJpbmRzIG9uZSB0byB0aGUgZW5kIG9mIHoNCg0KYGBge3J9DQp6IDwtIGNiaW5kKG9uZSx6KQ0KYGBgDQotPiBiaW5kcyB6IHRvIGVuZCBvZiBvbmUgYW5kIGFzc2lnbnMgbmV3IG1hdHJpeCB0byB6DQoNCk5vdGUsIHRvbywgdGhhdCB3ZSBjb3VsZCBoYXZlIHJlbGllZCBvbiByZWN5Y2xpbmc6DQoNCmBgYHtyfQ0KY2JpbmQoMSx6KQ0KYGBgDQotPiBhZGRzIGNvbHVtbiBvZiBvbmVzIHRvIGJlZ2lubmluZyBvZiB6DQoNCg0KWW91IGNhbiBhbHNvIHVzZSB0aGUgcmJpbmQoKSBhbmQgY2JpbmQoKSBmdW5jdGlvbnMgYXMgYSBxdWljayB3YXkgdG8gY3JlYXRlIHNtYWxsIG1hdHJpY2VzLiBIZXJl4oCZcyBhbiBleGFtcGxlOg0KDQogDQpgYGB7cn0NCnEgPC0gY2JpbmQoYygxLDIpLGMoMyw0KSkNCnENCmBgYA0KLT4gY3JlYXRlcyBuZXcgbWF0cml4IHdpdGggY2JpbmQgZnVuY3Rpb24NCg0KDQpZb3UgY2FuIGRlbGV0ZSByb3dzIG9yIGNvbHVtbnMgYnkgcmVhc3NpZ25tZW50LCB0b286DQoNCg0KYGBge3J9DQptIDwtIG1hdHJpeCgxOjYsbnJvdz0zKQ0KbQ0KYGBgDQotPiByZWFzc2lnbnMgbWF0cml4IHRvIG0gYW5kLCB0aGVyZWZvcmUsIGRlbGV0ZXMgb2xkLCB1bnVzZWQgdmFsdWVzDQoNCg0KYGBge3J9DQp6IDwtIHpbYygxLDMpLF0NCnoNCmBgYA0KLT4gcmV0dXJucyBmaXJzdCBhbmQgdGhyaWQgcm93IG9mIHoNCg0K