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