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
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.
Skaláre (jednočíselné hodnoty)
Numerické skaláre
# Priradenie konštanty do premennej
a <- 7
b <- 3.5
# Arithmetic
sum_ab <- a + b # sucet
diff_ab <- a - b # rozdiel
prod_ab <- a * b # násobenie
quot_ab <- a / b # delenie
power_ab <- a ^ b # umocňovanie
mod_ab <- a %% 3 # zbytok po delení tromi (tzv modulo)
# Rounding
round_b <- round(b) # zaokruhlovanie smerom k najblizsiemu celemu cislu
ceil_b <- ceiling(b) # najblizsie vyssie cele cislo
floor_b <- floor(b) # najblizsie nizsie cele cislo
a; b
[1] 7
[1] 3.5
sum_ab; diff_ab; prod_ab; quot_ab; power_ab; mod_ab; int_div_ab
[1] 10.5
[1] 3.5
[1] 24.5
[1] 2
[1] 907.4927
[1] 1
Error: object 'int_div_ab' not found
Poznámky
^ operátor umocňovania.
%% je modulo, teda zbytok po delení,
round(x, digits = 0) zaokrúhľovanie na určitý počet
desatinných miest (digits=). ak digits = 0, potom ide o celočíselné
zaokrúhľovanie
Malé cvičenie
Vypočítajte:
\[\frac{(15^2-4)}{7}\]
Text
Vytváranie textovými premennými a práca s nimi
Dĺžka textového reťazca, podreťazec
Tip: Knižnica stringr mnohé zaujímavé možnosti práce
s textami, ale implicitné knižnice R pokrývajú väčšinu bežných potrieb
páce s textami.
Logické (boolovské) hodnoty a premenné
Základy
Logický výsledok porovnávania
Zložitejšie logické operácie
Zlučovanie viacerých log. premenných do vektora
Numerické vektory
Generovanie vektorov
Aritmetické operácie s vektormi
Matematické operácie s 2 vektormi rovnakého rozmeru
Indexovanie a výber niektorych prvkov vektora
Práca s chýbajúcimi hodnotami
Základné štatistiky a usporiadanie prvkov vektora podľa
veľkosti
Malé cvičenie
Vytvorte vektor w s číslami 1..20 a vypočítajte sumu
všetkých párnych čísel.
Matice
Vytvorenie matíc
Rozmery matice
Adresovanie prvkov matice
m[1, 2] # riadok 1, stlpec 2
Error: object 'm' not found
Maticové operácie
Zlučovanie vektorov do matíc
Vypočítanie zvolenej štatistiky po riadkoch (stĺpcoch) matice
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\).
Môj návrh použitia novinky
Priklad 1 - Skaláre a logické operácie
x <- 12 y <- 5
result <- (x^2 + y^2) / (x - y) result
result > 20
round(result, 2)
Príklad 2 - Práca s vektormi
v <- 5:30
div3 <- v[v %% 3 == 0] div3
mean(div3)
length(div3)
Príklad 3 - Matice
A <- matrix(1:16, nrow = 4, byrow = TRUE) A
rowSums(A)
colMeans(A)
t(A) %*% A
LS0tCnRpdGxlOiAiWsOha2xhZG7DqSBvcGVyw6FjaWUgdiBSIgphdXRob3I6ICJWbGFkaW3DrXIgR2F6ZGEgIDxicj4gKHMgdnl1xb5pdMOtbSBDaGF0R1BUKSIKZGF0ZTogIlNlcHRlbWJlciAyMDI1IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0aGVtZTogdW5pdGVkCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgZGZfcHJpbnQ6IHBhZ2VkCmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogNzIKLS0tCgojIEdsb2LDoWxuZSBuYXN0YXZlbmllIENodW5rb3YKClYgbmnFvsWhaWUgdXZlZGVub20gQ2h1bmt1IGplIHVyb2JlbsOpIHrDoWtsYWRuw6kgZ2xvYsOhbG5lIG5hc3RhdmVuaWUgQ2h1bmtvdiB2IGNlbG9tIE5vdGVib29rdS4gCgotICoqZWNobyoqIG5hc3RhdnVqZSwgxI1pIGNoY2VtZSB2IE5vdGVib29rdSB2eXBpc292YcWlIGplZG5vdGxpdsOpIGvDs2R5IFIKLSAqKm1lc3NhZ2UqKiBqZSBuYXN0YXZlbsO9IG5hICpGQUxTRSosIMSNbyB6bmFtZW7DoSwgxb5lIHNhIGJ1ZMO6IHBvdGzDocSNYcWlIHByYWNvdm7DqSB2w71zdHVweSB6IFIsIHQuai4gbmFwcsOta2xhZCB2w71zbGVkb2sgb3R2w6FyYW5pYSBrbmnFvm7DrWMsIGEgbmlla3RvcsOpIGluw6kgdsO9c3R1cHksIGt0b3LDqSBhbGUgcHJlIGNlbGtvdsO9IE5vdGVib29rIG5lbWFqw7ogdGFrbWVyIMW+aWFkZW4gdsO9em5hbSBhIHPDuiB2aG9kbsOpIHNrw7RyIHByaSBsYWRlbsOtIGvDs2Rvdi4KLSAqKndhcm5pbmcqKiBuYXN0YXZlbsO9IG5hIEZBTFNFIHBvdGzDocSNYSB6b2JyYXplbmllIGNoeWJvdsO9Y2ggaGzDocWhb2sKCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1UUlVFLGVjaG89VFJVRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UKKQpgYGAKCiMgw5p2b2QgayB6w6FrbGFkbsO9bSBvcGVyw6FjacOhbSB2IFIKClRlbnRvIG5vdGVib29rIGRlbW9uxaF0cnVqZSAqKnrDoWtsYWRuw6kgb3BlcsOhY2llKiogdiBqYXp5a3UgUiBzbzoKCi0gc2thbMOhcm55bWkgxI3DrXNsYW1pICh0LmouIDEgxI3DrXNsbyksCi0gdGV4dG92w71taSAoem5ha292w71taSkgcmXFpWF6Y2FtaSwKLSBsb2dpY2vDvW1pIChib29sb3Zza8O9bWkpIGhvZG5vdGFtaSBhIHByZW1lbm7DvW1pLAotIChudW1lcmlja8O9bWkpIHZla3Rvcm1pLAotIG1hdGljYW1pLgoKVGFtLCBrZGUgamUgdG8gdcW+aXRvxI1uw6ksIHPDuiB6YWhybnV0w6kgbWFsw6kgY3ZpxI1lbmlhLgoKLS0tCgojIFNrYWzDoXJlIChqZWRub8SNw61zZWxuw6kgaG9kbm90eSkKCiMjIE51bWVyaWNrw6kgc2thbMOhcmUKCmBgYHtyfQojIFByaXJhZGVuaWUga29uxaF0YW50eSBkbyBwcmVtZW5uZWoKYSA8LSA3CmIgPC0gMy41CgojIEFyaXRobWV0aWMKc3VtX2FiICAgICAgPC0gYSArIGIgICAgICAgICMgc3VjZXQKZGlmZl9hYiAgICAgPC0gYSAtIGIgICAgICAgICMgcm96ZGllbApwcm9kX2FiICAgICA8LSBhICogYiAgICAgICAgIyBuw6Fzb2JlbmllCnF1b3RfYWIgICAgIDwtIGEgLyBiICAgICAgICAjIGRlbGVuaWUKcG93ZXJfYWIgICAgPC0gYSBeIGIgICAgICAgICMgdW1vY8WIb3ZhbmllCm1vZF9hYiAgICAgIDwtIGEgJSUgMyAgICAgICAjIHpieXRvayBwbyBkZWxlbsOtIHRyb21pICh0enYgbW9kdWxvKQoKCiMgUm91bmRpbmcKcm91bmRfYiAgIDwtIHJvdW5kKGIpICAgICAgICMgemFva3J1aGxvdmFuaWUgc21lcm9tIGsgbmFqYmxpenNpZW11IGNlbGVtdSBjaXNsdQpjZWlsX2IgICAgPC0gY2VpbGluZyhiKSAgICAgIyBuYWpibGl6c2llIHZ5c3NpZSBjZWxlIGNpc2xvCmZsb29yX2IgICA8LSBmbG9vcihiKSAgICAgICAjIG5hamJsaXpzaWUgbml6c2llIGNlbGUgY2lzbG8KCmE7IGIKc3VtX2FiOyBkaWZmX2FiOyBwcm9kX2FiOyBxdW90X2FiOyBwb3dlcl9hYjsgbW9kX2FiOyBpbnRfZGl2X2FiCnJvdW5kX2I7IGNlaWxfYjsgZmxvb3JfYgpgYGAKCioqUG96bsOhbWt5KioKCi0gYF5gIG9wZXLDoXRvciB1bW9jxYhvdmFuaWEuCi0gYCUlYCBqZSBtb2R1bG8sIHRlZGEgemJ5dG9rIHBvIGRlbGVuw60sIAotIGByb3VuZCh4LCBkaWdpdHMgPSAwKWAgemFva3LDumjEvm92YW5pZSBuYSB1csSNaXTDvSBwb8SNZXQgZGVzYXRpbm7DvWNoIG1pZXN0IChkaWdpdHM9KS4gYWsgZGlnaXRzID0gMCwgcG90b20gaWRlIG8gY2Vsb8SNw61zZWxuw6kgemFva3LDumjEvm92YW5pZQoKCiMjIE1hbMOpIGN2acSNZW5pZQoKPiBWeXBvxI3DrXRhanRlOgoKJCRcZnJhY3soMTVeMi00KX17N30kJAoKYGBge3J9CigxNV4yIC0gNCkgLyA3CmBgYAoKLS0tCgojIFRleHQgCgojIyBWeXR2w6FyYW5pZSB0ZXh0b3bDvW1pIHByZW1lbm7DvW1pIGEgcHLDoWNhIHMgbmltaQoKYGBge3J9CmZpcnN0IDwtICJWbGFkaW1pciIgICAgICAgICAgICAgICAgICAgICAgICMgZGVmaW5vdmFuaWUgb2JzYWh1IHRleHRvdmVqIHByZW1lbm5laiBmaXJzdApsYXN0ICA8LSAiR2F6ZGEiICAgICAgICAgICAgICAgICAgICAgICAgICAjIGRlZmlub3ZhbmllIG9ic2FodSB0ZXh0LiBwcmVtZW5uZWogbGFzdApmdWxsICA8LSBwYXN0ZShmaXJzdCwgbGFzdCkgICAgICAgICAgICAgICAjIHNwb2plbmllIGR2b2NoIHRleHQuIHByZW1lbm55Y2ggZG8gamVkbmVqIChzIG1lZHplcm91KQpmdWxsX25vc3BhY2UgPC0gcGFzdGUwKGZpcnN0LCBsYXN0KSAgICAgICAjIHNwb2plbmllIGJleiBtZWR6ZXJ5CmNzdl9saW5lIDwtIHBhc3RlKCJhcHBsZSIsICJiYW5hbmEiLCAicGVhciIsIHNlcCA9ICIsIikgICMgc3BvamVuaWUgdGV4dG92IHMgb2RkZWxvdmFjb20gLApmaXJzdDsgbGFzdDsgZnVsbDsgZnVsbF9ub3NwYWNlOyBjc3ZfbGluZSAgICMgYm9ka2/EjWlhcmthIHR1IG5haHJhZHp1amUgb2Rza29rIG5hIG5vdnkgcmlhZG9rIApgYGAKCiMjIETEusW+a2EgdGV4dG92w6lobyByZcWlYXpjYSwgcG9kcmXFpWF6ZWMKCmBgYHtyfQp4IDwtICJSIGlzIGdyZWF0ISIKbmNoYXIoeCkgICAgICAgICAgICAgICAgICMgcG/EjWV0IHpuYWtvdiAgdiByZXRhemNpICJSIGlzIGdyZWF0ISIKc3Vic3RyKHgsIDEsIDUpICAgICAgICAgICMgcG9kcmXFpWF6ZWMgb2QgMS4gZG8gNS4gem5ha3UKYGBgCgoKPiBUaXA6IEtuacW+bmljYSAqKnN0cmluZ3IqKiBtbm9ow6kgemF1asOtbWF2w6kgbW/Fvm5vc3RpIHByw6FjZSBzIHRleHRhbWksIGFsZSBpbXBsaWNpdG7DqSBrbmnFvm5pY2UgUiBwb2tyw712YWrDuiB2w6TEjcWhaW51IGJlxb5uw71jaCBwb3RyaWViIHDDoWNlIHMgdGV4dGFtaS4KCi0tLQoKIyBMb2dpY2vDqSAoYm9vbG92c2vDqSkgaG9kbm90eSBhIHByZW1lbm7DqQoKIyMgWsOha2xhZHkKCmBgYHtyfQpwIDwtIFRSVUUKcSA8LSBGQUxTRQohcCAgICAgICAgICAgICAgICAgIyBOT1QKcCAmIHEgICAgICAgICAgICAgICMgQU5ECnAgfCBxICAgICAgICAgICAgICAjIE9SCnhvcihwLCBxKSAgICAgICAgICAjIGV4Y2x1c2l2ZSBPUiAtIHBsYXTDrSBsZW4gamVkbm8geiBwLGFsZWJvIHEKYGBgCgojIyBMb2dpY2vDvSB2w71zbGVkb2sgcG9yb3Zuw6F2YW5pYQoKYGBge3J9CjMgPCA1CjcgPj0gNwoiY2F0IiA9PSAiY2F0IgoiY2F0IiAhPSAiZG9nIiAgICMgdnlrcmljbmlrIGplIHR1IHYgem15c2xlIG5lZ2FjaWUuIE5hcHIuOiAgICE9LCAhPiwgITwsICFUUlVFCiFUUlVFCmBgYAoKIyMgWmxvxb5pdGVqxaFpZSBsb2dpY2vDqSBvcGVyw6FjaWUKCmBgYHtyfQp4IDwtIDEwCnggPiA1ICYgeCA8IDIwICAgICAgIyBhIHN1Y2FzbmUgLSBsb2dpY2t5IHByaWVuaWsgKHN1Y2luKQp4IDwgMCB8IHggPiAxMDAgICAgICMgYWxlYm8gLSBsb2dpY2tlIHpqZWRub3RlbmllIChzdWNldCkKICAgICAgICAgICAgICAgICAgICAjIHByaSB6bG96aXRlanNpY2ggdnp0YWhvY2ggcG91eml2YWp0ZSB6YXR2b3JreSAoKQpgYGAKCiMjIFpsdcSNb3ZhbmllIHZpYWNlcsO9Y2ggbG9nLiBwcmVtZW5uw71jaCBkbyB2ZWt0b3JhCgpgYGB7cn0KdmFscyA8LSBjKFRSVUUsIEZBTFNFLCBUUlVFLCBUUlVFKSAgICMgZGVmaW5pY2lhIHZla3RvcmEgcyBsb2dpY2t5bWkgaG9kbm90YW1pCmBgYAoKLS0tCgojIE51bWVyaWNrw6kgdmVrdG9yeQoKIyMgR2VuZXJvdmFuaWUgdmVrdG9yb3YKCmBgYHtyfQp2MSA8LSBjKDIsIDQsIDYsIDgpCnYyIDwtIDE6NSAgICAgICAgICAgICAgICAgICMgcG9zdHVwbm9zdCAxLDIsMyw0LDUKdjMgPC0gc2VxKGZyb20gPSAwLCB0byA9IDEsIGJ5ID0gMC4yNSkgICMgcG9zdHVwbm9zdCBzIGtyb2tvbSAwLjI1CnY0IDwtIHJlcCgzLCB0aW1lcyA9IDUpICAgICMgMywzLDMsMywzICAjIDUgY2xlbm5hIHBvc3R1cG5vc3QgdHJvamFrCnY1IDwtIHJ1bmlmKDUpICAgICAgICAgICAgICMgZ2VuZXJvdmFuaWUgcm92bm9tZXJuZSByb3pkZWxlbnljaCBwcmVtZW5ueWNoIHYgaW50ZXJ2YWxlIFswLDFdCnY2IDwtIHJub3JtKDUpICAgICAgICAgICAgICMgZ2VuZXJvdmFuaWUgbm9ybWFsbmUgcm96ZGVsZW55Y2ggcHJlbWVubnljaAp2MTsgdjI7IHYzOyB2NDsgdjUKYGBgCgojIyBBcml0bWV0aWNrw6kgb3BlcsOhY2llIHMgdmVrdG9ybWkKCmBgYHtyfQp2IDwtIGMoMSwgMiwgMywgNCkKdiArIDEwICAgICAgICAgICAjIGthemR5IHBydm9rIHZla3RvcmEgenZhY3NpbWUgbyAxMAp2ICogMiAgICAgICAgICAgICMga2F6ZHkgcHJ2b2sgdmVrdG9yYSBwcmVuYXNvYmltZSAyCih2ICsgMSkgLyAyCmV4cCh2KSAgICAgICAgICAgIyBleHBvbmVuY2lhbG5hIGZ1bmtjaWEgeiBrYXpkZWhvIHBydmt1IHZla3RvcmEKc3VtKGMoMSwyLDMpLGMoMSwxLDEpKSAgICAgICAgICAjIHNrYWxhcm55IHN1Y2luIC0gdnlzbGVkb2sgamUgc2thbGFyCmNyb3NzcHJvZChjKDEsMiwzKSxjKDEsMSwxKSkgICAgIyBza2FsYXJueSBzdWNpbiAtIHZ5c2xlZG9rIGplIG1hdGljYSAxeDEKYygxLDIsMykqYygxLDEsMSkgICAgICAgICAgICAgICAjIEhhZGFtYXJkb3Ygc3VjaW4gKHN1Y2luIHpvZHBvdmVkYWp1Y2ljaCBwcnZrb3YgdmVrdG9yYSkKYGBgCgojIyBNYXRlbWF0aWNrw6kgb3BlcsOhY2llIHMgMiB2ZWt0b3JtaSByb3ZuYWvDqWhvIHJvem1lcnUKCmBgYHtyfQpsZW5ndGgoYygxLDIsMyw0LDUpKQpsZW5ndGgodjUpICAgICAgICAgICAgI3Zla3RvciB2NSBqZSBkZWZpbm92YW55IHZ5c3NpZQpjKDEsMiwzLDQsNSkgKyB2NSAgICAgIyBwb3pvciwgb2JhIHZla3RvcnkgbXVzaWEgbWF0IHJvdm5ha3kgcm96bWVyCmBgYAoKIyMgSW5kZXhvdmFuaWUgYSB2w71iZXIgbmlla3RvcnljaCBwcnZrb3YgdmVrdG9yYQoKYGBge3J9CnggPC0gYyg1LCAxMiwgMywgMTgsIDcsIDAsIDIxKQp4WzFdICAgICAgICAgICAjIGluZGV4b3ZhbmllIC0gbm92eSBqZWRuby1wcnZrb3Z5IHZla3RvciAtIHBydnkgcHJ2b2sgdmVrdG9yYSB4CnhbMjo0XSAgICAgICAgICMgbm92eSB2ZWt0b3IgcyBkcnVoeW0gYXogc3R2cnR5bSBwcnZrb20gdmVrdG9yYSB4CnhbLTFdICAgICAgICAgICMgbm92eSB2ZWt0b3IgLSB2c2V0a3kgcHJ2a3kgdmVrdG9yYSB4IG9rcmVtIHBydsOpaG8KeFt4ID4gMTBdICAgICAgIyBub3Z5IHZla3RvciBkZWZpbm92YW55IHBydmthbWkgeCB2YWNzaW1pIGFrbyAxMAp3aGljaCh4ID4gMTApICAjIGt0b3JlIHBydmt5IHpvZHBvdmVkYWp1IHBvZG1pZW5rZSB2YWNzaWVobyBha28gMTA/CmBgYAoKIyMgUHLDoWNhIHMgY2jDvWJhasO6Y2ltaSBob2Rub3RhbWkKCmBgYHtyfQp5IDwtIGMoMSwgTkEsIDMsIE5BLCA1KQppcy5uYSh5KQptZWFuKHkpICAgICAgICAgICAgICAgICAjIE5BCm1lYW4oeSwgbmEucm0gPSBUUlVFKSAgICMgcmVtb3ZlIE5BcwpgYGAKCiMjIFrDoWtsYWRuw6kgxaF0YXRpc3Rpa3kgYSB1c3BvcmlhZGFuaWUgcHJ2a292IHZla3RvcmEgcG9kxL5hIHZlxL5rb3N0aQoKYGBge3J9CnogPC0gYygxMCwgMywgNSwgOCwgMikKbWVhbih6KSAgICAgICAgICAgICAgICAgIyBwcmllbWVybmEgaG9kbm90YQpzZCh6KSAgICAgICAgICAgICAgICAgICMgc3RhbmRhcmRuYSBvZGNoeWxrYQptYXgoeikgICAgICAgICAgICAgICAgICAjIG1heGltYWxuYSBob2Rub3RhCnN1bW1hcnkoeikgICAgICAgICAgICAgICMgcnljaGx5IHByZWhsYWQgemFrbGFkbnljaCBzdGF0aXN0aWsgbyB2ZWt0b3JlCnNvcnQoeikgICAgICAgICAgICAgICAgICMgcmFzdHVjZSB1c3BvcmlhZGFuaWUgCnNvcnQoeiwgZGVjcmVhc2luZyA9IFRSVUUpICAjIGtsZXNhanVjZQpgYGAKCiMjIE1hbMOpIGN2acSNZW5pZQo+IFZ5dHZvcnRlIHZla3RvciBgd2AgcyDEjcOtc2xhbWkgMS4uMjAgYSB2eXBvxI3DrXRhanRlIHN1bXUgdsWhZXRrw71jaCBww6FybnljaCDEjcOtc2VsLgoKYGBge3J9CncgPC0gMToyMApzdW0od1t3ICUlIDIgPT0gMF0pCmBgYAoKLS0tCgojIE1hdGljZQoKIyMgVnl0dm9yZW5pZSBtYXTDrWMKCmBgYHtyfQptIDwtIG1hdHJpeCgxOjEyLCBucm93ID0gMywgbmNvbCA9IDQpICAgICAgICAgICAgIyBob2Rub3R5IHPDuiB6YWRhdmFuZSBwbyBzdGxwY29jaAptX2J5cm93IDwtIG1hdHJpeCgxOjEyLCBucm93ID0gMywgYnlyb3cgPSBUUlVFKSAgIyBob2Rub3R5IHN1IHphZGF2YW5lIHBvIHJpYWRrb2NoCm07IG1fYnlyb3cKYGBgCgojIyBSb3ptZXJ5IG1hdGljZQoKYGBge3J9CmRpbShtKSAgICAgICAgICAgICAgICAgICAjIChyb3dzLCBjb2xzKQptCmBgYAoKIyMgQWRyZXNvdmFuaWUgcHJ2a292IG1hdGljZQoKYGBge3J9Cm1bMSwgMl0gICAgICAjIHJpYWRvayAxLCBzdGxwZWMgMgptWyAsIDNdICAgICAgIyB2c2V0a3kgcHJ2a3kgdiB0cmV0b20gc3RscGNpIC0gdnlzbGVkb2sgbWF0aWNhIDN4MQptWzIsIF0gICAgICAgIyB2c2V0a3kgcHJ2a3kgdiBkcnVob20gcmlhZGt1IC0gdnlzbGVkb2sgbWF0aWNhIDEqMwptWzE6MiwgMjozXSAgIyBwb2RtYXRpY2EgdHZvcmVuYSByaWFka2FtaSAxLCAyIGEgc3RscGNhbWkgMiwgMwpgYGAKCiMjIE1hdGljb3bDqSBvcGVyw6FjaWUKCmBgYHtyfQpBIDwtIG1hdHJpeChjKDEsMiwzLDQpLCBucm93ID0gMikKQiA8LSBtYXRyaXgoYyg1LDYsNyw4KSwgbnJvdyA9IDIpCgpBICsgQiAgICAgICAgIyBzY2l0YW5pZSBtYXRpYwpBICogQiAgICAgICAgIyBIYWRhbWFyZCBwcm9kdWN0IC0gbmFzb2JlbmllIHBvIHpvZHBvdmVkYWp1Y2ljaCBwcnZrb2NoCkEgJSolIEIgICAgICAjIG5hc29iZW5pZSBtYXRpYwp0KEEpICAgICAgICAgIyB0cmFuc3BvemljaWEgbWF0aWNlIEEgLSB2eW1lbmEgcmlhZGtvdiBhIHN0bHBjb3YKZGV0KEEpICAgICAgICMgZGV0ZXJtaW5hbnQgbWF0aWNlCnNvbHZlKEEpICAgICAjIGludmVyemlhIG1hdGljZSAoYWsgamUgbWF0aWNhIHJlZ3VsYXJuYSAtIHRlZGEgaW52ZXJ6aWEgc2EgZGEgc3BvY2l0YXQpCmBgYAoKIyMgWmx1xI1vdmFuaWUgdmVrdG9yb3YgZG8gbWF0w61jIAoKYGBge3J9CkMgPC0gY2JpbmQoMTozLCA0OjYpICAgIyAgLSBwbyBzdGxwY29jaCAKRCA8LSByYmluZCgxOjMsIDQ6NikgICAjICAtIHBvIHJpYWRrb2NoIApDOyBECmBgYAoKIyMgVnlwb8SNw610YW5pZSB6dm9sZW5laiDFoXRhdGlzdGlreSBwbyByaWFka29jaCAoc3TEunBjb2NoKSBtYXRpY2UKCmBgYHtyfQpNIDwtIG1hdHJpeCgxOjksIG5yb3cgPSAzKQpNCmFwcGx5KE0sIDEsIHN1bSkgICAjIHN1bWEgcG8gcmlhZGtvY2gKYXBwbHkoTSwgMiwgbWVhbikgICMgcHJpZW1lcnkgcG8gc3TEunBjb2NoCmBgYAoKIyMgTWFsw6kgY3ZpxI1lbmllCgo+IFZ5dHZvcnRlIG1hdGljdSA1eDUgcyBob2Rub3RhbWkgcG8gcmlhZGtvY2ggMS4uMjUsIHZ5cG/EjcOtdGFqdGUgc3TEunBjb3bDqSBzdW15IGEgc8O6xI1pbiBtYXTDrWMgXChNXnQgTVwpLgoKYGBge3J9Ck0yIDwtIG1hdHJpeCgxOjI1LCBucm93ID0gNSwgYnlyb3cgPSBUUlVFKQpjb2xTdW1zKE0yKQp0KE0yKSAlKiUgTTIKYGBgCgotLS0KIyBNw7RqIG7DoXZyaCBwb3XFvml0aWEgbm92aW5reSAKCiMjIFByaWtsYWQgMSAtIFNrYWzDoXJlIGEgbG9naWNrw6kgb3BlcsOhY2llIAoKeCA8LSAxMgp5IDwtIDUKCnJlc3VsdCA8LSAoeF4yICsgeV4yKSAvICh4IC0geSkKcmVzdWx0CgpyZXN1bHQgPiAyMAoKcm91bmQocmVzdWx0LCAyKQoKIyMgUHLDrWtsYWQgMiAtIFByw6FjYSBzIHZla3Rvcm1pIAoKdiA8LSA1OjMwCgpkaXYzIDwtIHZbdiAlJSAzID09IDBdCmRpdjMKCm1lYW4oZGl2MykKCmxlbmd0aChkaXYzKQoKIyMgUHLDrWtsYWQgMyAtIE1hdGljZQoKQSA8LSBtYXRyaXgoMToxNiwgbnJvdyA9IDQsIGJ5cm93ID0gVFJVRSkKQQoKcm93U3VtcyhBKQoKY29sTWVhbnMoQSkKCnQoQSkgJSolIEEKCgoKCgoKCg==