Globálne nastavenie Chunkov
V nižšie uvedenom Chunku je urobené základné globálne nastavenie
Chunkov v celom Notebooku.
- echo nastavuje, či chceme v Notebooku vypisovať
jednotlivé kódy R
- message je nastavený na FALSE, čo znamená,
že sa budú potláčať pracovné výstupy z R, t.j. napríklad výsledok
otvárania knižníc, a niektoré iné výstupy, ktoré ale pre celkový
Notebook nemajú takmer žiaden význam a sú vhodné skôr pri ladení
kódov.
- warning nastavený na FALSE potláča zobrazenie
chybových hlášok
Quitting from Cvicenie2a_scalars_text_logical_vectors_matrices.Rmd:26-32 [setup]
knitr::opts_chunk$set(
echo = TRUE,
message = FALSE,
warning = FALSE
)
Úvod k základným operáciám v R
Tento notebook demonštruje základné operácie v
jazyku R so:
- skalárnymi číslami (t.j. 1 číslo),
- textovými (znakovými) reťazcami,
- logickými (boolovskými) hodnotami a premennými,
- (numerickými) vektormi,
- maticami.
Tam, kde je to užitočné, sú zahrnuté malé cvičenia.
Numerické vektory
Generovanie vektorov
v1 <- c(3, 6, 9, 12)
v2 <- 3:15 # postupnost 1,2,3,4,5
v3 <- seq(from = 0, to = 16, by = 0.55) # postupnost s krokom 0.25
v4 <- rep(3, times = 4) # 3,3,3,3,3 # 5 clenna postupnost trojak
v5 <- runif(4) # generovanie rovnomerne rozdelenych premennych v intervale [0,1]
v6 <- rnorm(4) # generovanie normalne rozdelenych premennych
v1; v2; v3; v4; v5
[1] 3 6 9 12
[1] 3 4 5 6 7 8 9 10 11 12 13 14 15
[1] 0.00 0.55 1.10 1.65 2.20 2.75 3.30 3.85 4.40 4.95
[11] 5.50 6.05 6.60 7.15 7.70 8.25 8.80 9.35 9.90 10.45
[21] 11.00 11.55 12.10 12.65 13.20 13.75 14.30 14.85 15.40 15.95
[1] 3 3 3 3
[1] 0.2540458 0.6141199 0.4359565 0.2626499
Aritmetické operácie s vektormi
v <- c(10, 32, 44, 58)
v + 3 # kazdy prvok vektora zvacsime o 10
[1] 13 35 47 61
v * 9 # kazdy prvok vektora prenasobime 2
[1] 90 288 396 522
[1] 5.5 16.5 22.5 29.5
exp(v) # exponencialna funkcia z kazdeho prvku vektora
[1] 2.202647e+04 7.896296e+13 1.285160e+19 1.545539e+25
sum(c(8,9,10),c(2,3,3)) # skalarny sucin - vysledok je skalar
[1] 35
crossprod(c(4,6,8),c(10,12,14)) # skalarny sucin - vysledok je matica 1x1
[,1]
[1,] 224
c(11,22,333)*c(5,5,5) # Hadamardov sucin (sucin zodpovedajucich prvkov vektora)
[1] 55 110 1665
Matematické operácie s 2 vektormi rovnakého rozmeru
[1] 5
length(v5) #vektor v5 je definovany vyssie
[1] 4
c(6,8,3,10,1) + v5 # pozor, oba vektory musia mat rovnaky rozmer
[1] 6.254046 8.614120 3.435956 10.262650 1.254046
Indexovanie a výber niektorych prvkov vektora
x <- c(3, 8, 33, 1, 2, 18, 29)
x[3] # indexovanie - novy jedno-prvkovy vektor - prvy prvok vektora x
[1] 33
x[1:2] # novy vektor s druhym az stvrtym prvkom vektora x
[1] 3 8
x[-5] # novy vektor - vsetky prvky vektora x okrem prvého
[1] 3 8 33 1 18 29
x[x > 20] # novy vektor definovany prvkami x vacsimi ako 10
[1] 33 29
which(x > 20) # ktore prvky zodpovedaju podmienke vacsieho ako 10?
[1] 3 7
Práca s chýbajúcimi hodnotami
y <- c(1, NA, 3, NA, 5)
is.na(y)
[1] FALSE TRUE FALSE TRUE FALSE
[1] NA
mean(y, na.rm = TRUE) # remove NAs
[1] 3
Základné štatistiky a usporiadanie prvkov vektora podľa
veľkosti
a <- c(1, 6, 3, 9, 4)
mean(a) # priemerna hodnota
[1] 4.6
sd(a) # standardna odchylka
[1] 3.04959
max(a) # maximalna hodnota
[1] 9
summary(a) # rychly prehlad zakladnych statistik o vektore
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.0 3.0 4.0 4.6 6.0 9.0
sort(a) # rastuce usporiadanie
[1] 1 3 4 6 9
sort(a, decreasing = TRUE) # klesajuce
[1] 9 6 4 3 1
Malé cvičenie
Vytvorte vektor w s číslami 1..20 a vypočítajte sumu
všetkých párnych čísel.
k <- 1:18
sum(w[w %% 2 == 0])
[1] 110
Matice
Vytvorenie matíc
m <- matrix(1:12, nrow = 5, ncol = 3) # hodnoty sú zadavane po stlpcoch
m_byrow <- matrix(1:12, nrow = 5, byrow = TRUE) # hodnoty su zadavane po riadkoch
m; m_byrow
[,1] [,2] [,3]
[1,] 1 6 11
[2,] 2 7 12
[3,] 3 8 1
[4,] 4 9 2
[5,] 5 10 3
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
[4,] 10 11 12
[5,] 1 2 3
Rozmery matice
[1] 5 3
[,1] [,2] [,3]
[1,] 1 6 11
[2,] 2 7 12
[3,] 3 8 1
[4,] 4 9 2
[5,] 5 10 3
Adresovanie prvkov matice
m[2, 3] # riadok 1, stlpec 2
[1] 12
m[ , 2] # vsetky prvky v tretom stlpci - vysledok matica 3x1
[1] 6 7 8 9 10
m[3, ] # vsetky prvky v druhom riadku - vysledok matica 1*3
[1] 3 8 1
m[1:5, 1:2] # podmatica tvorena riadkami 1, 2 a stlpcami 2, 3
[,1] [,2]
[1,] 1 6
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
Maticové operácie
A <- matrix(c(6,2,1,5), nrow = 2)
B <- matrix(c(1,3,4,2), nrow = 2)
C <- matrix(c(2,3,5,2), nrow = 2)
A + B # scitanie matic
[,1] [,2]
[1,] 7 5
[2,] 5 7
A * B # Hadamard product - nasobenie po zodpovedajucich prvkoch
[,1] [,2]
[1,] 6 4
[2,] 6 10
A %*% B # nasobenie matic
[,1] [,2]
[1,] 9 26
[2,] 17 18
t(A) # transpozicia matice A - vymena riadkov a stlpcov
[,1] [,2]
[1,] 6 2
[2,] 1 5
det(A) # determinant matice
[1] 28
solve(A) # inverzia matice (ak je matica regularna - teda inverzia sa da spocitat)
[,1] [,2]
[1,] 0.17857143 -0.03571429
[2,] -0.07142857 0.21428571
Zlučovanie vektorov do matíc
C <- cbind(2:4, 1:3) # - po stlpcoch
D <- rbind(8:3, 5:7) # - po riadkoch
C; D
[,1] [,2]
[1,] 2 1
[2,] 3 2
[3,] 4 3
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 8 7 6 5 4 3
[2,] 5 6 7 5 6 7
Vypočítanie zvolenej štatistiky po riadkoch (stĺpcoch) matice
M <- matrix(2:4, nrow = 2)
M
[,1] [,2]
[1,] 2 4
[2,] 3 2
apply(M, 2, sum) # suma po riadkoch
[1] 5 6
apply(M, 2, mean) # priemery po stĺpcoch
[1] 2.5 3.0
Malé cvičenie
Vytvorte maticu 5x5 s hodnotami po riadkoch 1..25, vypočítajte
stĺpcové sumy a súčin matíc \(M^t
M\).
M2 <- matrix(1:15, nrow = 5, byrow = TRUE)
colSums(M2)
[1] 35 40 45
[,1] [,2] [,3]
[1,] 335 370 405
[2,] 370 410 450
[3,] 405 450 495
# 1) Moje dáta
water <- c(6, 8, 5, 9, 7, 4, 10) # Počet pohárov vody v dňoch 1..7
# 2) Malé úlohy
sum(water >= 8) # a) koľko dní >= 8 pohárov
[1] 3
mean(water) # b) priemer za týždeň
[1] 7
which.max(water) # c) ktorý deň bol najlepší (index dňa 1..7)
[1] 7
water[which.max(water)] # koľko pohárov to bolo
[1] 10
# 3) Graf (časová krivka)
plot(
water, type = "o",
main = "Poháre vody za 7 dní",
xlab = "Deň", ylab = "Počet pohárov",
ylim = c(0, max(water) + 1)
)
abline(h = 8, lty = 2) # vyznačený cieľ 8 pohárov

days <- c("Po","Ut","St","Št","Pi","So","Ne")
plot(1:7, water, type="o", xaxt="n", xlab="Deň", ylab="Poháre")
axis(1, at=1:7, labels=days); abline(h=8, lty=2)

LS0tCnRpdGxlOiAiWsOha2xhZG7DqSBvcGVyw6FjaWUgdiBSIgphdXRob3I6ICJCYXJib3JhIEtvcHJkb3ZhICA8YnI+CihzIHZ5dcW+aXTDrW0gQ2hhdEdQVCkiCmRhdGU6ICJPa3RvYmVyIDIwMjUiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0aGVtZTogdW5pdGVkCiAgICBoaWdobGlnaHQ6IHRhbmdvCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiA3MgotLS0KCiMgR2xvYsOhbG5lIG5hc3RhdmVuaWUgQ2h1bmtvdgoKViBuacW+xaFpZSB1dmVkZW5vbSBDaHVua3UgamUgdXJvYmVuw6kgesOha2xhZG7DqSBnbG9iw6FsbmUgbmFzdGF2ZW5pZSBDaHVua292IHYgY2Vsb20gTm90ZWJvb2t1LiAKCi0gKiplY2hvKiogbmFzdGF2dWplLCDEjWkgY2hjZW1lIHYgTm90ZWJvb2t1IHZ5cGlzb3ZhxaUgamVkbm90bGl2w6kga8OzZHkgUgotICoqbWVzc2FnZSoqIGplIG5hc3RhdmVuw70gbmEgKkZBTFNFKiwgxI1vIHpuYW1lbsOhLCDFvmUgc2EgYnVkw7ogcG90bMOhxI1hxaUgcHJhY292bsOpIHbDvXN0dXB5IHogUiwgdC5qLiBuYXByw61rbGFkIHbDvXNsZWRvayBvdHbDoXJhbmlhIGtuacW+bsOtYywgYSBuaWVrdG9yw6kgaW7DqSB2w71zdHVweSwga3RvcsOpIGFsZSBwcmUgY2Vsa292w70gTm90ZWJvb2sgbmVtYWrDuiB0YWttZXIgxb5pYWRlbiB2w716bmFtIGEgc8O6IHZob2Ruw6kgc2vDtHIgcHJpIGxhZGVuw60ga8OzZG92LgotICoqd2FybmluZyoqIG5hc3RhdmVuw70gbmEgRkFMU0UgcG90bMOhxI1hIHpvYnJhemVuaWUgY2h5Ym92w71jaCBobMOhxaFvawoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPVRSVUUsZWNobz1UUlVFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFRSVUUsCiAgbWVzc2FnZSA9IEZBTFNFLAogIHdhcm5pbmcgPSBGQUxTRQopCmBgYAoKIyDDmnZvZCBrIHrDoWtsYWRuw71tIG9wZXLDoWNpw6FtIHYgUgoKVGVudG8gbm90ZWJvb2sgZGVtb27FoXRydWplICoqesOha2xhZG7DqSBvcGVyw6FjaWUqKiB2IGphenlrdSBSIHNvOgoKLSBza2Fsw6FybnltaSDEjcOtc2xhbWkgKHQuai4gMSDEjcOtc2xvKSwKLSB0ZXh0b3bDvW1pICh6bmFrb3bDvW1pKSByZcWlYXpjYW1pLAotIGxvZ2lja8O9bWkgKGJvb2xvdnNrw71taSkgaG9kbm90YW1pIGEgcHJlbWVubsO9bWksCi0gKG51bWVyaWNrw71taSkgdmVrdG9ybWksCi0gbWF0aWNhbWkuCgpUYW0sIGtkZSBqZSB0byB1xb5pdG/EjW7DqSwgc8O6IHphaHJudXTDqSBtYWzDqSBjdmnEjWVuaWEuCgotLS0KCiMgU2thbMOhcmUgKGplZG5vxI3DrXNlbG7DqSBob2Rub3R5KQoKIyMgTnVtZXJpY2vDqSBza2Fsw6FyZQoKYGBge3J9CiMgUHJpcmFkZW5pZSBrb27FoXRhbnR5IGRvIHByZW1lbm5lagphIDwtIDkKYiA8LSAyLjMKCiMgQXJpdGhtZXRpYwpzdW1fYWIgICAgICA8LSBhICsgYiAgICAgICAgIyBzdWNldApkaWZmX2FiICAgICA8LSBhIC0gYiAgICAgICAgIyByb3pkaWVsCnByb2RfYWIgICAgIDwtIGEgKiBiICAgICAgICAjIG7DoXNvYmVuaWUKcXVvdF9hYiAgICAgPC0gYSAvIGIgICAgICAgICMgZGVsZW5pZQpwb3dlcl9hYiAgICA8LSBhIF4gYiAgICAgICAgIyB1bW9jxYhvdmFuaWUKbW9kX2FiICAgICAgPC0gYSAlJSA0ICAgICAgICMgemJ5dG9rIHBvIGRlbGVuw60gdHJvbWkgKHR6diBtb2R1bG8pCgoKIyBSb3VuZGluZwpyb3VuZF9iICAgPC0gcm91bmQoYikgICAgICAgIyB6YW9rcnVobG92YW5pZSBzbWVyb20gayBuYWpibGl6c2llbXUgY2VsZW11IGNpc2x1CmNlaWxfYiAgICA8LSBjZWlsaW5nKGIpICAgICAjIG5hamJsaXpzaWUgdnlzc2llIGNlbGUgY2lzbG8KZmxvb3JfYiAgIDwtIGZsb29yKGIpICAgICAgICMgbmFqYmxpenNpZSBuaXpzaWUgY2VsZSBjaXNsbwoKYTsgYgpzdW1fYWI7IGRpZmZfYWI7IHByb2RfYWI7IHF1b3RfYWI7IHBvd2VyX2FiOyBtb2RfYWI7CnJvdW5kX2I7IGNlaWxfYjsgZmxvb3JfYgpgYGAKCioqUG96bsOhbWt5KioKCi0gYF5gIG9wZXLDoXRvciB1bW9jxYhvdmFuaWEuCi0gYCUlYCBqZSBtb2R1bG8sIHRlZGEgemJ5dG9rIHBvIGRlbGVuw60sIAotIGByb3VuZCh4LCBkaWdpdHMgPSAwKWAgemFva3LDumjEvm92YW5pZSBuYSB1csSNaXTDvSBwb8SNZXQgZGVzYXRpbm7DvWNoIG1pZXN0IChkaWdpdHM9KS4gYWsgZGlnaXRzID0gMCwgcG90b20gaWRlIG8gY2Vsb8SNw61zZWxuw6kgemFva3LDumjEvm92YW5pZQoKCiMjIE1hbMOpIGN2acSNZW5pZQoKPiBWeXBvxI3DrXRhanRlOgoKJCRcZnJhY3soMTVeMi00KX17N30kJAoKYGBge3J9CigoMjFeKDEuMikgKiA4KSAvICgzLzIpKS0oOC8yLjUpCmBgYAoKLS0tCgojIFRleHQgCgojIyBWeXR2w6FyYW5pZSB0ZXh0b3bDvW1pIHByZW1lbm7DvW1pIGEgcHLDoWNhIHMgbmltaQoKYGBge3J9CmZpcnN0IDwtICJCYXJib3JhIiAgICAgICAgICAgICAgICAgICAgICAgIyBkZWZpbm92YW5pZSBvYnNhaHUgdGV4dG92ZWogcHJlbWVubmVqIGZpcnN0Cmxhc3QgIDwtICJLb3ByZG92YSIgICAgICAgICAgICAgICAgICAgICAgICAgICMgZGVmaW5vdmFuaWUgb2JzYWh1IHRleHQuIHByZW1lbm5laiBsYXN0CmZ1bGwgIDwtIHBhc3RlKGZpcnN0LCBsYXN0KSAgICAgICAgICAgICAgICMgc3BvamVuaWUgZHZvY2ggdGV4dC4gcHJlbWVubnljaCBkbyBqZWRuZWogKHMgbWVkemVyb3UpCmZ1bGxfbm9zcGFjZSA8LSBwYXN0ZTAoZmlyc3QsIGxhc3QpICAgICAgICMgc3BvamVuaWUgYmV6IG1lZHplcnkKY3N2X2xpbmUgPC0gcGFzdGUoInN0bHAiLCAicG9zdGVsIiwgInBhcGllciIsIHNlcCA9ICIsIikgICMgc3BvamVuaWUgdGV4dG92IHMgb2RkZWxvdmFjb20gLApmaXJzdDsgbGFzdDsgZnVsbDsgZnVsbF9ub3NwYWNlOyBjc3ZfbGluZSAgICMgYm9ka2/EjWlhcmthIHR1IG5haHJhZHp1amUgb2Rza29rIG5hIG5vdnkgcmlhZG9rIApgYGAKCiMjIETEusW+a2EgdGV4dG92w6lobyByZcWlYXpjYSwgcG9kcmXFpWF6ZWMKCmBgYHtyfQp4IDwtICJBaG9qIGphIHNvbSBGZXJvISIKbmNoYXIoeCkgICAgICAgICAgICAgICAgICMgcG/EjWV0IHpuYWtvdiAgdiByZXRhemNpICJSIGlzIGdyZWF0ISIKc3Vic3RyKHgsIDksIDExKSAgICAgICAgICAjIHBvZHJlxaVhemVjIG9kIDEuIGRvIDUuIHpuYWt1CmBgYAoKCj4gVGlwOiBLbmnFvm5pY2EgKipzdHJpbmdyKiogbW5vaMOpIHphdWrDrW1hdsOpIG1vxb5ub3N0aSBwcsOhY2UgcyB0ZXh0YW1pLCBhbGUgaW1wbGljaXRuw6kga25pxb5uaWNlIFIgcG9rcsO9dmFqw7ogdsOkxI3FoWludSBiZcW+bsO9Y2ggcG90cmllYiBww6FjZSBzIHRleHRhbWkuCgotLS0KCiMgTG9naWNrw6kgKGJvb2xvdnNrw6kpIGhvZG5vdHkgYSBwcmVtZW5uw6kKCiMjIFrDoWtsYWR5CgpgYGB7cn0KZiA8LSBUUlVFCmogPC0gRkFMU0UKIWEgICAgICAgICAgICAgICAgICMgTk9UCmYgJiBqICAgICAgICAgICAgICAjIEFORApmIHwgaiAgICAgICAgICAgICAgIyBPUgp4b3IoZiwgaikgICAgICAgICAgIyBleGNsdXNpdmUgT1IgLSBwbGF0w60gbGVuIGplZG5vIHogcCxhbGVibyBxCmBgYAoKIyMgTG9naWNrw70gdsO9c2xlZG9rIHBvcm92bsOhdmFuaWEKCmBgYHtyfQoyODEgPCAzMzMKNDQgPj0gNDQKIm9iZWQiID09ICJvYmVkIgoib2JlZCIgIT0gInZlY2VyYSIgICAjIHZ5a3JpY25payBqZSB0dSB2IHpteXNsZSBuZWdhY2llLiBOYXByLjogICAhPSwgIT4sICE8LCAhVFJVRQohVFJVRQpgYGAKCiMjIFpsb8W+aXRlasWhaWUgbG9naWNrw6kgb3BlcsOhY2llCgpgYGB7cn0KeSA8LSA4OQp5ID4gMyAmIHggPCAyMDAgICAgICAjIGEgc3VjYXNuZSAtIGxvZ2lja3kgcHJpZW5payAoc3VjaW4pCnkgPCAxMCB8IHggPiAzMCAgICAgIyBhbGVibyAtIGxvZ2lja2UgemplZG5vdGVuaWUgKHN1Y2V0KQogICAgICAgICAgICAgICAgICAgICMgcHJpIHpsb3ppdGVqc2ljaCB2enRhaG9jaCBwb3V6aXZhanRlIHphdHZvcmt5ICgpCmBgYAoKIyMgWmx1xI1vdmFuaWUgdmlhY2Vyw71jaCBsb2cuIHByZW1lbm7DvWNoIGRvIHZla3RvcmEKCmBgYHtyfQp2YWxzIDwtIGMoVFJVRSwgRkFMU0UsIFRSVUUsIFRSVUUpICAgIyBkZWZpbmljaWEgdmVrdG9yYSBzIGxvZ2lja3ltaSBob2Rub3RhbWkKYGBgCgotLS0KCiMgTnVtZXJpY2vDqSB2ZWt0b3J5CgojIyBHZW5lcm92YW5pZSB2ZWt0b3JvdgoKYGBge3J9CnYxIDwtIGMoMywgNiwgOSwgMTIpCnYyIDwtIDM6MTUgICAgICAgICAgICAgICAgICAjIHBvc3R1cG5vc3QgMSwyLDMsNCw1CnYzIDwtIHNlcShmcm9tID0gMCwgdG8gPSAxNiwgYnkgPSAwLjU1KSAgIyBwb3N0dXBub3N0IHMga3Jva29tIDAuMjUKdjQgPC0gcmVwKDMsIHRpbWVzID0gNCkgICAgIyAzLDMsMywzLDMgICMgNSBjbGVubmEgcG9zdHVwbm9zdCB0cm9qYWsKdjUgPC0gcnVuaWYoNCkgICAgICAgICAgICAgIyBnZW5lcm92YW5pZSByb3Zub21lcm5lIHJvemRlbGVueWNoIHByZW1lbm55Y2ggdiBpbnRlcnZhbGUgWzAsMV0KdjYgPC0gcm5vcm0oNCkgICAgICAgICAgICAgIyBnZW5lcm92YW5pZSBub3JtYWxuZSByb3pkZWxlbnljaCBwcmVtZW5ueWNoCnYxOyB2MjsgdjM7IHY0OyB2NQpgYGAKCiMjIEFyaXRtZXRpY2vDqSBvcGVyw6FjaWUgcyB2ZWt0b3JtaQoKYGBge3J9CnYgPC0gYygxMCwgMzIsIDQ0LCA1OCkKdiArIDMgICAgICAgICAgICMga2F6ZHkgcHJ2b2sgdmVrdG9yYSB6dmFjc2ltZSBvIDEwCnYgKiA5ICAgICAgICAgICAgIyBrYXpkeSBwcnZvayB2ZWt0b3JhIHByZW5hc29iaW1lIDIKKHYgKyAxKSAvIDIKZXhwKHYpICAgICAgICAgICAjIGV4cG9uZW5jaWFsbmEgZnVua2NpYSB6IGthemRlaG8gcHJ2a3UgdmVrdG9yYQpzdW0oYyg4LDksMTApLGMoMiwzLDMpKSAgICAgICAgICAjIHNrYWxhcm55IHN1Y2luIC0gdnlzbGVkb2sgamUgc2thbGFyCmNyb3NzcHJvZChjKDQsNiw4KSxjKDEwLDEyLDE0KSkgICAgIyBza2FsYXJueSBzdWNpbiAtIHZ5c2xlZG9rIGplIG1hdGljYSAxeDEKYygxMSwyMiwzMzMpKmMoNSw1LDUpICAgICAgICAgICAgICAgIyBIYWRhbWFyZG92IHN1Y2luIChzdWNpbiB6b2Rwb3ZlZGFqdWNpY2ggcHJ2a292IHZla3RvcmEpCmBgYAoKIyMgTWF0ZW1hdGlja8OpIG9wZXLDoWNpZSBzIDIgdmVrdG9ybWkgcm92bmFrw6lobyByb3ptZXJ1CgpgYGB7cn0KbGVuZ3RoKGMoMiw4LDE0LDEsMykpCmxlbmd0aCh2NSkgICAgICAgICAgICAjdmVrdG9yIHY1IGplIGRlZmlub3Zhbnkgdnlzc2llCmMoNiw4LDMsMTAsMSkgKyB2NSAgICAgIyBwb3pvciwgb2JhIHZla3RvcnkgbXVzaWEgbWF0IHJvdm5ha3kgcm96bWVyCmBgYAoKIyMgSW5kZXhvdmFuaWUgYSB2w71iZXIgbmlla3RvcnljaCBwcnZrb3YgdmVrdG9yYQoKYGBge3J9CnggPC0gYygzLCA4LCAzMywgMSwgMiwgMTgsIDI5KQp4WzNdICAgICAgICAgICAjIGluZGV4b3ZhbmllIC0gbm92eSBqZWRuby1wcnZrb3Z5IHZla3RvciAtIHBydnkgcHJ2b2sgdmVrdG9yYSB4CnhbMToyXSAgICAgICAgICMgbm92eSB2ZWt0b3IgcyBkcnVoeW0gYXogc3R2cnR5bSBwcnZrb20gdmVrdG9yYSB4CnhbLTVdICAgICAgICAgICMgbm92eSB2ZWt0b3IgLSB2c2V0a3kgcHJ2a3kgdmVrdG9yYSB4IG9rcmVtIHBydsOpaG8KeFt4ID4gMjBdICAgICAgIyBub3Z5IHZla3RvciBkZWZpbm92YW55IHBydmthbWkgeCB2YWNzaW1pIGFrbyAxMAp3aGljaCh4ID4gMjApICAjIGt0b3JlIHBydmt5IHpvZHBvdmVkYWp1IHBvZG1pZW5rZSB2YWNzaWVobyBha28gMTA/CmBgYAoKIyMgUHLDoWNhIHMgY2jDvWJhasO6Y2ltaSBob2Rub3RhbWkKCmBgYHtyfQp5IDwtIGMoMSwgTkEsIDMsIE5BLCA1KQppcy5uYSh5KQptZWFuKHkpICAgICAgICAgICAgICAgICAjIE5BCm1lYW4oeSwgbmEucm0gPSBUUlVFKSAgICMgcmVtb3ZlIE5BcwpgYGAKCiMjIFrDoWtsYWRuw6kgxaF0YXRpc3Rpa3kgYSB1c3BvcmlhZGFuaWUgcHJ2a292IHZla3RvcmEgcG9kxL5hIHZlxL5rb3N0aQoKYGBge3J9CmEgPC0gYygxLCA2LCAzLCA5LCA0KQptZWFuKGEpICAgICAgICAgICAgICAgICAjIHByaWVtZXJuYSBob2Rub3RhCnNkKGEpICAgICAgICAgICAgICAgICAgIyBzdGFuZGFyZG5hIG9kY2h5bGthCm1heChhKSAgICAgICAgICAgICAgICAgICMgbWF4aW1hbG5hIGhvZG5vdGEKc3VtbWFyeShhKSAgICAgICAgICAgICAgIyByeWNobHkgcHJlaGxhZCB6YWtsYWRueWNoIHN0YXRpc3RpayBvIHZla3RvcmUKc29ydChhKSAgICAgICAgICAgICAgICAgIyByYXN0dWNlIHVzcG9yaWFkYW5pZSAKc29ydChhLCBkZWNyZWFzaW5nID0gVFJVRSkgICMga2xlc2FqdWNlCmBgYAoKIyMgTWFsw6kgY3ZpxI1lbmllCj4gVnl0dm9ydGUgdmVrdG9yIGB3YCBzIMSNw61zbGFtaSAxLi4yMCBhIHZ5cG/EjcOtdGFqdGUgc3VtdSB2xaFldGvDvWNoIHDDoXJueWNoIMSNw61zZWwuCgpgYGB7cn0KayA8LSAxOjE4CnN1bSh3W3cgJSUgMiA9PSAwXSkKYGBgCgotLS0KCiMgTWF0aWNlCgojIyBWeXR2b3JlbmllIG1hdMOtYwoKYGBge3J9Cm0gPC0gbWF0cml4KDE6MTIsIG5yb3cgPSA1LCBuY29sID0gMykgICAgICAgICAgICAjIGhvZG5vdHkgc8O6IHphZGF2YW5lIHBvIHN0bHBjb2NoCm1fYnlyb3cgPC0gbWF0cml4KDE6MTIsIG5yb3cgPSA1LCBieXJvdyA9IFRSVUUpICAjIGhvZG5vdHkgc3UgemFkYXZhbmUgcG8gcmlhZGtvY2gKbTsgbV9ieXJvdwpgYGAKCiMjIFJvem1lcnkgbWF0aWNlCgpgYGB7cn0KZGltKG0pICAgICAgICAgICAgICAgICAgICMgKHJvd3MsIGNvbHMpCm0KYGBgCgojIyBBZHJlc292YW5pZSBwcnZrb3YgbWF0aWNlCgpgYGB7cn0KbVsyLCAzXSAgICAgICMgcmlhZG9rIDEsIHN0bHBlYyAyCm1bICwgMl0gICAgICAjIHZzZXRreSBwcnZreSB2IHRyZXRvbSBzdGxwY2kgLSB2eXNsZWRvayBtYXRpY2EgM3gxCm1bMywgXSAgICAgICAjIHZzZXRreSBwcnZreSB2IGRydWhvbSByaWFka3UgLSB2eXNsZWRvayBtYXRpY2EgMSozCm1bMTo1LCAxOjJdICAjIHBvZG1hdGljYSB0dm9yZW5hIHJpYWRrYW1pIDEsIDIgYSBzdGxwY2FtaSAyLCAzCmBgYAoKIyMgTWF0aWNvdsOpIG9wZXLDoWNpZQoKYGBge3J9CkEgPC0gbWF0cml4KGMoNiwyLDEsNSksIG5yb3cgPSAyKQpCIDwtIG1hdHJpeChjKDEsMyw0LDIpLCBucm93ID0gMikKQyA8LSBtYXRyaXgoYygyLDMsNSwyKSwgbnJvdyA9IDIpCgpBICsgQiAgICAgICAgIyBzY2l0YW5pZSBtYXRpYwpBICogQiAgICAgICAgIyBIYWRhbWFyZCBwcm9kdWN0IC0gbmFzb2JlbmllIHBvIHpvZHBvdmVkYWp1Y2ljaCBwcnZrb2NoCkEgJSolIEIgICAgICAjIG5hc29iZW5pZSBtYXRpYwp0KEEpICAgICAgICAgIyB0cmFuc3BvemljaWEgbWF0aWNlIEEgLSB2eW1lbmEgcmlhZGtvdiBhIHN0bHBjb3YKZGV0KEEpICAgICAgICMgZGV0ZXJtaW5hbnQgbWF0aWNlCnNvbHZlKEEpICAgICAjIGludmVyemlhIG1hdGljZSAoYWsgamUgbWF0aWNhIHJlZ3VsYXJuYSAtIHRlZGEgaW52ZXJ6aWEgc2EgZGEgc3BvY2l0YXQpCmBgYAoKIyMgWmx1xI1vdmFuaWUgdmVrdG9yb3YgZG8gbWF0w61jIAoKYGBge3J9CkMgPC0gY2JpbmQoMjo0LCAxOjMpICAgIyAgLSBwbyBzdGxwY29jaCAKRCA8LSByYmluZCg4OjMsIDU6NykgICAjICAtIHBvIHJpYWRrb2NoIApDOyBECmBgYAoKIyMgVnlwb8SNw610YW5pZSB6dm9sZW5laiDFoXRhdGlzdGlreSBwbyByaWFka29jaCAoc3TEunBjb2NoKSBtYXRpY2UKCmBgYHtyfQpNIDwtIG1hdHJpeCgyOjQsIG5yb3cgPSAyKQpNCmFwcGx5KE0sIDIsIHN1bSkgICAjIHN1bWEgcG8gcmlhZGtvY2gKYXBwbHkoTSwgMiwgbWVhbikgICMgcHJpZW1lcnkgcG8gc3TEunBjb2NoCmBgYAoKIyMgTWFsw6kgY3ZpxI1lbmllCgo+IFZ5dHZvcnRlIG1hdGljdSA1eDUgcyBob2Rub3RhbWkgcG8gcmlhZGtvY2ggMS4uMjUsIHZ5cG/EjcOtdGFqdGUgc3TEunBjb3bDqSBzdW15IGEgc8O6xI1pbiBtYXTDrWMgXChNXnQgTVwpLgoKYGBge3J9Ck0yIDwtIG1hdHJpeCgxOjE1LCBucm93ID0gNSwgYnlyb3cgPSBUUlVFKQpjb2xTdW1zKE0yKQp0KE0yKSAlKiUgTTIKYGBgCmBgYHtyfQojIDEpIE1vamUgZMOhdGEgCndhdGVyIDwtIGMoNiwgOCwgNSwgOSwgNywgNCwgMTApICAjIFBvxI1ldCBwb2jDoXJvdiB2b2R5IHYgZMWIb2NoIDEuLjcKCiMgMikgTWFsw6kgw7psb2h5CnN1bSh3YXRlciA+PSA4KSAgICAgICAgICAgIyBhKSBrb8S+a28gZG7DrSA+PSA4IHBvaMOhcm92Cm1lYW4od2F0ZXIpICAgICAgICAgICAgICAgIyBiKSBwcmllbWVyIHphIHTDvcW+ZGXFiAp3aGljaC5tYXgod2F0ZXIpICAgICAgICAgICMgYykga3RvcsO9IGRlxYggYm9sIG5hamxlcMWhw60gKGluZGV4IGTFiGEgMS4uNykKd2F0ZXJbd2hpY2gubWF4KHdhdGVyKV0gICAjICAgIGtvxL5rbyBwb2jDoXJvdiB0byBib2xvCgojIDMpIEdyYWYgKMSNYXNvdsOhIGtyaXZrYSkKcGxvdCgKICB3YXRlciwgdHlwZSA9ICJvIiwKICBtYWluID0gIlBvaMOhcmUgdm9keSB6YSA3IGRuw60iLAogIHhsYWIgPSAiRGXFiCIsIHlsYWIgPSAiUG/EjWV0IHBvaMOhcm92IiwKICB5bGltID0gYygwLCBtYXgod2F0ZXIpICsgMSkKKQphYmxpbmUoaCA9IDgsIGx0eSA9IDIpICAjIHZ5em5hxI1lbsO9IGNpZcS+IDggcG9ow6Fyb3YKCmRheXMgPC0gYygiUG8iLCJVdCIsIlN0IiwixaB0IiwiUGkiLCJTbyIsIk5lIikKcGxvdCgxOjcsIHdhdGVyLCB0eXBlPSJvIiwgeGF4dD0ibiIsIHhsYWI9IkRlxYgiLCB5bGFiPSJQb2jDoXJlIikKYXhpcygxLCBhdD0xOjcsIGxhYmVscz1kYXlzKTsgYWJsaW5lKGg9OCwgbHR5PTIpCgpgYGAKCgoKCgoKCgo=