1.5.4 Les vecteurs

x <- c(5.6,-2,78,42.3) # vecteur de numériques à 4 éléments
x
x <- c(x,3,c(12,8)) # vecteur à 7 éléments
x
x <- 2 # vecteur de longueur 1
x
1:6
seq(1,6,by=0.5)
seq(1,6,length=5)
rep(1,4)
rep(c(1,2),each=3)
A = rep(1,1000) # création d’un vecteur de 1
typeof(A)
[1] "double"
object.size(A)
8048 bytes
object.size(as.integer(A))
4048 bytes
typeof(as.integer(A)+1)
[1] "double"
object.size(as.integer(A)+1)
8048 bytes
typeof(as.integer(A)+1L)
[1] "integer"
object.size(as.integer(A)+1L)
4048 bytes
A = rep(1L,1000) # vecteur de 1 stocké en entiers
object.size(A)
4048 bytes
x <- c("A","BB","C1")
x
[1] "A"  "BB" "C1"
x <- rep('A',5)
x
[1] "A" "A" "A" "A" "A"
paste("X",1:5,sep="-")
[1] "X-1" "X-2" "X-3" "X-4" "X-5"
paste(c("X","Y"),1:5,"txt",sep=".")
[1] "X.1.txt" "Y.2.txt" "X.3.txt" "Y.4.txt" "X.5.txt"
paste(c("X","Y"),1:5,sep=".",collapse="+")
[1] "X.1+Y.2+X.3+Y.4+X.5"
substr("livre",2,5)
[1] "ivre"
txtvec <- c("arm","foot","lefroo", "bafoobar")
grep("foo", txtvec)
[1] 2 4
gsub("foo", txtvec, replacement = "DON")
[1] "arm"      "DONt"     "lefroo"   "baDONbar"
1>0
[1] TRUE
x>13
[1] TRUE TRUE TRUE TRUE TRUE
x <- c(-1,0,2)
test <- x>1
(1+x^2)*test
[1] 0 0 5
all(x>1)
[1] FALSE
any(x>1)
[1] TRUE
v <- 1:100
v[6] # donne le sixième élément de v
[1] 6
v[6:8] # donne les 6ème, 7ème et 8ème éléments de v
[1] 6 7 8
v[c(6,6,1:2)] # donne les 6ème, 6ème, 1er et 2ème éléments de v
[1] 6 6 1 2
v[10:1] # donne les 10ème, 9ème, ..., 1er éléments de v
 [1] 10  9  8  7  6  5  4  3  2  1
v[-(1:5)] # donne v sans ses 5 premiers éléments
 [1]   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34
[30]  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63
[59]  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92
[88]  93  94  95  96  97  98  99 100
v[-c(1,5)] # donne v sans le premier et le cinquième élément
 [1]   2   3   4   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
[30]  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60
[59]  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89
[88]  90  91  92  93  94  95  96  97  98  99 100
v <- 1:15
print(v)
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
v[(v<5)]
[1] 1 2 3 4
v[(v<5)&(v>=12)] # & signifie "et"
integer(0)
v[(v<5)|(v>=12)] # | signifie "ou"
[1]  1  2  3  4 12 13 14 15
T <- c(23, 28, 24, 32)
O3 <- c(80, 102, 87, 124)
O3[T>25]
[1] 102 124
x[is.na(x)] <- 0 # les éléments NA de x reçoivent la valeur 0
y[y<0]<- -y[y<0]
y <- abs(y)
which.min(x)
[1] 1
which(x==min(x))
[1] 1

1.5.5 Les matrices

m <- matrix(c(1,17,12,3,6,0),ncol=2)
m
     [,1] [,2]
[1,]    1    3
[2,]   17    6
[3,]   12    0
m <- matrix(1:8,nrow=2,byrow=TRUE)
m
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8
m <- matrix(1:4,nrow=3,ncol=3)
data length [4] is not a sub-multiple or multiple of the number of rows [3]
m
     [,1] [,2] [,3]
[1,]    1    4    3
[2,]    2    1    4
[3,]    3    2    1
un <- matrix(1,nrow=2,ncol=4)
un
     [,1] [,2] [,3] [,4]
[1,]    1    1    1    1
[2,]    1    1    1    1
x <- seq(1,10,by=2)
x
[1] 1 3 5 7 9
as.matrix(x)
     [,1]
[1,]    1
[2,]    3
[3,]    5
[4,]    7
[5,]    9
m[1,]
[1] 1 4 3
m[1,,drop=FALSE]
     [,1] [,2] [,3]
[1,]    1    4    3
m[,c(2,2,1)]
     [,1] [,2] [,3]
[1,]    4    4    1
[2,]    1    1    2
[3,]    2    2    3
m[-1,] # matrice m sans sa première ligne
     [,1] [,2] [,3]
[1,]    2    1    4
[2,]    3    2    1
m[1:2,-1] # 2 premières lignes de m privée de sa 1ère colonne
     [,1] [,2]
[1,]    4    3
[2,]    1    4
m <- matrix(1:8,ncol=4,byrow=TRUE)
m
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8
m[,m[1,]>2]
     [,1] [,2]
[1,]    3    4
[2,]    7    8
m[m>2]
[1] 5 6 3 7 4 8
m[m>2] <- NA
m
     [,1] [,2] [,3] [,4]
[1,]    1    2   NA   NA
[2,]   NA   NA   NA   NA
m <- matrix(1:4,ncol=2)
m
     [,1] [,2]
[1,]    1    3
[2,]    2    4
n <- matrix(3:6,ncol=2,byrow=T)
n
     [,1] [,2]
[1,]    3    4
[2,]    5    6
m+n
     [,1] [,2]
[1,]    4    7
[2,]    7   10
m*n # produit élément par élément
     [,1] [,2]
[1,]    3   12
[2,]   10   24
sin(m) # sinus élément par élément
          [,1]       [,2]
[1,] 0.8414710  0.1411200
[2,] 0.9092974 -0.7568025
exp(m) # exponentielle élément par élément
         [,1]     [,2]
[1,] 2.718282 20.08554
[2,] 7.389056 54.59815
m^4 # puissance quatrième élément par élément
     [,1] [,2]
[1,]    1   81
[2,]   16  256
A <- matrix(1:4,ncol=2)
B <- matrix(c(5,7,6,8),ncol=2)
D <- A%*%t(B)
D
     [,1] [,2]
[1,]   23   31
[2,]   34   46
eig <- eigen(D)
eig
eigen() decomposition
$`values`
[1] 68.9419802  0.0580198

$vectors
           [,1]       [,2]
[1,] -0.5593385 -0.8038173
[2,] -0.8289393  0.5948762
eig$vectors[,1]
[1] -0.5593385 -0.8289393
V <- c(1,2)
solve(D,V)
[1] -4  3
X <- matrix(1:6,ncol=3)
X
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
ncol(X)
[1] 3
nrow(X)
[1] 2
dim(X)
[1] 2 3
cbind(c(1,2),c(3,4))
     [,1] [,2]
[1,]    1    3
[2,]    2    4
apply(X,MARGIN=2,sum) # sommes par colonne
[1]  3  7 11
apply(X,1,mean) # moyennes par ligne
[1] 3 4

1.5.6 Les facteurs

sexe <- factor(c("M","M","F","M","F","M","M","M"))
sexe
[1] M M F M F M M M
Levels: F M
sexe <- factor(c(2,2,1,2,1,2,1),labels=c("femme","homme"))
sexe
[1] homme homme femme homme femme homme femme
Levels: femme homme
niveau <- ordered(c("débutant","débutant","champion","champion",
"moyen","moyen","moyen","champion"),
levels=c("débutant","moyen","champion"))
niveau
[1] débutant débutant champion champion moyen    moyen    moyen    champion
Levels: débutant < moyen < champion
salto <- c(1:5,5:1)
salto
 [1] 1 2 3 4 5 5 4 3 2 1
salto.f <- as.factor(salto)
salto.f
 [1] 1 2 3 4 5 5 4 3 2 1
Levels: 1 2 3 4 5
levels(salto.f)
[1] "1" "2" "3" "4" "5"
nlevels(salto.f)
[1] 5
table(salto.f)
salto.f
1 2 3 4 5 
2 2 2 2 2 
x <- factor(c(10,11,13))
as.numeric(x)
[1] 1 2 3
as.numeric(as.character(x))
[1] 10 11 13

1.5.7 Les listes

vecteur <- seq(2,10,by=3)
matrice <- matrix(1:8,ncol=2)
facteur <- factor(c("M","M","F","M","F","M","M","M"))
ordonne <- ordered(c("débutant","débutant","champion",
                     "champion","moyen","moyen","moyen","champion"),
                   levels=c("débutant","moyen","champion"))
maliste <- list(vecteur,matrice,facteur,ordonne)
length(maliste)
[1] 4
mode(maliste)
[1] "list"
names(maliste)
NULL
names(maliste) <- c("vec","mat","sexe","ski")
names(maliste)
[1] "vec"  "mat"  "sexe" "ski" 
maliste[[3]]
[1] M M F M F M M M
Levels: F M
maliste[[1]]
[1] 2 5 8
maliste$sexe
[1] M M F M F M M M
Levels: F M
maliste[["sexe"]]
[1] M M F M F M M M
Levels: F M
maliste[c(1,3)]
$`vec`
[1] 2 5 8

$sexe
[1] M M F M F M M M
Levels: F M
X <- matrix(1:12,nrow=4,ncol=3)
nomligne <- c("ligne1","ligne2","ligne3","ligne4")
nomcol <- c("col1","col2","col3")
dimnames(X) <- list(nomligne,nomcol)
X
       col1 col2 col3
ligne1    1    5    9
ligne2    2    6   10
ligne3    3    7   11
ligne4    4    8   12
X[c("ligne4","ligne1"),c("col3","col2")]
       col3 col2
ligne4   12    8
ligne1    9    5
dimnames(X) <- list(NULL,dimnames(X)[[2]])
X
     col1 col2 col3
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12

1.5.8 Les data-frames

vec1 <- 1:5
vec2 <- c("a","b","c","c","b")
df <- data.frame(nom.var1 = vec1, nom.var2 = vec2)

1.5.9 La classe d’un objet

df <- data.frame(x = 1:2, y = c(3, 5))
print(df)
  x y
1 1 3
2 2 5
print.default(df)
$`x`
[1] 1 2

$y
[1] 3 5

attr(,"class")
[1] "data.frame"
library(data.table)
dt <- data.table::data.table(df)
dt
   x y
1: 1 3
2: 2 5
class(dt)
[1] "data.table" "data.frame"

1.6 Les fonctions

set.seed(13) # fixe la graine du générateur
rnorm(n=3)
[1]  0.5543269 -0.2802719  1.7751634
set.seed(13) # fixe la graine du générateur
rnorm(n=4,mean=5,sd=0.5)
[1] 5.277163 4.859864 5.887582 5.093660
args(rnorm)
function (n, mean = 0, sd = 1) 
NULL
args(plot)
function (x, y, ...) 
NULL

1.7 Les packages

set.seed(45) # fixe la graine du générateur aléatoire
require(MASS) # ou library(MASS)
mvrnorm(3,mu=c(0,1),Sigma=matrix(c(1,0.5,0.5,1),2,2))
           [,1]        [,2]
[1,]  0.6681649  0.92211747
[2,] -0.1600569 -0.05816423
[3,] -0.1612923  0.50391363
set.seed(45) # fixe la graine du générateur aléatoire
MASS::mvrnorm(3,mu=c(0,1),Sigma=matrix(c(1,0.5,0.5,1),2,2))
           [,1]        [,2]
[1,]  0.6681649  0.92211747
[2,] -0.1600569 -0.05816423
[3,] -0.1612923  0.50391363
if (!require(rpart)) install.packages("rpart") # installe rpart si besoin
require(rpart)
update.packages(ask=FALSE)
packs = as.data.frame(installed.packages(.libPaths()[1]), stringsAsFactors = F)
install.packages(packs$Package) ## réinstallation des packages
LS0tDQp0aXRsZTogIkNoYXBpdHJlIDEgOiBjb25jZXB0cyINCmF1dGhvcjogIkh1c3NvbiBldCBhbC4iDQpkYXRlOiAiMDkvMDkvMjAxOCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogMw0KICAgIHRvY19mbG9hdDogeWVzDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6ICczJw0KICAgIHRvY19mbG9hdDogeWVzDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGNhY2hlID0gVFJVRSkNCmBgYA0KDQojIDEuNS40IExlcyB2ZWN0ZXVycw0KDQpgYGB7cixldmFsPUZBTFNFfQ0KeCA8LSBjKDUuNiwtMiw3OCw0Mi4zKSAjIHZlY3RldXIgZGUgbnVtw6lyaXF1ZXMgw6AgNCDDqWzDqW1lbnRzDQp4DQp4IDwtIGMoeCwzLGMoMTIsOCkpICMgdmVjdGV1ciDDoCA3IMOpbMOpbWVudHMNCngNCnggPC0gMiAjIHZlY3RldXIgZGUgbG9uZ3VldXIgMQ0KeA0KMTo2DQpzZXEoMSw2LGJ5PTAuNSkNCnNlcSgxLDYsbGVuZ3RoPTUpDQpyZXAoMSw0KQ0KcmVwKGMoMSwyKSxlYWNoPTMpDQpgYGANCmBgYHtyfQ0KQSA9IHJlcCgxLDEwMDApICMgY3LDqWF0aW9uIGTigJl1biB2ZWN0ZXVyIGRlIDENCnR5cGVvZihBKQ0Kb2JqZWN0LnNpemUoQSkNCm9iamVjdC5zaXplKGFzLmludGVnZXIoQSkpDQpgYGANCg0KYGBge3J9DQp0eXBlb2YoYXMuaW50ZWdlcihBKSsxKQ0Kb2JqZWN0LnNpemUoYXMuaW50ZWdlcihBKSsxKQ0KdHlwZW9mKGFzLmludGVnZXIoQSkrMUwpDQpvYmplY3Quc2l6ZShhcy5pbnRlZ2VyKEEpKzFMKQ0KYGBgDQpgYGB7cn0NCkEgPSByZXAoMUwsMTAwMCkgIyB2ZWN0ZXVyIGRlIDEgc3RvY2vDqSBlbiBlbnRpZXJzDQpvYmplY3Quc2l6ZShBKQ0KYGBgDQoNCmBgYHtyfQ0KeCA8LSBjKCJBIiwiQkIiLCJDMSIpDQp4DQp4IDwtIHJlcCgnQScsNSkNCngNCmBgYA0KYGBge3J9DQpwYXN0ZSgiWCIsMTo1LHNlcD0iLSIpDQpwYXN0ZShjKCJYIiwiWSIpLDE6NSwidHh0IixzZXA9Ii4iKQ0KcGFzdGUoYygiWCIsIlkiKSwxOjUsc2VwPSIuIixjb2xsYXBzZT0iKyIpDQpgYGANCmBgYHtyfQ0Kc3Vic3RyKCJsaXZyZSIsMiw1KQ0KdHh0dmVjIDwtIGMoImFybSIsImZvb3QiLCJsZWZyb28iLCAiYmFmb29iYXIiKQ0KZ3JlcCgiZm9vIiwgdHh0dmVjKQ0KZ3N1YigiZm9vIiwgdHh0dmVjLCByZXBsYWNlbWVudCA9ICJET04iKQ0KDQpgYGANCg0KYGBge3J9DQoxPjANCng+MTMNCnggPC0gYygtMSwwLDIpDQp0ZXN0IDwtIHg+MQ0KKDEreF4yKSp0ZXN0DQphbGwoeD4xKQ0KYW55KHg+MSkNCmBgYA0KDQpgYGB7cn0NCnYgPC0gMToxMDANCnZbNl0gIyBkb25uZSBsZSBzaXhpw6htZSDDqWzDqW1lbnQgZGUgdg0Kdls2OjhdICMgZG9ubmUgbGVzIDbDqG1lLCA3w6htZSBldCA4w6htZSDDqWzDqW1lbnRzIGRlIHYNCnZbYyg2LDYsMToyKV0gIyBkb25uZSBsZXMgNsOobWUsIDbDqG1lLCAxZXIgZXQgMsOobWUgw6lsw6ltZW50cyBkZSB2DQp2WzEwOjFdICMgZG9ubmUgbGVzIDEww6htZSwgOcOobWUsIC4uLiwgMWVyIMOpbMOpbWVudHMgZGUgdg0KdlstKDE6NSldICMgZG9ubmUgdiBzYW5zIHNlcyA1IHByZW1pZXJzIMOpbMOpbWVudHMNCnZbLWMoMSw1KV0gIyBkb25uZSB2IHNhbnMgbGUgcHJlbWllciBldCBsZSBjaW5xdWnDqG1lIMOpbMOpbWVudA0KYGBgDQpgYGB7cn0NCnYgPC0gMToxNQ0KcHJpbnQodikNCnZbKHY8NSldDQp2Wyh2PDUpJih2Pj0xMildICMgJiBzaWduaWZpZSAiZXQiDQpgYGANCmBgYHtyfQ0Kdlsodjw1KXwodj49MTIpXSAjIHwgc2lnbmlmaWUgIm91Ig0KYGBgDQpgYGB7cn0NClQgPC0gYygyMywgMjgsIDI0LCAzMikNCk8zIDwtIGMoODAsIDEwMiwgODcsIDEyNCkNCk8zW1Q+MjVdDQpgYGANCg0KYGBge3IsIGV2YWw9RkFMU0V9DQp4W2lzLm5hKHgpXSA8LSAwICMgbGVzIMOpbMOpbWVudHMgTkEgZGUgeCByZcOnb2l2ZW50IGxhIHZhbGV1ciAwDQp5W3k8MF08LSAteVt5PDBdDQp5IDwtIGFicyh5KQ0KYGBgDQpgYGB7cn0NCndoaWNoLm1pbih4KQ0Kd2hpY2goeD09bWluKHgpKQ0KYGBgDQoNCiMgMS41LjUgTGVzIG1hdHJpY2VzDQoNCmBgYHtyfQ0KbSA8LSBtYXRyaXgoYygxLDE3LDEyLDMsNiwwKSxuY29sPTIpDQptDQptIDwtIG1hdHJpeCgxOjgsbnJvdz0yLGJ5cm93PVRSVUUpDQptDQptIDwtIG1hdHJpeCgxOjQsbnJvdz0zLG5jb2w9MykNCm0NCnVuIDwtIG1hdHJpeCgxLG5yb3c9MixuY29sPTQpDQp1bg0KYGBgDQpgYGB7cn0NCnggPC0gc2VxKDEsMTAsYnk9MikNCngNCmFzLm1hdHJpeCh4KQ0KYGBgDQoNCmBgYHtyfQ0KbVsxLF0NCm1bMSwsZHJvcD1GQUxTRV0NCm1bLGMoMiwyLDEpXQ0KbVstMSxdICMgbWF0cmljZSBtIHNhbnMgc2EgcHJlbWnDqHJlIGxpZ25lDQptWzE6MiwtMV0gIyAyIHByZW1pw6hyZXMgbGlnbmVzIGRlIG0gcHJpdsOpZSBkZSBzYSAxw6hyZSBjb2xvbm5lDQptIDwtIG1hdHJpeCgxOjgsbmNvbD00LGJ5cm93PVRSVUUpDQptDQptWyxtWzEsXT4yXQ0KbVttPjJdDQptW20+Ml0gPC0gTkENCm0NCm0gPC0gbWF0cml4KDE6NCxuY29sPTIpDQptDQpuIDwtIG1hdHJpeCgzOjYsbmNvbD0yLGJ5cm93PVQpDQpuDQptK24NCm0qbiAjIHByb2R1aXQgw6lsw6ltZW50IHBhciDDqWzDqW1lbnQNCnNpbihtKSAjIHNpbnVzIMOpbMOpbWVudCBwYXIgw6lsw6ltZW50DQpleHAobSkgIyBleHBvbmVudGllbGxlIMOpbMOpbWVudCBwYXIgw6lsw6ltZW50DQptXjQgIyBwdWlzc2FuY2UgcXVhdHJpw6htZSDDqWzDqW1lbnQgcGFyIMOpbMOpbWVudA0KYGBgDQoNCmBgYHtyfQ0KQSA8LSBtYXRyaXgoMTo0LG5jb2w9MikNCkIgPC0gbWF0cml4KGMoNSw3LDYsOCksbmNvbD0yKQ0KRCA8LSBBJSoldChCKQ0KRA0KZWlnIDwtIGVpZ2VuKEQpDQplaWcNCmVpZyR2ZWN0b3JzWywxXQ0KViA8LSBjKDEsMikNCnNvbHZlKEQsVikNCmBgYA0KYGBge3J9DQpYIDwtIG1hdHJpeCgxOjYsbmNvbD0zKQ0KWA0KbmNvbChYKQ0KbnJvdyhYKQ0KZGltKFgpDQpjYmluZChjKDEsMiksYygzLDQpKQ0KYXBwbHkoWCxNQVJHSU49MixzdW0pICMgc29tbWVzIHBhciBjb2xvbm5lDQphcHBseShYLDEsbWVhbikgIyBtb3llbm5lcyBwYXIgbGlnbmUNCmBgYA0KDQojIDEuNS42IExlcyBmYWN0ZXVycw0KDQpgYGB7cn0NCnNleGUgPC0gZmFjdG9yKGMoIk0iLCJNIiwiRiIsIk0iLCJGIiwiTSIsIk0iLCJNIikpDQpzZXhlDQpzZXhlIDwtIGZhY3RvcihjKDIsMiwxLDIsMSwyLDEpLGxhYmVscz1jKCJmZW1tZSIsImhvbW1lIikpDQpzZXhlDQpuaXZlYXUgPC0gb3JkZXJlZChjKCJkw6lidXRhbnQiLCJkw6lidXRhbnQiLCJjaGFtcGlvbiIsImNoYW1waW9uIiwNCiJtb3llbiIsIm1veWVuIiwibW95ZW4iLCJjaGFtcGlvbiIpLA0KbGV2ZWxzPWMoImTDqWJ1dGFudCIsIm1veWVuIiwiY2hhbXBpb24iKSkNCm5pdmVhdQ0Kc2FsdG8gPC0gYygxOjUsNToxKQ0Kc2FsdG8NCnNhbHRvLmYgPC0gYXMuZmFjdG9yKHNhbHRvKQ0Kc2FsdG8uZg0KbGV2ZWxzKHNhbHRvLmYpDQpubGV2ZWxzKHNhbHRvLmYpDQp0YWJsZShzYWx0by5mKQ0KeCA8LSBmYWN0b3IoYygxMCwxMSwxMykpDQphcy5udW1lcmljKHgpDQphcy5udW1lcmljKGFzLmNoYXJhY3Rlcih4KSkNCmBgYA0KDQojIDEuNS43IExlcyBsaXN0ZXMNCg0KYGBge3J9DQp2ZWN0ZXVyIDwtIHNlcSgyLDEwLGJ5PTMpDQptYXRyaWNlIDwtIG1hdHJpeCgxOjgsbmNvbD0yKQ0KZmFjdGV1ciA8LSBmYWN0b3IoYygiTSIsIk0iLCJGIiwiTSIsIkYiLCJNIiwiTSIsIk0iKSkNCm9yZG9ubmUgPC0gb3JkZXJlZChjKCJkw6lidXRhbnQiLCJkw6lidXRhbnQiLCJjaGFtcGlvbiIsDQogICAgICAgICAgICAgICAgICAgICAiY2hhbXBpb24iLCJtb3llbiIsIm1veWVuIiwibW95ZW4iLCJjaGFtcGlvbiIpLA0KICAgICAgICAgICAgICAgICAgIGxldmVscz1jKCJkw6lidXRhbnQiLCJtb3llbiIsImNoYW1waW9uIikpDQptYWxpc3RlIDwtIGxpc3QodmVjdGV1cixtYXRyaWNlLGZhY3RldXIsb3Jkb25uZSkNCmxlbmd0aChtYWxpc3RlKQ0KbW9kZShtYWxpc3RlKQ0KbmFtZXMobWFsaXN0ZSkNCm5hbWVzKG1hbGlzdGUpIDwtIGMoInZlYyIsIm1hdCIsInNleGUiLCJza2kiKQ0KbmFtZXMobWFsaXN0ZSkNCm1hbGlzdGVbWzNdXQ0KbWFsaXN0ZVtbMV1dDQptYWxpc3RlJHNleGUNCm1hbGlzdGVbWyJzZXhlIl1dDQptYWxpc3RlW2MoMSwzKV0NClggPC0gbWF0cml4KDE6MTIsbnJvdz00LG5jb2w9MykNCm5vbWxpZ25lIDwtIGMoImxpZ25lMSIsImxpZ25lMiIsImxpZ25lMyIsImxpZ25lNCIpDQpub21jb2wgPC0gYygiY29sMSIsImNvbDIiLCJjb2wzIikNCmRpbW5hbWVzKFgpIDwtIGxpc3Qobm9tbGlnbmUsbm9tY29sKQ0KWA0KWFtjKCJsaWduZTQiLCJsaWduZTEiKSxjKCJjb2wzIiwiY29sMiIpXQ0KZGltbmFtZXMoWCkgPC0gbGlzdChOVUxMLGRpbW5hbWVzKFgpW1syXV0pDQpYDQpgYGANCg0KIyAxLjUuOCBMZXMgZGF0YS1mcmFtZXMNCg0KYGBge3J9DQp2ZWMxIDwtIDE6NQ0KdmVjMiA8LSBjKCJhIiwiYiIsImMiLCJjIiwiYiIpDQpkZiA8LSBkYXRhLmZyYW1lKG5vbS52YXIxID0gdmVjMSwgbm9tLnZhcjIgPSB2ZWMyKQ0KYGBgDQoNCiMgMS41LjkgTGEgY2xhc3NlIGTigJl1biBvYmpldA0KDQpgYGB7cixtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0V9DQpkZiA8LSBkYXRhLmZyYW1lKHggPSAxOjIsIHkgPSBjKDMsIDUpKQ0KcHJpbnQoZGYpDQpwcmludC5kZWZhdWx0KGRmKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KZHQgPC0gZGF0YS50YWJsZTo6ZGF0YS50YWJsZShkZikNCmR0DQpjbGFzcyhkdCkNCmBgYA0KDQojIDEuNiBMZXMgZm9uY3Rpb25zDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTMpICMgZml4ZSBsYSBncmFpbmUgZHUgZ8OpbsOpcmF0ZXVyDQpybm9ybShuPTMpDQpzZXQuc2VlZCgxMykgIyBmaXhlIGxhIGdyYWluZSBkdSBnw6luw6lyYXRldXINCnJub3JtKG49NCxtZWFuPTUsc2Q9MC41KQ0KYXJncyhybm9ybSkNCmFyZ3MocGxvdCkNCmBgYA0KDQojIDEuNyBMZXMgcGFja2FnZXMNCg0KYGBge3IsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0Kc2V0LnNlZWQoNDUpICMgZml4ZSBsYSBncmFpbmUgZHUgZ8OpbsOpcmF0ZXVyIGFsw6lhdG9pcmUNCnJlcXVpcmUoTUFTUykgIyBvdSBsaWJyYXJ5KE1BU1MpDQptdnJub3JtKDMsbXU9YygwLDEpLFNpZ21hPW1hdHJpeChjKDEsMC41LDAuNSwxKSwyLDIpKQ0Kc2V0LnNlZWQoNDUpICMgZml4ZSBsYSBncmFpbmUgZHUgZ8OpbsOpcmF0ZXVyIGFsw6lhdG9pcmUNCk1BU1M6Om12cm5vcm0oMyxtdT1jKDAsMSksU2lnbWE9bWF0cml4KGMoMSwwLjUsMC41LDEpLDIsMikpDQpgYGANCg0KYGBge3IsIGV2YWw9RkFMU0UsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0KaWYgKCFyZXF1aXJlKHJwYXJ0KSkgaW5zdGFsbC5wYWNrYWdlcygicnBhcnQiKSAjIGluc3RhbGxlIHJwYXJ0IHNpIGJlc29pbg0KcmVxdWlyZShycGFydCkNCmBgYA0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCnVwZGF0ZS5wYWNrYWdlcyhhc2s9RkFMU0UpDQpwYWNrcyA9IGFzLmRhdGEuZnJhbWUoaW5zdGFsbGVkLnBhY2thZ2VzKC5saWJQYXRocygpWzFdKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQppbnN0YWxsLnBhY2thZ2VzKHBhY2tzJFBhY2thZ2UpICMjIHLDqWluc3RhbGxhdGlvbiBkZXMgcGFja2FnZXMNCmBgYA==