This is an R Markdown
Notebook. When you execute code within the notebook, the results appear
beneath the code.
Try executing this chunk by clicking the Run button within
the chunk or by placing your cursor inside it and pressing
Ctrl+Shift+Enter.
# Numerické vektory
## Generovanie vektorov
v1 <- c(2, 4, 6, 8)
v2 <- 1:5 # postupnost 1,2,3,4,5
v3 <- seq(from = 0, to = 1, by = 0.25) # postupnost s krokom 0.25
v4 <- rep(3, times = 5) # 3,3,3,3,3 # 5 clenna postupnost trojak
v5 <- runif(5) # generovanie rovnomerne rozdelenych premennych v intervale [0,1]
v6 <- rnorm(5) # generovanie normalne rozdelenych premennych
v1; v2; v3; v4; v5
Aritmetické operácie s vektormi
v <- c(1, 2, 3, 4)
v + 10 # kazdy prvok vektora zvacsime o 10
v * 2 # kazdy prvok vektora prenasobime 2
(v + 1) / 2
exp(v) # exponencialna funkcia z kazdeho prvku vektora
sum(c(1,2,3),c(1,1,1)) # skalarny sucin - vysledok je skalar
crossprod(c(1,2,3),c(1,1,1)) # skalarny sucin - vysledok je matica 1x1
c(1,2,3)*c(1,1,1) # Hadamardov sucin (sucin zodpovedajucich prvkov vektora)
Matematické operácie s 2 vektormi rovnakého rozmeru
length(c(1,2,3,4,5))
length(v5) #vektor v5 je definovany vyssie
c(1,2,3,4,5) + v5 # pozor, oba vektory musia mat rovnaky rozmer
Indexovanie a výber niektorych prvkov vektora
x <- c(5, 12, 3, 18, 7, 0, 21)
x[1] # indexovanie - novy jedno-prvkovy vektor - prvy prvok vektora x
x[2:4] # novy vektor s druhym az stvrtym prvkom vektora x
x[-1] # novy vektor - vsetky prvky vektora x okrem prvého
x[x > 10] # novy vektor definovany prvkami x vacsimi ako 10
which(x > 10) # ktore prvky zodpovedaju podmienke vacsieho ako 10?
Práca s chýbajúcimi hodnotami
y <- c(1, NA, 3, NA, 5)
is.na(y)
mean(y) # NA
mean(y, na.rm = TRUE) # remove NAs
Základné štatistiky a usporiadanie prvkov vektora podľa
veľkosti
z <- c(10, 3, 5, 8, 2)
mean(z) # priemerna hodnota
sd(z) # standardna odchylka
max(z) # maximalna hodnota
summary(z) # rychly prehlad zakladnych statistik o vektore
sort(z) # rastuce usporiadanie
sort(z, decreasing = TRUE) # klesajuce
#Moje malé cvičenie
set.seed(2025)
# Simuluj 1000 denných log-returnov (normálne rozdelené)
n <- 1000
mu <- 0.0005 # priemerný denný log-return
sigma <- 0.01 # denná sigma
log_returns <- rnorm(n, mean = mu, sd = sigma) # vektor dĺžky n
# Prepočítaj na cenový index (index začína na 100)
price_index <- 100 * cumprod(exp(log_returns)) # vektor cien
# Kumulatívny výnos na konci:
total_return_pct <- (tail(price_index,1) / price_index[1] - 1) * 100
# Drawdown: aktuálny pokles oproti maximu doposiaľ
running_max <- cummax(price_index)
drawdown <- (price_index - running_max) / running_max # negatívne alebo 0, vektor
# Max drawdown a kedy nastal:
max_drawdown <- min(drawdown) # najväčší pokles (negatívna hodnota)
t_idx <- which.min(drawdown) # index najväčšieho drawdownu
t_date <- t_idx # ak chceš, pripíš dátumy
# Výstup
list(
total_return_pct = total_return_pct,
max_drawdown_pct = max_drawdown * 100,
time_of_max_drawdown = t_idx,
head_log_returns = head(log_returns),
head_price_index = head(price_index)
)
Matice
Vytvorenie matíc
m <- matrix(1:12, nrow = 3, ncol = 4) # hodnoty sú zadavane po stlpcoch
m_byrow <- matrix(1:12, nrow = 3, byrow = TRUE) # hodnoty su zadavane po riadkoch
m; m_byrow
Rozmery matice
dim(m) # (rows, cols)
m
Adresovanie prvkov matice
m[1, 2] # riadok 1, stlpec 2
m[ , 3] # vsetky prvky v tretom stlpci - vysledok matica 3x1
m[2, ] # vsetky prvky v druhom riadku - vysledok matica 1*3
m[1:2, 2:3] # podmatica tvorena riadkami 1, 2 a stlpcami 2, 3
Maticové operácie
A <- matrix(c(1,2,3,4), nrow = 2)
B <- matrix(c(5,6,7,8), nrow = 2)
A + B # scitanie matic
A * B # Hadamard product - nasobenie po zodpovedajucich prvkoch
A %*% B # nasobenie matic
t(A) # transpozicia matice A - vymena riadkov a stlpcov
det(A) # determinant matice
solve(A) # inverzia matice (ak je matica regularna - teda inverzia sa da spocitat)
Zlučovanie vektorov do matíc
C <- cbind(1:3, 4:6) # - po stlpcoch
D <- rbind(1:3, 4:6) # - po riadkoch
C; D
Vypočítanie zvolenej štatistiky po riadkoch (stĺpcoch) matice
M <- matrix(1:9, nrow = 3)
M
apply(M, 1, sum) # suma po riadkoch
apply(M, 2, mean) # priemery po stĺpcoch
#Moje malé cvičenie
# Definuj prechodovú maticu pre 3-stavový Markov reťazec (napr. pocasie)
P <- matrix(c(
0.7, 0.2, 0.1, # zo stavu "Sunny" -> (Sunny,Cloudy,Rainy)
0.3, 0.4, 0.3, # zo stavu "Cloudy"
0.2, 0.3, 0.5 # zo stavu "Rainy"
), byrow = TRUE, nrow = 3)
rownames(P) <- colnames(P) <- c("Sunny","Cloudy","Rainy")
P
# 1) n-krokový prechod (napr. pravdepodobnosti za 10 dní)
n <- 10
P_n <- P
for(i in 2:n) P_n <- P_n %*% P # efektívne: P_n = P^n
P_n
# 2) Stacionárne rozdelenie: riešenie π = π P , s podmienkou sum(π)=1
# Metóda: riešime (t(P) - I)' x = 0 alebo použijeme vlastné vektory
eig <- eigen(t(P))
# eigenvalue 1 -> vlastný vektor
idx <- which.min(abs(eig$values - 1))
pi_vec <- Re(eig$vectors[,idx])
pi_vec <- pi_vec / sum(pi_vec) # normalizuj
names(pi_vec) <- c("Sunny","Cloudy","Rainy")
pi_vec
# 3) Simulácia trajektórie Markov reťazca (prečiarkni náhodný chod) - vektorové techniky
set.seed(2025)
T <- 50
states <- character(T)
states[1] <- "Sunny"
for(t in 2:T){
cur <- which(colnames(P) == states[t-1])
states[t] <- sample(colnames(P), 1, prob = P[cur, ])
}
table(states) / T # empirical frequencies
Add a new chunk by clicking the Insert Chunk button on the
toolbar or by pressing Ctrl+Alt+I.
When you save the notebook, an HTML file containing the code and
output will be saved alongside it (click the Preview button or
press Ctrl+Shift+K to preview the HTML file).
The preview shows you a rendered HTML copy of the contents of the
editor. Consequently, unlike Knit, Preview does not
run any R code chunks. Instead, the output of the chunk when it was last
run in the editor is displayed.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKYGBge3J9CiMgTnVtZXJpY2vDqSB2ZWt0b3J5CgojIyBHZW5lcm92YW5pZSB2ZWt0b3JvdgoKYGBge3J9CnYxIDwtIGMoMiwgNCwgNiwgOCkKdjIgPC0gMTo1ICAgICAgICAgICAgICAgICAgIyBwb3N0dXBub3N0IDEsMiwzLDQsNQp2MyA8LSBzZXEoZnJvbSA9IDAsIHRvID0gMSwgYnkgPSAwLjI1KSAgIyBwb3N0dXBub3N0IHMga3Jva29tIDAuMjUKdjQgPC0gcmVwKDMsIHRpbWVzID0gNSkgICAgIyAzLDMsMywzLDMgICMgNSBjbGVubmEgcG9zdHVwbm9zdCB0cm9qYWsKdjUgPC0gcnVuaWYoNSkgICAgICAgICAgICAgIyBnZW5lcm92YW5pZSByb3Zub21lcm5lIHJvemRlbGVueWNoIHByZW1lbm55Y2ggdiBpbnRlcnZhbGUgWzAsMV0KdjYgPC0gcm5vcm0oNSkgICAgICAgICAgICAgIyBnZW5lcm92YW5pZSBub3JtYWxuZSByb3pkZWxlbnljaCBwcmVtZW5ueWNoCnYxOyB2MjsgdjM7IHY0OyB2NQpgYGAKCiMjIEFyaXRtZXRpY2vDqSBvcGVyw6FjaWUgcyB2ZWt0b3JtaQpgYGB7cn0KdiA8LSBjKDEsIDIsIDMsIDQpCnYgKyAxMCAgICAgICAgICAgIyBrYXpkeSBwcnZvayB2ZWt0b3JhIHp2YWNzaW1lIG8gMTAKdiAqIDIgICAgICAgICAgICAjIGthemR5IHBydm9rIHZla3RvcmEgcHJlbmFzb2JpbWUgMgoodiArIDEpIC8gMgpleHAodikgICAgICAgICAgICMgZXhwb25lbmNpYWxuYSBmdW5rY2lhIHoga2F6ZGVobyBwcnZrdSB2ZWt0b3JhCnN1bShjKDEsMiwzKSxjKDEsMSwxKSkgICAgICAgICAgIyBza2FsYXJueSBzdWNpbiAtIHZ5c2xlZG9rIGplIHNrYWxhcgpjcm9zc3Byb2QoYygxLDIsMyksYygxLDEsMSkpICAgICMgc2thbGFybnkgc3VjaW4gLSB2eXNsZWRvayBqZSBtYXRpY2EgMXgxCmMoMSwyLDMpKmMoMSwxLDEpICAgICAgICAgICAgICAgIyBIYWRhbWFyZG92IHN1Y2luIChzdWNpbiB6b2Rwb3ZlZGFqdWNpY2ggcHJ2a292IHZla3RvcmEpCmBgYAoKIyMgTWF0ZW1hdGlja8OpIG9wZXLDoWNpZSBzIDIgdmVrdG9ybWkgcm92bmFrw6lobyByb3ptZXJ1CmBgYHtyfQpsZW5ndGgoYygxLDIsMyw0LDUpKQpsZW5ndGgodjUpICAgICAgICAgICAgI3Zla3RvciB2NSBqZSBkZWZpbm92YW55IHZ5c3NpZQpjKDEsMiwzLDQsNSkgKyB2NSAgICAgIyBwb3pvciwgb2JhIHZla3RvcnkgbXVzaWEgbWF0IHJvdm5ha3kgcm96bWVyCmBgYAoKIyMgSW5kZXhvdmFuaWUgYSB2w71iZXIgbmlla3RvcnljaCBwcnZrb3YgdmVrdG9yYQpgYGB7cn0KeCA8LSBjKDUsIDEyLCAzLCAxOCwgNywgMCwgMjEpCnhbMV0gICAgICAgICAgICMgaW5kZXhvdmFuaWUgLSBub3Z5IGplZG5vLXBydmtvdnkgdmVrdG9yIC0gcHJ2eSBwcnZvayB2ZWt0b3JhIHgKeFsyOjRdICAgICAgICAgIyBub3Z5IHZla3RvciBzIGRydWh5bSBheiBzdHZydHltIHBydmtvbSB2ZWt0b3JhIHgKeFstMV0gICAgICAgICAgIyBub3Z5IHZla3RvciAtIHZzZXRreSBwcnZreSB2ZWt0b3JhIHggb2tyZW0gcHJ2w6lobwp4W3ggPiAxMF0gICAgICAjIG5vdnkgdmVrdG9yIGRlZmlub3ZhbnkgcHJ2a2FtaSB4IHZhY3NpbWkgYWtvIDEwCndoaWNoKHggPiAxMCkgICMga3RvcmUgcHJ2a3kgem9kcG92ZWRhanUgcG9kbWllbmtlIHZhY3NpZWhvIGFrbyAxMD8KYGBgCgojIyBQcsOhY2EgcyBjaMO9YmFqw7pjaW1pIGhvZG5vdGFtaQpgYGB7cn0KeSA8LSBjKDEsIE5BLCAzLCBOQSwgNSkKaXMubmEoeSkKbWVhbih5KSAgICAgICAgICAgICAgICAgIyBOQQptZWFuKHksIG5hLnJtID0gVFJVRSkgICAjIHJlbW92ZSBOQXMKYGBgCgojIyBaw6FrbGFkbsOpIMWhdGF0aXN0aWt5IGEgdXNwb3JpYWRhbmllIHBydmtvdiB2ZWt0b3JhIHBvZMS+YSB2ZcS+a29zdGkKYGBge3J9CnogPC0gYygxMCwgMywgNSwgOCwgMikKbWVhbih6KSAgICAgICAgICAgICAgICAgIyBwcmllbWVybmEgaG9kbm90YQpzZCh6KSAgICAgICAgICAgICAgICAgICMgc3RhbmRhcmRuYSBvZGNoeWxrYQptYXgoeikgICAgICAgICAgICAgICAgICAjIG1heGltYWxuYSBob2Rub3RhCnN1bW1hcnkoeikgICAgICAgICAgICAgICMgcnljaGx5IHByZWhsYWQgemFrbGFkbnljaCBzdGF0aXN0aWsgbyB2ZWt0b3JlCnNvcnQoeikgICAgICAgICAgICAgICAgICMgcmFzdHVjZSB1c3BvcmlhZGFuaWUgCnNvcnQoeiwgZGVjcmVhc2luZyA9IFRSVUUpICAjIGtsZXNhanVjZQpgYGAKCiNNb2plIG1hbMOpIGN2acSNZW5pZQpgYGB7cn0Kc2V0LnNlZWQoMjAyNSkKCiMgU2ltdWx1aiAxMDAwIGRlbm7DvWNoIGxvZy1yZXR1cm5vdiAobm9ybcOhbG5lIHJvemRlbGVuw6kpCm4gPC0gMTAwMAptdSA8LSAwLjAwMDUgICAgICAgICMgcHJpZW1lcm7DvSBkZW5uw70gbG9nLXJldHVybgpzaWdtYSA8LSAwLjAxICAgICAgICMgZGVubsOhIHNpZ21hCmxvZ19yZXR1cm5zIDwtIHJub3JtKG4sIG1lYW4gPSBtdSwgc2QgPSBzaWdtYSkgICAjIHZla3RvciBkxLrFvmt5IG4KCiMgUHJlcG/EjcOtdGFqIG5hIGNlbm92w70gaW5kZXggKGluZGV4IHphxI3DrW5hIG5hIDEwMCkKcHJpY2VfaW5kZXggPC0gMTAwICogY3VtcHJvZChleHAobG9nX3JldHVybnMpKSAgICMgdmVrdG9yIGNpZW4KCiMgS3VtdWxhdMOtdm55IHbDvW5vcyBuYSBrb25jaToKdG90YWxfcmV0dXJuX3BjdCA8LSAodGFpbChwcmljZV9pbmRleCwxKSAvIHByaWNlX2luZGV4WzFdIC0gMSkgKiAxMDAKCiMgRHJhd2Rvd246IGFrdHXDoWxueSBwb2tsZXMgb3Byb3RpIG1heGltdSBkb3Bvc2lhxL4KcnVubmluZ19tYXggPC0gY3VtbWF4KHByaWNlX2luZGV4KQpkcmF3ZG93biA8LSAocHJpY2VfaW5kZXggLSBydW5uaW5nX21heCkgLyBydW5uaW5nX21heCAgICMgbmVnYXTDrXZuZSBhbGVibyAwLCB2ZWt0b3IKCiMgTWF4IGRyYXdkb3duIGEga2VkeSBuYXN0YWw6Cm1heF9kcmF3ZG93biA8LSBtaW4oZHJhd2Rvd24pICAgICAgICAgICMgbmFqdsOkxI3FocOtIHBva2xlcyAobmVnYXTDrXZuYSBob2Rub3RhKQp0X2lkeCA8LSB3aGljaC5taW4oZHJhd2Rvd24pICAgICAgICAgICAjIGluZGV4IG5hanbDpMSNxaFpZWhvIGRyYXdkb3dudQp0X2RhdGUgPC0gdF9pZHggICAgICAgICAgICAgICAgICAgICAgICAjIGFrIGNoY2XFoSwgcHJpcMOtxaEgZMOhdHVteQoKIyBWw71zdHVwCmxpc3QoCiAgdG90YWxfcmV0dXJuX3BjdCA9IHRvdGFsX3JldHVybl9wY3QsCiAgbWF4X2RyYXdkb3duX3BjdCA9IG1heF9kcmF3ZG93biAqIDEwMCwKICB0aW1lX29mX21heF9kcmF3ZG93biA9IHRfaWR4LAogIGhlYWRfbG9nX3JldHVybnMgPSBoZWFkKGxvZ19yZXR1cm5zKSwKICBoZWFkX3ByaWNlX2luZGV4ID0gaGVhZChwcmljZV9pbmRleCkKKQpgYGAKCiMgTWF0aWNlCiMjIFZ5dHZvcmVuaWUgbWF0w61jCmBgYHtyfQptIDwtIG1hdHJpeCgxOjEyLCBucm93ID0gMywgbmNvbCA9IDQpICAgICAgICAgICAgIyBob2Rub3R5IHPDuiB6YWRhdmFuZSBwbyBzdGxwY29jaAptX2J5cm93IDwtIG1hdHJpeCgxOjEyLCBucm93ID0gMywgYnlyb3cgPSBUUlVFKSAgIyBob2Rub3R5IHN1IHphZGF2YW5lIHBvIHJpYWRrb2NoCm07IG1fYnlyb3cKYGBgCgojIyBSb3ptZXJ5IG1hdGljZQpgYGB7cn0KZGltKG0pICAgICAgICAgICAgICAgICAgICMgKHJvd3MsIGNvbHMpCm0KYGBgCgojIyBBZHJlc292YW5pZSBwcnZrb3YgbWF0aWNlCmBgYHtyfQptWzEsIDJdICAgICAgIyByaWFkb2sgMSwgc3RscGVjIDIKbVsgLCAzXSAgICAgICMgdnNldGt5IHBydmt5IHYgdHJldG9tIHN0bHBjaSAtIHZ5c2xlZG9rIG1hdGljYSAzeDEKbVsyLCBdICAgICAgICMgdnNldGt5IHBydmt5IHYgZHJ1aG9tIHJpYWRrdSAtIHZ5c2xlZG9rIG1hdGljYSAxKjMKbVsxOjIsIDI6M10gICMgcG9kbWF0aWNhIHR2b3JlbmEgcmlhZGthbWkgMSwgMiBhIHN0bHBjYW1pIDIsIDMKYGBgCgojIyBNYXRpY292w6kgb3BlcsOhY2llCmBgYHtyfQpBIDwtIG1hdHJpeChjKDEsMiwzLDQpLCBucm93ID0gMikKQiA8LSBtYXRyaXgoYyg1LDYsNyw4KSwgbnJvdyA9IDIpCgpBICsgQiAgICAgICAgIyBzY2l0YW5pZSBtYXRpYwpBICogQiAgICAgICAgIyBIYWRhbWFyZCBwcm9kdWN0IC0gbmFzb2JlbmllIHBvIHpvZHBvdmVkYWp1Y2ljaCBwcnZrb2NoCkEgJSolIEIgICAgICAjIG5hc29iZW5pZSBtYXRpYwp0KEEpICAgICAgICAgIyB0cmFuc3BvemljaWEgbWF0aWNlIEEgLSB2eW1lbmEgcmlhZGtvdiBhIHN0bHBjb3YKZGV0KEEpICAgICAgICMgZGV0ZXJtaW5hbnQgbWF0aWNlCnNvbHZlKEEpICAgICAjIGludmVyemlhIG1hdGljZSAoYWsgamUgbWF0aWNhIHJlZ3VsYXJuYSAtIHRlZGEgaW52ZXJ6aWEgc2EgZGEgc3BvY2l0YXQpCmBgYAoKIyMgWmx1xI1vdmFuaWUgdmVrdG9yb3YgZG8gbWF0w61jIApgYGB7cn0KQyA8LSBjYmluZCgxOjMsIDQ6NikgICAjICAtIHBvIHN0bHBjb2NoIApEIDwtIHJiaW5kKDE6MywgNDo2KSAgICMgIC0gcG8gcmlhZGtvY2ggCkM7IEQKYGBgCgojIyBWeXBvxI3DrXRhbmllIHp2b2xlbmVqIMWhdGF0aXN0aWt5IHBvIHJpYWRrb2NoIChzdMS6cGNvY2gpIG1hdGljZQpgYGB7cn0KTSA8LSBtYXRyaXgoMTo5LCBucm93ID0gMykKTQphcHBseShNLCAxLCBzdW0pICAgIyBzdW1hIHBvIHJpYWRrb2NoCmFwcGx5KE0sIDIsIG1lYW4pICAjIHByaWVtZXJ5IHBvIHN0xLpwY29jaApgYGAKCiNNb2plIG1hbMOpIGN2acSNZW5pZQpgYGB7cn0KIyBEZWZpbnVqIHByZWNob2RvdsO6IG1hdGljdSBwcmUgMy1zdGF2b3bDvSBNYXJrb3YgcmXFpWF6ZWMgKG5hcHIuIHBvY2FzaWUpClAgPC0gbWF0cml4KGMoCiAgMC43LCAwLjIsIDAuMSwgICAjIHpvIHN0YXZ1ICJTdW5ueSIgLT4gKFN1bm55LENsb3VkeSxSYWlueSkKICAwLjMsIDAuNCwgMC4zLCAgICMgem8gc3RhdnUgIkNsb3VkeSIKICAwLjIsIDAuMywgMC41ICAgICMgem8gc3RhdnUgIlJhaW55IgopLCBieXJvdyA9IFRSVUUsIG5yb3cgPSAzKQoKcm93bmFtZXMoUCkgPC0gY29sbmFtZXMoUCkgPC0gYygiU3VubnkiLCJDbG91ZHkiLCJSYWlueSIpClAKCiMgMSkgbi1rcm9rb3bDvSBwcmVjaG9kIChuYXByLiBwcmF2ZGVwb2RvYm5vc3RpIHphIDEwIGRuw60pCm4gPC0gMTAKUF9uIDwtIFAKZm9yKGkgaW4gMjpuKSBQX24gPC0gUF9uICUqJSBQICAgICMgZWZla3TDrXZuZTogUF9uID0gUF5uClBfbgoKIyAyKSBTdGFjaW9uw6FybmUgcm96ZGVsZW5pZTogcmllxaFlbmllIM+AID0gz4AgUCAsIHMgcG9kbWllbmtvdSBzdW0oz4ApPTEKIyBNZXTDs2RhOiByaWXFoWltZSAodChQKSAtIEkpJyB4ID0gMCBhbGVibyBwb3XFvmlqZW1lIHZsYXN0bsOpIHZla3RvcnkKZWlnIDwtIGVpZ2VuKHQoUCkpCiMgZWlnZW52YWx1ZSAxIC0+IHZsYXN0bsO9IHZla3RvcgppZHggPC0gd2hpY2gubWluKGFicyhlaWckdmFsdWVzIC0gMSkpCnBpX3ZlYyA8LSBSZShlaWckdmVjdG9yc1ssaWR4XSkKcGlfdmVjIDwtIHBpX3ZlYyAvIHN1bShwaV92ZWMpICAgIyBub3JtYWxpenVqCm5hbWVzKHBpX3ZlYykgPC0gYygiU3VubnkiLCJDbG91ZHkiLCJSYWlueSIpCnBpX3ZlYwoKIyAzKSBTaW11bMOhY2lhIHRyYWpla3TDs3JpZSBNYXJrb3YgcmXFpWF6Y2EgKHByZcSNaWFya25pIG7DoWhvZG7DvSBjaG9kKSAtIHZla3Rvcm92w6kgdGVjaG5pa3kKc2V0LnNlZWQoMjAyNSkKVCA8LSA1MApzdGF0ZXMgPC0gY2hhcmFjdGVyKFQpCnN0YXRlc1sxXSA8LSAiU3VubnkiCmZvcih0IGluIDI6VCl7CiAgY3VyIDwtIHdoaWNoKGNvbG5hbWVzKFApID09IHN0YXRlc1t0LTFdKQogIHN0YXRlc1t0XSA8LSBzYW1wbGUoY29sbmFtZXMoUCksIDEsIHByb2IgPSBQW2N1ciwgXSkKfQp0YWJsZShzdGF0ZXMpIC8gVCAgICMgZW1waXJpY2FsIGZyZXF1ZW5jaWVzCmBgYAoKCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDdHJsK0FsdCtJKi4KCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLgoKVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLgo=