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