Working directory

Before starting, you have to create a directory where you put all the files of the tutorial. The command

getwd()

indicates the directory where R works. The command setwd allows to change this directory. You can also use the menu Session -> Set Working directory -> Choose directory…

Creating objects

Numeric

An object can be created by being assigned to one of the three operators <-, ->, = and by naming

b<-41.3  # set up object b consisting of one number: 41.3 
x<-b     # b is assigned to x
x=b      # b is assigned to x
b->x     # b is assigned to x
is.numeric(b)
mode(b)

Character

x <- "La mort"
y <- "aux trousses"
paste(x,y)
is.character(x)

Logical (Boolean)

x <- TRUE
is.logical(x)
mode(x)
a <- 1
a==1
a!=1
a<0
a>0

Vector

There are different ways to define a vector:

  • collect function c
x <- c(1.2,5,9,11)
x
  • sequence operator :
1:5
  • sequence function seq
seq(1,10,by=2)
seq(0,1,length=0.05)
  • The rep function
rep(1,4)
rep(c(1,3),each=3)

We can also create character or logical vectors

x <- c("A","B","C")
x <- rep("A",5)
paste("X",1:5,sep="-")
substr("statistician",5,9)

Selecting part of a vector

Selections are made using the selection operator [ ]

x <- c(-4,-3,1,3,5,8,0)
x[2]
x[c(2,5)]
x>0
x[x>0]

Operations

Explain the following commands

x <- seq(-10,10,by=2)
y <- 1:length(x)
x+y
x*y
z <- x>0
x*z

Factors

Factors are particular vectors very useful when we deal with categorical variables.

V1 <- factor(c("less20years","more50years","less20years","more50years","less20years"))
V1
levels(V1)
levels(V1) <- c("Young","Old")
V1

Exercise 1

  1. Compute the mean, the sum, the mean, the median and the variance of the vector (1,3,8,9,11)

  2. Create the following vectors using the rep function:

vec1 = 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5

vec2 = 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5

vec3 = 1 1 2 2 2 3 3 3 3 4 4 4 4 4

  1. Create the following vector using the paste function:

vec4 = “A0)” “A1)” “A2)” “A3)” “A4)” “A5)” “A6)” “A7)” “A8)” “A9)” “A10)”

  1. letters is a vector containing the 26 letters of the alphabet. Find the index of the letter \(q\) and create the vector containing “a1”,“b2”,\(\dots\) until \(q\) with the index of \(q\).

Matrix

The matrix function allows the creation of matrices

m <- matrix(1:4,ncol=2)
m
m <- matrix(1:4,nrow=2)
m
m <- matrix(1:4,nrow=2,byrow=TRUE)
dim(m)

The position of an element within a matrix is indicated by its row and column number. Thus, to select the term in the second row and the first column, we execute

m[2,1]

We can also extract rows or columns of matrices:

m[1,] #first row
m[,2] #second column

It is easy to make classical operations on matrices

det(m) #determinant
solve(m) #inverse
t(m) #transpose
n <- matrix(5:8,nrow=2)
m+n
m*n #be carefull: Hadamart product
m%*%n #matrix product
solve(m) #eigen decomposition

Lists

A list is a heterogeneous object. It is a set of ranked objects which do not always have the same mode or length. The objects are referred to as components of the list. For instance, we can put a vector and a matrix in a list with

mylist <- list(vector=rep(1:5),mat=matrix(1:8,nrow=2))
mylist
length(mylist)

To extract a component from the list, we can simply indicate the position of the element that we want to extract. [[ ]] are used to identify the element in the list:

mylist[[1]]

We can also use the name of the element, if it has one, which can be written in two ways:

mylist$mat
mylist[["mat"]]

Data frame

Data frames are special lists with components of the same length but with potentially different modes. The data tables generally used in statistics are often referred to as data frame. Indeed, a data table is made up of quantitative and/or qualitative variables taken from the same individuals.

name <- c("Paul","Mary","Steven","Charlotte","Peter")
sex <- factor(c("M","F","M","F","M"))
size <- c(180,165,168,170,175)
data <- data.frame(name,sex,size)
summary(data)

Observe that name is character vector, sex a factor and size a numeric vector.

Extraction is similar to matrix and list

data[2,3]
data[,2]
data$sex

Some basic functions

summary(data)
summary(1:10)
x <- c(1,8,5,4)
sort(x)
order(x)
V1 <- 1:10
V2 <- seq(-20,25,length=10)
df <- data.frame(V1,V2)
apply(df,1,mean)
apply(df,2,sum)

Exercise 2

  1. Create the following matrix mat (with the column and row names):
column 1 column 2 column 3 column 4
row-1 1 5 5 0
row-2 0 5 6 1
row-3 3 0 3 3
row-4 4 4 4 2
  1. Create a vector containing the diagonal elements of the matrix mat.

  2. Create a matrix containing the first 2 rows of mat.

  3. Create a matrix containing the last 2 columns of mat.

  4. Calculate the determinant and then invert the matrix using the appropriate functions.

Exercise 3

  1. From the iris dataset available in R (use data(iris) to load it and then head(iris) to visualise the first rows), create a sub-dataset comprising only the data for the category versicolor of the variable species (call this new dataset iris2).

  2. Sort the data in iris2 in descending order according to the variable Sepal.Length (you can use the order function).

Exercise 4

  1. Calculate the benchmark statistics (mean, min, max, etc.) for the three variables of the ethanol dataset (available in the lattice package).

  2. Calculate the quartiles for each of the three variables. To do this, use the apply function with the quantile function.

  3. Again with the apply function, calculate all the deciles for each of the three variables using the argument probs of the quantile function.

LS0tCnRpdGxlOiAiUiBPYmplY3RzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIyBXb3JraW5nIGRpcmVjdG9yeQoKQmVmb3JlIHN0YXJ0aW5nLCB5b3UgaGF2ZSB0byBjcmVhdGUgYSBkaXJlY3Rvcnkgd2hlcmUgeW91IHB1dCBhbGwgdGhlIGZpbGVzIG9mIHRoZSB0dXRvcmlhbC4gVGhlIGNvbW1hbmQKCmBgYHtyfQpnZXR3ZCgpCmBgYAppbmRpY2F0ZXMgdGhlIGRpcmVjdG9yeSB3aGVyZSAqKlIqKiB3b3Jrcy4gVGhlIGNvbW1hbmQgKipzZXR3ZCoqIGFsbG93cyB0byBjaGFuZ2UgdGhpcyBkaXJlY3RvcnkuIFlvdSBjYW4gYWxzbyB1c2UgdGhlIG1lbnUgKipTZXNzaW9uIC0+IFNldCBXb3JraW5nIGRpcmVjdG9yeSAtPiBDaG9vc2UgZGlyZWN0b3J5Li4uKioKCiMjIENyZWF0aW5nIG9iamVjdHMKCiMjIyBOdW1lcmljCkFuIG9iamVjdCBjYW4gYmUgY3JlYXRlZCBieSBiZWluZyBhc3NpZ25lZCB0byBvbmUgb2YgdGhlIHRocmVlIG9wZXJhdG9ycyAqKjwtKiosICoqLT4qKiwgKio9KiogYW5kIGJ5IG5hbWluZyAKCmBgYHtyfQpiPC00MS4zICAjIHNldCB1cCBvYmplY3QgYiBjb25zaXN0aW5nIG9mIG9uZSBudW1iZXI6IDQxLjMgCng8LWIgICAgICMgYiBpcyBhc3NpZ25lZCB0byB4Cng9YiAgICAgICMgYiBpcyBhc3NpZ25lZCB0byB4CmItPnggICAgICMgYiBpcyBhc3NpZ25lZCB0byB4CmlzLm51bWVyaWMoYikKbW9kZShiKQpgYGAKCiMjIyBDaGFyYWN0ZXIKCmBgYHtyfQp4IDwtICJMYSBtb3J0Igp5IDwtICJhdXggdHJvdXNzZXMiCnBhc3RlKHgseSkKaXMuY2hhcmFjdGVyKHgpCmBgYAoKIyMjIExvZ2ljYWwgKEJvb2xlYW4pCgpgYGB7cn0KeCA8LSBUUlVFCmlzLmxvZ2ljYWwoeCkKbW9kZSh4KQphIDwtIDEKYT09MQphIT0xCmE8MAphPjAKYGBgCgojIyMgVmVjdG9yCgpUaGVyZSBhcmUgZGlmZmVyZW50IHdheXMgdG8gZGVmaW5lIGEgdmVjdG9yOgoKKiBjb2xsZWN0IGZ1bmN0aW9uICoqYyoqCmBgYHtyfQp4IDwtIGMoMS4yLDUsOSwxMSkKeApgYGAKCiogc2VxdWVuY2Ugb3BlcmF0b3IgKio6KioKCmBgYHtyfQoxOjUKYGBgCgoqICBzZXF1ZW5jZSBmdW5jdGlvbiAqKnNlcSoqCgpgYGB7cn0Kc2VxKDEsMTAsYnk9MikKc2VxKDAsMSxsZW5ndGg9MC4wNSkKYGBgCgoqIFRoZSAqcmVwKiBmdW5jdGlvbgoKYGBge3J9CnJlcCgxLDQpCnJlcChjKDEsMyksZWFjaD0zKQpgYGAKCldlIGNhbiBhbHNvIGNyZWF0ZSAqY2hhcmFjdGVyKiBvciAqbG9naWNhbCogdmVjdG9ycwoKYGBge3J9CnggPC0gYygiQSIsIkIiLCJDIikKeCA8LSByZXAoIkEiLDUpCnBhc3RlKCJYIiwxOjUsc2VwPSItIikKc3Vic3RyKCJzdGF0aXN0aWNpYW4iLDUsOSkKYGBgCgoKIyMjIFNlbGVjdGluZyBwYXJ0IG9mIGEgdmVjdG9yCgpTZWxlY3Rpb25zIGFyZSBtYWRlIHVzaW5nIHRoZSBzZWxlY3Rpb24gb3BlcmF0b3IgKipbIF0qKgoKYGBge3J9CnggPC0gYygtNCwtMywxLDMsNSw4LDApCnhbMl0KeFtjKDIsNSldCng+MAp4W3g+MF0KYGBgCgoKIyMjIE9wZXJhdGlvbnMKCkV4cGxhaW4gdGhlIGZvbGxvd2luZyBjb21tYW5kcwpgYGB7cn0KeCA8LSBzZXEoLTEwLDEwLGJ5PTIpCnkgPC0gMTpsZW5ndGgoeCkKeCt5CngqeQp6IDwtIHg+MAp4KnoKYGBgCgojIyBGYWN0b3JzCgpGYWN0b3JzIGFyZSBwYXJ0aWN1bGFyIHZlY3RvcnMgdmVyeSB1c2VmdWwgd2hlbiB3ZSBkZWFsIHdpdGggY2F0ZWdvcmljYWwgdmFyaWFibGVzLgoKYGBge3J9ClYxIDwtIGZhY3RvcihjKCJsZXNzMjB5ZWFycyIsIm1vcmU1MHllYXJzIiwibGVzczIweWVhcnMiLCJtb3JlNTB5ZWFycyIsImxlc3MyMHllYXJzIikpClYxCmxldmVscyhWMSkKbGV2ZWxzKFYxKSA8LSBjKCJZb3VuZyIsIk9sZCIpClYxCmBgYAoKCiMjIyBFeGVyY2lzZSAxCgoxLiBDb21wdXRlIHRoZSBtZWFuLCB0aGUgc3VtLCB0aGUgbWVhbiwgdGhlIG1lZGlhbiBhbmQgdGhlIHZhcmlhbmNlIG9mIHRoZSB2ZWN0b3IgKDEsMyw4LDksMTEpCgoKCjIuIENyZWF0ZSB0aGUgZm9sbG93aW5nIHZlY3RvcnMgdXNpbmcgdGhlICoqcmVwKiogZnVuY3Rpb246Cgp2ZWMxID0gMSAyIDMgNCA1IDEgMiAzIDQgNSAxIDIgMyA0IDUgCgp2ZWMyID0gMSAxIDEgMiAyIDIgMyAzIDMgNCA0IDQgNSA1IDUKCnZlYzMgPSAxIDEgMiAyIDIgMyAzIDMgMyA0IDQgNCA0IDQKCgoKMy4gQ3JlYXRlIHRoZSBmb2xsb3dpbmcgdmVjdG9yIHVzaW5nIHRoZSAqKnBhc3RlKiogZnVuY3Rpb246Cgp2ZWM0ID0gIkEwKSIgIkExKSIgIkEyKSIgIkEzKSIgIkE0KSIgIkE1KSIgIkE2KSIgIkE3KSIgIkE4KSIgIkE5KSIgIkExMCkiCgoKCgo0LiAqKmxldHRlcnMqKiBpcyBhIHZlY3RvciBjb250YWluaW5nIHRoZSAyNiBsZXR0ZXJzIG9mIHRoZSBhbHBoYWJldC4gRmluZCB0aGUgaW5kZXggb2YgdGhlIGxldHRlciAkcSQgYW5kIGNyZWF0ZSB0aGUgdmVjdG9yIGNvbnRhaW5pbmcgImExIiwiYjIiLCRcZG90cyQgdW50aWwgJHEkIHdpdGggdGhlIGluZGV4IG9mICRxJC4KCgoKCgojIyBNYXRyaXgKClRoZSAqKm1hdHJpeCoqIGZ1bmN0aW9uIGFsbG93cyB0aGUgY3JlYXRpb24gb2YgbWF0cmljZXMKYGBge3J9Cm0gPC0gbWF0cml4KDE6NCxuY29sPTIpCm0KbSA8LSBtYXRyaXgoMTo0LG5yb3c9MikKbQptIDwtIG1hdHJpeCgxOjQsbnJvdz0yLGJ5cm93PVRSVUUpCmRpbShtKQpgYGAKClRoZSBwb3NpdGlvbiBvZiBhbiBlbGVtZW50IHdpdGhpbiBhIG1hdHJpeCBpcyBpbmRpY2F0ZWQgYnkgaXRzIHJvdyBhbmQgY29sdW1uIG51bWJlci4gVGh1cywgdG8gc2VsZWN0IHRoZSB0ZXJtIGluIHRoZSBzZWNvbmQgcm93IGFuZCB0aGUgZmlyc3QgY29sdW1uLCB3ZSBleGVjdXRlCmBgYHtyfQptWzIsMV0KYGBgCgpXZSBjYW4gYWxzbyBleHRyYWN0IHJvd3Mgb3IgY29sdW1ucyBvZiBtYXRyaWNlczoKYGBge3J9Cm1bMSxdICNmaXJzdCByb3cKbVssMl0gI3NlY29uZCBjb2x1bW4KYGBgCgpJdCBpcyBlYXN5IHRvIG1ha2UgY2xhc3NpY2FsIG9wZXJhdGlvbnMgb24gbWF0cmljZXMKCmBgYHtyfQpkZXQobSkgI2RldGVybWluYW50CnNvbHZlKG0pICNpbnZlcnNlCnQobSkgI3RyYW5zcG9zZQpuIDwtIG1hdHJpeCg1OjgsbnJvdz0yKQptK24KbSpuICNiZSBjYXJlZnVsbDogSGFkYW1hcnQgcHJvZHVjdAptJSolbiAjbWF0cml4IHByb2R1Y3QKc29sdmUobSkgI2VpZ2VuIGRlY29tcG9zaXRpb24KYGBgCgojIyBMaXN0cwoKQSBsaXN0IGlzIGEgaGV0ZXJvZ2VuZW91cyBvYmplY3QuICBJdCBpcyBhIHNldCBvZiByYW5rZWQgb2JqZWN0cyB3aGljaCBkbyBub3QgYWx3YXlzIGhhdmUgdGhlIHNhbWUgbW9kZSBvciBsZW5ndGguIFRoZSBvYmplY3RzIGFyZSByZWZlcnJlZCB0byBhcyBjb21wb25lbnRzIG9mIHRoZSBsaXN0LiBGb3IgaW5zdGFuY2UsIHdlIGNhbiBwdXQgYSB2ZWN0b3IgYW5kIGEgbWF0cml4IGluIGEgbGlzdCB3aXRoCgpgYGB7cn0KbXlsaXN0IDwtIGxpc3QodmVjdG9yPXJlcCgxOjUpLG1hdD1tYXRyaXgoMTo4LG5yb3c9MikpCm15bGlzdApsZW5ndGgobXlsaXN0KQpgYGAKVG8gZXh0cmFjdCBhIGNvbXBvbmVudCBmcm9tIHRoZSBsaXN0LCB3ZSBjYW4gc2ltcGx5IGluZGljYXRlIHRoZSBwb3NpdGlvbiBvZiB0aGUgZWxlbWVudCB0aGF0IHdlIHdhbnQgdG8gZXh0cmFjdC4gKipbWyAgXV0qKiBhcmUgdXNlZCB0byBpZGVudGlmeSB0aGUgZWxlbWVudCBpbiB0aGUgbGlzdDoKCmBgYHtyfQpteWxpc3RbWzFdXQpgYGAKCldlIGNhbiBhbHNvIHVzZSB0aGUgbmFtZSBvZiB0aGUgZWxlbWVudCwgaWYgaXQgaGFzIG9uZSwgd2hpY2ggY2FuIGJlIHdyaXR0ZW4gaW4gdHdvIHdheXM6CmBgYHtyfQpteWxpc3QkbWF0Cm15bGlzdFtbIm1hdCJdXQpgYGAKCgojIyBEYXRhIGZyYW1lCgpEYXRhIGZyYW1lcyBhcmUgc3BlY2lhbCBsaXN0cyB3aXRoIGNvbXBvbmVudHMgb2YgdGhlIHNhbWUgbGVuZ3RoIGJ1dCB3aXRoIHBvdGVudGlhbGx5IGRpZmZlcmVudCBtb2Rlcy4gVGhlIGRhdGEgdGFibGVzIGdlbmVyYWxseSB1c2VkIGluIHN0YXRpc3RpY3MgYXJlIG9mdGVuIHJlZmVycmVkIHRvIGFzIGRhdGEgZnJhbWUuIEluZGVlZCwgYSBkYXRhIHRhYmxlIGlzIG1hZGUgdXAgb2YgcXVhbnRpdGF0aXZlIGFuZC9vciBxdWFsaXRhdGl2ZSB2YXJpYWJsZXMgdGFrZW4gZnJvbSB0aGUgc2FtZSBpbmRpdmlkdWFscy4KCmBgYHtyfQpuYW1lIDwtIGMoIlBhdWwiLCJNYXJ5IiwiU3RldmVuIiwiQ2hhcmxvdHRlIiwiUGV0ZXIiKQpzZXggPC0gZmFjdG9yKGMoIk0iLCJGIiwiTSIsIkYiLCJNIikpCnNpemUgPC0gYygxODAsMTY1LDE2OCwxNzAsMTc1KQpkYXRhIDwtIGRhdGEuZnJhbWUobmFtZSxzZXgsc2l6ZSkKc3VtbWFyeShkYXRhKQpgYGAKCk9ic2VydmUgdGhhdCAqbmFtZSogaXMgY2hhcmFjdGVyIHZlY3RvciwgKnNleCogYSBmYWN0b3IgYW5kICpzaXplKiBhIG51bWVyaWMgdmVjdG9yLgoKRXh0cmFjdGlvbiBpcyBzaW1pbGFyIHRvIG1hdHJpeCBhbmQgbGlzdAoKYGBge3J9CmRhdGFbMiwzXQpkYXRhWywyXQpkYXRhJHNleApgYGAKCgojIyBTb21lIGJhc2ljIGZ1bmN0aW9ucwoKKiAqKnN1bW1hcnkqKiBwcm9kdWNlcyByZXN1bHQgc3VtbWFyaWVzIG9mIGFuIG9iamVjdAoKYGBge3J9CnN1bW1hcnkoZGF0YSkKc3VtbWFyeSgxOjEwKQpgYGAKCiogbWVhbiwgc3VtLCBtZWRpYW4sIHZhciwgbWluLCBtYXguLi4gKGVhc3kgdG8gdW5kZXJzdGFuZCkKCiogKnNvcnQqLCAqb3JkZXIqCgpgYGB7cn0KeCA8LSBjKDEsOCw1LDQpCnNvcnQoeCkKb3JkZXIoeCkKYGBgCgoqICoqYXBwbHkqKiBhcHBseSBhIGZ1bmN0aW9uICoqZioqIHRvIHRoZSByb3dzIG9yIGNvbHVtbnMgb2YgYSBtYXRyaXggb3IgYSBkYXRhLWZyYW1lCgpgYGB7cn0KVjEgPC0gMToxMApWMiA8LSBzZXEoLTIwLDI1LGxlbmd0aD0xMCkKZGYgPC0gZGF0YS5mcmFtZShWMSxWMikKYXBwbHkoZGYsMSxtZWFuKQphcHBseShkZiwyLHN1bSkKYGBgCgojIyMgRXhlcmNpc2UgMgoKMS4gQ3JlYXRlIHRoZSBmb2xsb3dpbmcgbWF0cml4ICptYXQqICh3aXRoIHRoZSBjb2x1bW4gYW5kIHJvdyBuYW1lcyk6Cgp8ICAgICAgfGNvbHVtbiAxIHwgY29sdW1uIDIgfGNvbHVtbiAzIHwgY29sdW1uIDQgfAp8Oi0tLS06fDotLS0tLS0tOnw6LS0tLS0tLS06fDotLS0tLS0tOnw6LS0tLS0tLS06fAp8cm93LTEgfCAgICAxICAgIHwgICAgIDUgICAgfCAgICA1ICAgIHwgICAgMCAgICAgfAp8cm93LTIgfCAgICAwICAgIHwgICAgIDUgICAgfCAgICA2ICAgIHwgICAgMSAgICAgfAp8cm93LTMgfCAgICAzICAgIHwgICAgIDAgICAgfCAgICAzICAgIHwgICAgMyAgICAgfAp8cm93LTQgfCAgICA0ICAgIHwgICAgIDQgICAgfCAgICA0ICAgIHwgICAgMiAgICAgfAoKCgoyLiBDcmVhdGUgYSB2ZWN0b3IgY29udGFpbmluZyB0aGUgZGlhZ29uYWwgZWxlbWVudHMgb2YgdGhlIG1hdHJpeCAqKm1hdCoqLgoKCjMuIENyZWF0ZSBhIG1hdHJpeCBjb250YWluaW5nIHRoZSBmaXJzdCAyIHJvd3Mgb2YgKiptYXQqKi4KCgo0LiBDcmVhdGUgYSBtYXRyaXggY29udGFpbmluZyB0aGUgbGFzdCAyIGNvbHVtbnMgb2YgKiptYXQqKi4KCgo1LiBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50IGFuZCB0aGVuIGludmVydCB0aGUgbWF0cml4IHVzaW5nIHRoZSBhcHByb3ByaWF0ZSBmdW5jdGlvbnMuCgoKIyMjIEV4ZXJjaXNlIDMKCjEuIEZyb20gdGhlICoqaXJpcyoqIGRhdGFzZXQgYXZhaWxhYmxlIGluICoqUioqICh1c2UgKipkYXRhKGlyaXMpKiogdG8gbG9hZCBpdCBhbmQgdGhlbiAqKmhlYWQoaXJpcykqKiB0byB2aXN1YWxpc2UgdGhlIGZpcnN0IHJvd3MpLApjcmVhdGUgYSBzdWItZGF0YXNldCBjb21wcmlzaW5nIG9ubHkgdGhlIGRhdGEgZm9yIHRoZSBjYXRlZ29yeSAqdmVyc2ljb2xvciogb2YgdGhlIHZhcmlhYmxlICpzcGVjaWVzKiAoY2FsbCB0aGlzIG5ldyBkYXRhc2V0ICoqaXJpczIqKikuCgoKCjIuIFNvcnQgdGhlIGRhdGEgaW4gKippcmlzMioqIGluIGRlc2NlbmRpbmcgb3JkZXIgYWNjb3JkaW5nIHRvIHRoZSB2YXJpYWJsZSAqKlNlcGFsLkxlbmd0aCoqICh5b3UgY2FuIHVzZSB0aGUgKipvcmRlcioqIGZ1bmN0aW9uKS4KCgoKIyMjIEV4ZXJjaXNlIDQKCjEuIENhbGN1bGF0ZSB0aGUgYmVuY2htYXJrIHN0YXRpc3RpY3MgKG1lYW4sIG1pbiwgbWF4LCBldGMuKSBmb3IgdGhlIHRocmVlIHZhcmlhYmxlcyBvZiB0aGUgKipldGhhbm9sKiogZGF0YXNldCAoYXZhaWxhYmxlIGluIHRoZSAqbGF0dGljZSogcGFja2FnZSkuIAoKCgoyLiBDYWxjdWxhdGUgdGhlIHF1YXJ0aWxlcyBmb3IgZWFjaCBvZiB0aGUgdGhyZWUgdmFyaWFibGVzLiBUbyBkbyB0aGlzLCB1c2UgdGhlICoqYXBwbHkqKiBmdW5jdGlvbiB3aXRoIHRoZSAqKnF1YW50aWxlKiogZnVuY3Rpb24uCgoKCjMuIEFnYWluIHdpdGggdGhlICoqYXBwbHkqKiBmdW5jdGlvbiwgY2FsY3VsYXRlIGFsbCB0aGUgZGVjaWxlcyBmb3IgZWFjaCBvZiB0aGUgdGhyZWUgdmFyaWFibGVzIHVzaW5nIHRoZSBhcmd1bWVudCAqKnByb2JzKiogb2YgdGhlICoqcXVhbnRpbGUqKiBmdW5jdGlvbi4KCgoKCgoKCg==