1 Zakład Bioinformatyki, Instytut Informatyki, Uniwersytet w Białymstoku

Correspondence: Jarosław Kotowicz <>

1 Przygotowanie do pracy

1.1 Instalacja oprogramowania

  1. R strona domowa www.r-project.org
  • wybieramy download
  • wybieramy mirror np. serwer niemiecki
  • ściągamy plik instalacyjny
  1. Rstudio (GUI) dla R RStudio
  • należy pobrać system opensource
  1. Przeglądarka plików pdf natywna dla RStudio (pod Windows) sumatra (opensource)
  1. Instalujemy w kolejności R, Sumatra, RStudio

1.2 Przygotowanie do pracy

  1. W katalogu dokumenty tworzymy folder (nazwa zgodnie z zasadą Inf_xxxxx, gdzie xxxxx to numer albumu).
  2. Uruchamiamy RSudio
  3. Zachowujemy porządek. Tworzymy nowy projekt
  • Files -> New Project… -> Existing Directory -> Browse… i wybieramy folder, który utworzyliśmy oraz zaznaczamy Open in new session.
    Uwaga: Zawsze na koniec pracy/zajęć należy zamknąć projekt. Files -> Close Project
    Uwaga: Zawsze na początku pracy/zajęć należy otworzyć projekt. Files -> Recent Projects i wybrać swój (będzie miał on taką nazwę, jak nasz katalog).
  1. Dostosowujem RSudio do następujących wymagań:
  • Tools -> Project Options ->
    1. Code Editing -> Text encoding wybór UTF-8
    2. Sweave -> PDF Generaion wybór knitr
      Uwaga: Jeżeli chcemy korzystać z TeX (LaTeX), to musimy mieć zaistalowny system/program np. MikTeX.
  • Tools -> Global Options ->
    1. Appearance wybór wyglądu RSudion np. ambiance (ciemny motyw).

  1. W domu instalujemy konieczne biblioteki R nazywane package
  • dolne prawe okienko - okno Packages -> Install wpisujemy tidyverse
  1. Otwieramy pliki
  • R Script: Files -> New File -> R Script
  • R Notebook: Files -> New File -> R Notebook
  • R Markdown: Files -> New File -> R Markdown i wybieramy rodzaj dokumentu np. Document lub Presentation.
    Uwaga: Wszystkie pliki podpisujemy zgodnie ze schematem Inf_xxxxx.

  1. Będziemy zawsze pracować albo w pliku skryptowym R albo w R Notebook.
  2. Informacje dla pliku skryptowego
  • wywołanie aktualnej linii w konsoli CTRL+ENTER
  • odwołanie się do funkcji z danej biblioteki package::function np. stats::filter
  • podczytanie biblioteki library(nazwa biblioteki)
  • znak komentarza hashtag tzn. #

2 Laboratorium

2.1 Ostrzeżenie o działaniach na liczbach zmiennoprzecinkowych

0.1 * 0.1 == 0.01
[1] FALSE

2.2 Typ liczbowy double (liczby zmiennoprzecinkowe)

x <- 1
x
[1] 1
v1 <- c(1, 25, 7)
v1
[1]  1 25  7

2.2.1 Typ, mode i klasa

typeof(x)
[1] "double"
mode(x)
[1] "numeric"
class(x)
[1] "numeric"

2.3 Typ logiczny logical

v2 <- c(TRUE, FALSE)
v2
[1]  TRUE FALSE
v3 <- c(T, F)
v3
[1]  TRUE FALSE

2.3.1 Typ, mode i klasa

typeof(v2)
[1] "logical"
class(v2)
[1] "logical"
mode(v2)
[1] "logical"

2.3.2 Sprawdzenie typu

is.logical(v2)
[1] TRUE
is.logical(x)
[1] FALSE

2.4 Typ integer (liczby całkowite)

z <- 1L

2.4.1 Typ, mode i klasa

typeof(z)
[1] "integer"
class(z)
[1] "integer"
mode(z)
[1] "numeric"

2.4.2 Działania na wektorach

v1 + x
[1]  2 26  8
v4 <- c(1:2)
v1 + v4
długość dłuższego obiektu nie jest wielokrotnością długości krótszego obiektu
[1]  2 27  8
v2 / 2
[1] 0.5 0.0
2 * TRUE
[1] 2
2 * FALSE
[1] 0
3 == TRUE
[1] FALSE

2.5 Typ znakowy character

z <- c("napis", "to", "ja")
z
[1] "napis" "to"    "ja"   

2.5.1 Łączenie napisów

paste(z, collapse = " ")
[1] "napis to ja"

2.6 Zmienne czynnikowe (kategorialne)

f1 <- factor(c("zły", "dobry"))
f1
[1] zły   dobry
Levels: dobry zły

2.6.1 Typ, mode i klasa

typeof(f1)
[1] "integer"
mode(f1)
[1] "numeric"
class(f1)
[1] "factor"

2.7 Zmienne czynnikowe (uporządkowane)

f2 <- factor(c("zły", "dobry"), ordered = TRUE)
f2
[1] zły   dobry
Levels: dobry < zły

2.7.1 Typ, mode i klasa

typeof(f2)
[1] "integer"
mode(f2)
[1] "numeric"
class(f2)
[1] "ordered" "factor" 

2.7.2 Kolejność uporządkowania

f3 <- factor(c("zły", "dobry"), levels = c("zły", "dobry"), ordered = TRUE)
f3
[1] zły   dobry
Levels: zły < dobry
l1 <- list(litery = letters, cyfry = 0:9, logiczne = c(TRUE, FALSE))
l1
$litery
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"

$cyfry
 [1] 0 1 2 3 4 5 6 7 8 9

$logiczne
[1]  TRUE FALSE

2.7.3 Typ, mode i klasa

typeof(l1)
[1] "list"
mode(l1)
[1] "list"
class(l1)
[1] "list"

2.7.4 Typ atomowy i rekursywny

is.atomic(l1)
[1] FALSE
is.recursive(l1)
[1] TRUE

2.8 Listy

l2 <- list(l1, imiona = c("Adam", "Ewa"), nazwiska = c("Kowalski", "Nowak"))
l2
[[1]]
[[1]]$litery
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"

[[1]]$cyfry
 [1] 0 1 2 3 4 5 6 7 8 9

[[1]]$logiczne
[1]  TRUE FALSE


$imiona
[1] "Adam" "Ewa" 

$nazwiska
[1] "Kowalski" "Nowak"   

2.9 Tablice wielowymiarowe

a1 <- array(rnorm(100), c(10, 5, 2))
a1
, , 1

             [,1]       [,2]       [,3]        [,4]        [,5]
 [1,]  1.38386301 -0.5291288 -0.3879402 -0.25278199 -0.15617925
 [2,]  0.41036156  0.5319073  1.8455044  0.26837547  1.13910214
 [3,]  0.04684133  0.2285078 -0.1272259 -0.63439106  0.50874156
 [4,]  0.53981438  0.1644592  1.4775694 -0.89615459  0.11810905
 [5,]  0.75953487  0.4690186  1.9153122  0.37289431  1.01342012
 [6,]  1.68393299 -1.7487418  0.7112948  0.68004825 -0.16661938
 [7,] -2.11945092  1.5572583  0.4054456 -0.11984787  0.56231813
 [8,]  0.54284224 -1.8590479  0.1164868  0.44174336 -0.22827804
 [9,] -1.34492388  1.2664027 -1.3167933  0.02160616  0.04368969
[10,] -0.28355945 -0.3552558 -0.1029444 -0.57871159 -0.38364071

, , 2

            [,1]        [,2]        [,3]       [,4]        [,5]
 [1,]  1.4539201  1.64063372  0.52201056 -1.3989100 -0.14317466
 [2,]  0.6639905  0.35720029 -0.47125299 -0.7600393  0.08980089
 [3,] -1.2119809 -1.71161006  0.60703332  0.9986382 -0.10565636
 [4,] -1.1593771 -0.14008148  0.18827706  0.4306923  0.94462658
 [5,]  1.1886310  0.02925152  0.80984226  0.6909916 -1.51266805
 [6,]  0.5368452 -0.37967244 -0.86874601 -1.5706242  0.41821365
 [7,]  2.0893560  0.53252561  0.64773414  1.4461651 -0.33572958
 [8,]  0.3612782 -0.32884538 -0.10814663  1.6454971  0.18524837
 [9,]  0.4805084  0.57921196 -1.06489700  0.9362112 -0.90597064
[10,] -0.6519389 -1.87521890  0.01973623 -0.2948808  0.18746580

2.9.1 Typ, mode i klasa

typeof(a1)
[1] "double"
mode(a1)
[1] "numeric"
class(a1)
[1] "array"

2.10 Macierze i wybrane operacje na nich

m1 <- matrix(rnorm(100), ncol = 10, nrow = 10)
m1
             [,1]       [,2]        [,3]        [,4]        [,5]       [,6]        [,7]       [,8]        [,9]       [,10]
 [1,] -0.37821449 -0.1518669  1.00046581  0.07565567 -0.88222732 -1.3789073  1.56487967 -0.1013237  1.12998917 -0.02642563
 [2,]  1.92064707  0.1345935 -0.01050935  0.50974430 -0.44559790 -1.3152171  0.04956862  0.7814998 -2.21515807 -1.49686329
 [3,] -0.53099172 -1.2601387 -0.14822469  0.76105837 -1.36320851  1.0576217 -1.98593563  0.2456150 -0.68280088 -0.83517938
 [4,] -0.12465193  1.1429696  2.47718043 -0.24174876 -2.02076798 -0.4202247 -1.18895750 -0.1156164 -1.24545437 -0.55813466
 [5,] -0.78185244 -0.1224754 -0.45427055  0.16992759  0.56778292  1.8874210  0.48647843  0.7741051  0.38538470 -1.10222541
 [6,]  0.81679687  0.9689758  0.58929564  0.92260083  1.78742116 -0.8899874  0.29356212  0.8202191 -0.85326371 -0.25197820
 [7,]  0.40980333 -0.8940717 -0.50425854 -0.72904199 -0.08027053 -0.6676902  0.31518259  0.6444782  0.83744764 -1.06517821
 [8,] -0.80164231  0.1804351  1.45521736  1.07148373 -0.67298531  0.3987343 -0.85489285 -1.4448775 -0.09042728  0.15774196
 [9,]  0.02706468  0.4692385  0.12662650 -1.18959571  0.78837063 -0.0802130  0.57580836  0.9524794 -1.17914212  0.55757489
[10,] -0.91424190  0.3165340 -0.32293676  0.87819771 -0.85628815  2.0632735 -1.13635788 -0.9388210 -1.03002159 -0.14659916

2.10.1 Typ, mode i klasa

typeof(m1)
[1] "double"
mode(m1)
[1] "numeric"
class(m1)
[1] "matrix" "array" 

2.10.2 Wybrane operacje na elemetach macierzy

m2 <- abs(m1)
m2
            [,1]      [,2]       [,3]       [,4]       [,5]      [,6]       [,7]      [,8]       [,9]      [,10]
 [1,] 0.37821449 0.1518669 1.00046581 0.07565567 0.88222732 1.3789073 1.56487967 0.1013237 1.12998917 0.02642563
 [2,] 1.92064707 0.1345935 0.01050935 0.50974430 0.44559790 1.3152171 0.04956862 0.7814998 2.21515807 1.49686329
 [3,] 0.53099172 1.2601387 0.14822469 0.76105837 1.36320851 1.0576217 1.98593563 0.2456150 0.68280088 0.83517938
 [4,] 0.12465193 1.1429696 2.47718043 0.24174876 2.02076798 0.4202247 1.18895750 0.1156164 1.24545437 0.55813466
 [5,] 0.78185244 0.1224754 0.45427055 0.16992759 0.56778292 1.8874210 0.48647843 0.7741051 0.38538470 1.10222541
 [6,] 0.81679687 0.9689758 0.58929564 0.92260083 1.78742116 0.8899874 0.29356212 0.8202191 0.85326371 0.25197820
 [7,] 0.40980333 0.8940717 0.50425854 0.72904199 0.08027053 0.6676902 0.31518259 0.6444782 0.83744764 1.06517821
 [8,] 0.80164231 0.1804351 1.45521736 1.07148373 0.67298531 0.3987343 0.85489285 1.4448775 0.09042728 0.15774196
 [9,] 0.02706468 0.4692385 0.12662650 1.18959571 0.78837063 0.0802130 0.57580836 0.9524794 1.17914212 0.55757489
[10,] 0.91424190 0.3165340 0.32293676 0.87819771 0.85628815 2.0632735 1.13635788 0.9388210 1.03002159 0.14659916
m3 <- m1^2
m3
              [,1]       [,2]         [,3]        [,4]        [,5]        [,6]        [,7]       [,8]        [,9]       [,10]
 [1,] 0.1430461975 0.02306355 1.0009318356 0.005723781 0.778325044 1.901385309 2.448848383 0.01026649 1.276875534 0.000698314
 [2,] 3.6888851738 0.01811542 0.0001104463 0.259839255 0.198557491 1.729795985 0.002457048 0.61074197 4.906925271 2.240599720
 [3,] 0.2819522087 1.58794951 0.0219705581 0.579209843 1.858337437 1.118563659 3.943940313 0.06032672 0.466217041 0.697524595
 [4,] 0.0155381041 1.30637940 6.1364228617 0.058442463 4.083503222 0.176588781 1.413619932 0.01336715 1.551156589 0.311514294
 [5,] 0.6112932308 0.01500023 0.2063617297 0.028875386 0.322377440 3.562358072 0.236661258 0.59923878 0.148521369 1.214900851
 [6,] 0.6671571229 0.93891410 0.3472693541 0.851192300 3.194874408 0.792077485 0.086178716 0.67275945 0.728058951 0.063493012
 [7,] 0.1679387664 0.79936412 0.2542766704 0.531502229 0.006443359 0.445810205 0.099340063 0.41535212 0.701318558 1.134604626
 [8,] 0.6426303969 0.03255682 2.1176575511 1.148077381 0.452909233 0.158989050 0.730841787 2.08767099 0.008177094 0.024882525
 [9,] 0.0007324967 0.22018479 0.0160342705 1.415137963 0.621528245 0.006434126 0.331555273 0.90721694 1.390376149 0.310889758
[10,] 0.8358382481 0.10019375 0.1042881497 0.771231219 0.733229401 4.257097701 1.291309236 0.88138486 1.060944478 0.021491315
m4 <- m1 * m1
m4
              [,1]       [,2]         [,3]        [,4]        [,5]        [,6]        [,7]       [,8]        [,9]       [,10]
 [1,] 0.1430461975 0.02306355 1.0009318356 0.005723781 0.778325044 1.901385309 2.448848383 0.01026649 1.276875534 0.000698314
 [2,] 3.6888851738 0.01811542 0.0001104463 0.259839255 0.198557491 1.729795985 0.002457048 0.61074197 4.906925271 2.240599720
 [3,] 0.2819522087 1.58794951 0.0219705581 0.579209843 1.858337437 1.118563659 3.943940313 0.06032672 0.466217041 0.697524595
 [4,] 0.0155381041 1.30637940 6.1364228617 0.058442463 4.083503222 0.176588781 1.413619932 0.01336715 1.551156589 0.311514294
 [5,] 0.6112932308 0.01500023 0.2063617297 0.028875386 0.322377440 3.562358072 0.236661258 0.59923878 0.148521369 1.214900851
 [6,] 0.6671571229 0.93891410 0.3472693541 0.851192300 3.194874408 0.792077485 0.086178716 0.67275945 0.728058951 0.063493012
 [7,] 0.1679387664 0.79936412 0.2542766704 0.531502229 0.006443359 0.445810205 0.099340063 0.41535212 0.701318558 1.134604626
 [8,] 0.6426303969 0.03255682 2.1176575511 1.148077381 0.452909233 0.158989050 0.730841787 2.08767099 0.008177094 0.024882525
 [9,] 0.0007324967 0.22018479 0.0160342705 1.415137963 0.621528245 0.006434126 0.331555273 0.90721694 1.390376149 0.310889758
[10,] 0.8358382481 0.10019375 0.1042881497 0.771231219 0.733229401 4.257097701 1.291309236 0.88138486 1.060944478 0.021491315

2.10.3 Wybrane operacje na macierzach

m5 <- m1 %*% m1
colSums(m4)
 [1]  7.055012  5.041722 10.205323  5.649232 12.250085 14.149100 10.584752  6.258325 12.238571  6.020599
rowSums(m4)
 [1]  7.589164 13.656028 10.615992 15.066533  6.945588  8.341975  4.555951  7.404393  5.220090 10.057008
colMeans(m4)
 [1] 0.7055012 0.5041722 1.0205323 0.5649232 1.2250085 1.4149100 1.0584752 0.6258325 1.2238571 0.6020599
rowMeans(m4)
 [1] 0.7589164 1.3656028 1.0615992 1.5066533 0.6945588 0.8341975 0.4555951 0.7404393 0.5220090 1.0057008

2.11 Ramki danych

df1 <- data.frame(lzp = rnorm(10), 
                  lc = sample(1:100, 10), 
                  wl = sample(c(TRUE, FALSE), 10, replace = TRUE), 
                  zf = sample(factor(c("K", "M")), 10, replace = TRUE))
df1

2.11.1 Podsumowanie

summary(df1)
      lzp                lc            wl          zf   
 Min.   :-1.5075   Min.   :12.00   Mode :logical   K:6  
 1st Qu.:-0.9073   1st Qu.:42.50   FALSE:4         M:4  
 Median :-0.3529   Median :63.00   TRUE :6              
 Mean   :-0.3423   Mean   :56.10                        
 3rd Qu.: 0.0518   3rd Qu.:75.25                        
 Max.   : 1.2415   Max.   :93.00                        
LS0tDQp0aXRsZTogIk1ldG9keSBwcm9iYWJpbGlzdHljem5lIGkgc3RhdHlzdHlrYSAtIGxhYm9yYXRvcml1bSAoZ3J1cGEgMSkiDQphdXRob3I6DQotIEphcm9zxYJhdyBLb3Rvd2ljejoNCiAgICBjb3JyZXNwb25kZW5jZTogbm8NCiAgICBlbWFpbDogai5rb3Rvd2ljekB1d2IuZWR1LnBsDQogICAgaW5zdGl0dXRlOiBJSVV3Qg0KZGF0ZTogIjQgbWFyY2EgMjAyMSINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgaGlnaGxpZ2h0OiBoYWRkb2NrDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBwYW5kb2NfYXJnczoNCiAgICAtIC0tbHVhLWZpbHRlcj1zY2hvbGFybHktbWV0YWRhdGEubHVhDQogICAgLSAtLWx1YS1maWx0ZXI9YXV0aG9yLWluZm8tYmxvY2tzLmx1YQ0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIHRvYzogeWVzDQppbnN0aXR1dGU6DQotIElJVXdCOiBaYWvFgmFkIEJpb2luZm9ybWF0eWtpLCBJbnN0eXR1dCBJbmZvcm1hdHlraSwgVW5pd2Vyc3l0ZXQgdyBCaWHFgnltc3Rva3UNCmNzbDogYmlnLWRhdGEtYW5kLWluZm9ybWF0aW9uLWFuYWx5dGljcy5jc2wNCmFsd2F5c19hbGxvd19odG1sOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIFByenlnb3Rvd2FuaWUgZG8gcHJhY3kNCg0KIyMgSW5zdGFsYWNqYSBvcHJvZ3JhbW93YW5pYQ0KMS4gUiAgW3N0cm9uYSBkb21vd2Egd3d3LnItcHJvamVjdC5vcmddKGh0dHBzOi8vd3d3LnItcHJvamVjdC5vcmcpDQogIC0gd3liaWVyYW15IGRvd25sb2FkDQogIC0gd3liaWVyYW15IG1pcnJvciBucC4gc2Vyd2VyIG5pZW1pZWNraQ0KICAtIMWbY2nEhWdhbXkgcGxpayBpbnN0YWxhY3lqbnkNCjIuIFJzdHVkaW8gKEdVSSkgZGxhIFIgW1JTdHVkaW9dKGh0dHBzOi8vd3d3LnIuc3R1ZGlvLmNvbS8pDQogIC0gbmFsZcW8eSBwb2JyYcSHIHN5c3RlbSBvcGVuc291cmNlDQozLiBQcnplZ2zEhWRhcmthIHBsaWvDs3cgKipwZGYqKiBuYXR5d25hIGRsYSBSU3R1ZGlvIChwb2QgV2luZG93cykgKipzdW1hdHJhKiogKG9wZW5zb3VyY2UpDQogIC0gcG9iaWVyYW15IHplIHN0cm9ueSBbU3VtYXRyYV0oaHR0cHM6Ly93d3cuc3VtYXRyYXBkZnJlYWRlci5vcmcvZnJlZS1wZGYtcmVhZGVyLmh0bWwpDQo0LiBJbnN0YWx1amVteSB3IGtvbGVqbm/Fm2NpIFIsIFN1bWF0cmEsIFJTdHVkaW8gIA0KICANCiMjIFByenlnb3Rvd2FuaWUgZG8gcHJhY3kNCjEuIFcga2F0YWxvZ3UgZG9rdW1lbnR5IHR3b3J6eW15IGZvbGRlciAobmF6d2EgemdvZG5pZSB6IHphc2FkxIUgKipJbmZfeHh4eHgqKiwgZ2R6aWUgKnh4eHh4KiB0byBudW1lciBhbGJ1bXUpLg0KMi4gVXJ1Y2hhbWlhbXkgKlJTdWRpbyoNCjMuIFphY2hvd3VqZW15IHBvcnrEhWRlay4gVHdvcnp5bXkgbm93eSBwcm9qZWt0DQogIC0gKkZpbGVzKiAtPiAqTmV3IFByb2plY3QuLi4qIC0+ICpFeGlzdGluZyBEaXJlY3RvcnkqIC0+ICpCcm93c2UuLi4qIGkgd3liaWVyYW15IGZvbGRlciwga3TDs3J5IHV0d29yenlsacWbbXkgb3JheiB6YXpuYWN6YW15ICpPcGVuIGluIG5ldyBzZXNzaW9uKi4gPEJSPg0KPHNwYW4gc3R5bGUgPSAiY29sb3I6ICByZWQiPiBVd2FnYTogWmF3c3plIG5hIGtvbmllYyBwcmFjeS96YWrEmcSHIG5hbGXFvHkgemFta27EhcSHIHByb2pla3QuPC9zcGFuPiANCiAgKkZpbGVzKiAtPiAqQ2xvc2UgUHJvamVjdCogIDxCUj4NCjxzcGFuIHN0eWxlID0gImNvbG9yOiAgcmVkIj4gVXdhZ2E6IFphd3N6ZSBuYSBwb2N6xIV0a3UgcHJhY3kvemFqxJnEhyBuYWxlxbx5IG90d29yennEhyBwcm9qZWt0Ljwvc3Bhbj4gDQogICpGaWxlcyogLT4gKlJlY2VudCBQcm9qZWN0cyogIGkgd3licmHEhyBzd8OzaiAoKmLEmWR6aWUgbWlhxYIgb24gdGFrxIUgbmF6d8SZLCBqYWsgbmFzeiBrYXRhbG9nKikuDQo0LiBEb3N0b3Nvd3VqZW0gKlJTdWRpbyogZG8gbmFzdMSZcHVqxIVjeWNoIHd5bWFnYcWEOg0KICAtICAqVG9vbHMqIC0+ICAqUHJvamVjdCBPcHRpb25zKiAtPiANCiAgPG9sPg0KICAgIDxsaT4gKkNvZGUgRWRpdGluZyogLT4gICpUZXh0IGVuY29kaW5nKiB3eWLDs3IgKipVVEYtOCoqIDwvbGk+DQogICAgPGxpPiAqU3dlYXZlKiAtPiAgKlBERiBHZW5lcmFpb24qICB3eWLDs3IgKiprbml0cioqPEJSPg0KPHNwYW4gc3R5bGUgPSAiY29sb3I6ICByZWQiPiBVd2FnYTogSmXFvGVsaSBjaGNlbXkga29yenlzdGHEhyB6IFRlWCAoTGFUZVgpLCB0byBtdXNpbXkgbWllxIcgemFpc3RhbG93bnkgc3lzdGVtL3Byb2dyYW0gbnAuIE1pa1RlWC48L3NwYW4+IDwvbGk+DQogIDwvb2w+DQogIC0gICpUb29scyogLT4gICpHbG9iYWwgT3B0aW9ucyogLT4NCiAgPG9sPg0KICAgIDxsaT4gKkFwcGVhcmFuY2UqIHd5YsOzciB3eWdsxIVkdSAqUlN1ZGlvbiogbnAuICoqYW1iaWFuY2UqKiAoKmNpZW1ueSBtb3R5dyopLiA8L2xpPg0KICA8L29sPg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQo0LiBXIGRvbXUgaW5zdGFsdWplbXkga29uaWVjem5lIGJpYmxpb3Rla2kgKipSKiogbmF6eXdhbmUgKipwYWNrYWdlKioNCiAgLSBkb2xuZSBwcmF3ZSBva2llbmtvIC0gb2tubyAqUGFja2FnZXMqIC0+ICpJbnN0YWxsKiAgd3Bpc3VqZW15ICoqdGlkeXZlcnNlKioNCjUuIE90d2llcmFteSBwbGlraSANCiAgLSAqKlIgU2NyaXB0Kio6ICpGaWxlcyogLT4gKk5ldyBGaWxlKiAtPiAqUiBTY3JpcHQqDQogIC0gKipSIE5vdGVib29rKio6ICAqRmlsZXMqIC0+ICpOZXcgRmlsZSogLT4gKlIgTm90ZWJvb2sqDQogIC0gKipSIE1hcmtkb3duKio6ICpGaWxlcyogLT4gKk5ldyBGaWxlKiAtPiAqUiBNYXJrZG93biogaSB3eWJpZXJhbXkgcm9kemFqIGRva3VtZW50dSBucC4gKkRvY3VtZW50KiBsdWIgKlByZXNlbnRhdGlvbiouICAgPEJSPg0KPHNwYW4gc3R5bGUgPSAiY29sb3I6ICByZWQiPiBVd2FnYTogV3N6eXN0a2llIHBsaWtpIHBvZHBpc3VqZW15IHpnb2RuaWUgemUgc2NoZW1hdGVtICpJbmZfeHh4eHgqLjwvc3Bhbj4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KNi4gQsSZZHppZW15IHphd3N6ZSBwcmFjb3dhxIcgYWxibyB3IHBsaWt1IHNrcnlwdG93eW0gKlIqIGFsYm8gdyAqUiBOb3RlYm9vayouDQo3LiBJbmZvcm1hY2plIGRsYSBwbGlrdSBza3J5cHRvd2VnbyANCiAgLSB3eXdvxYJhbmllIGFrdHVhbG5laiBsaW5paSB3IGtvbnNvbGkgKkNUUkwrRU5URVIqDQogIC0gb2R3b8WCYW5pZSBzacSZIGRvIGZ1bmtjamkgeiBkYW5laiBiaWJsaW90ZWtpICpwYWNrYWdlOjpmdW5jdGlvbiogbnAuICpzdGF0czo6ZmlsdGVyKg0KICAtIHBvZGN6eXRhbmllIGJpYmxpb3Rla2kgKmxpYnJhcnkobmF6d2EgYmlibGlvdGVraSkqDQogIC0gem5hayBrb21lbnRhcnphIGhhc2h0YWcgdHpuLiAjDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgTGFib3JhdG9yaXVtDQoNCiMjIE9zdHJ6ZcW8ZW5pZSBvIGR6aWHFgmFuaWFjaCBuYSBsaWN6YmFjaCB6bWllbm5vcHJ6ZWNpbmtvd3ljaA0KYGBge3J9DQowLjEgKiAwLjEgPT0gMC4wMQ0KYGBgDQoNCiMjIFR5cCBsaWN6Ym93eSAqZG91YmxlKiAobGljemJ5IHptaWVubm9wcnplY2lua293ZSkNCmBgYHtyfQ0KeCA8LSAxDQp4DQpgYGANCg0KYGBge3J9DQp2MSA8LSBjKDEsIDI1LCA3KQ0KdjENCmBgYA0KIyMjIFR5cCwgbW9kZSBpIGtsYXNhDQpgYGB7cn0NCnR5cGVvZih4KQ0KbW9kZSh4KQ0KY2xhc3MoeCkNCmBgYA0KIyMgVHlwIGxvZ2ljem55ICpsb2dpY2FsKiANCmBgYHtyfQ0KdjIgPC0gYyhUUlVFLCBGQUxTRSkNCnYyDQpgYGANCg0KYGBge3J9DQp2MyA8LSBjKFQsIEYpDQp2Mw0KYGBgDQojIyMgVHlwLCBtb2RlIGkga2xhc2ENCmBgYHtyfQ0KdHlwZW9mKHYyKQ0KY2xhc3ModjIpDQptb2RlKHYyKQ0KYGBgDQojIyMgU3ByYXdkemVuaWUgdHlwdQ0KYGBge3J9DQppcy5sb2dpY2FsKHYyKQ0KaXMubG9naWNhbCh4KQ0KYGBgDQojIyBUeXAgKmludGVnZXIqICAobGljemJ5IGNhxYJrb3dpdGUpDQpgYGB7cn0NCnogPC0gMUwNCmBgYA0KIyMjIFR5cCwgbW9kZSBpIGtsYXNhDQpgYGB7cn0NCnR5cGVvZih6KQ0KY2xhc3MoeikNCm1vZGUoeikNCmBgYA0KIyMjIER6aWHFgmFuaWEgbmEgd2VrdG9yYWNoDQpgYGB7cn0NCnYxICsgeA0KYGBgDQoNCmBgYHtyfQ0KdjQgPC0gYygxOjIpDQp2MSArIHY0DQpgYGANCg0KYGBge3J9DQp2MiAvIDINCmBgYA0KDQpgYGB7cn0NCjIgKiBUUlVFDQoyICogRkFMU0UNCjMgPT0gVFJVRQ0KYGBgDQojIyBUeXAgem5ha293eSAqY2hhcmFjdGVyKg0KYGBge3J9DQp6IDwtIGMoIm5hcGlzIiwgInRvIiwgImphIikNCnoNCmBgYA0KIyMjIMWBxIVjemVuaWUgbmFwaXPDs3cNCmBgYHtyfQ0KcGFzdGUoeiwgY29sbGFwc2UgPSAiICIpDQpgYGANCiMjIFptaWVubmUgY3p5bm5pa293ZSAoa2F0ZWdvcmlhbG5lKQ0KYGBge3J9DQpmMSA8LSBmYWN0b3IoYygiesWCeSIsICJkb2JyeSIpKQ0KZjENCmBgYA0KIyMjIFR5cCwgbW9kZSBpIGtsYXNhDQpgYGB7cn0NCnR5cGVvZihmMSkNCm1vZGUoZjEpDQpjbGFzcyhmMSkNCmBgYA0KIyMgWm1pZW5uZSBjenlubmlrb3dlICh1cG9yesSFZGtvd2FuZSkNCmBgYHtyfQ0KZjIgPC0gZmFjdG9yKGMoInrFgnkiLCAiZG9icnkiKSwgb3JkZXJlZCA9IFRSVUUpDQpmMg0KYGBgDQojIyMgVHlwLCBtb2RlIGkga2xhc2ENCmBgYHtyfQ0KdHlwZW9mKGYyKQ0KbW9kZShmMikNCmNsYXNzKGYyKQ0KYGBgDQojIyMgS29sZWpub8WbxIcgdXBvcnrEhWRrb3dhbmlhDQpgYGB7cn0NCmYzIDwtIGZhY3RvcihjKCJ6xYJ5IiwgImRvYnJ5IiksIGxldmVscyA9IGMoInrFgnkiLCAiZG9icnkiKSwgb3JkZXJlZCA9IFRSVUUpDQpmMw0KYGBgDQoNCmBgYHtyfQ0KbDEgPC0gbGlzdChsaXRlcnkgPSBsZXR0ZXJzLCBjeWZyeSA9IDA6OSwgbG9naWN6bmUgPSBjKFRSVUUsIEZBTFNFKSkNCmwxDQpgYGANCiMjIyBUeXAsIG1vZGUgaSBrbGFzYQ0KYGBge3J9DQp0eXBlb2YobDEpDQptb2RlKGwxKQ0KY2xhc3MobDEpDQpgYGANCiMjIyBUeXAgYXRvbW93eSBpIHJla3Vyc3l3bnkNCmBgYHtyfQ0KaXMuYXRvbWljKGwxKQ0KaXMucmVjdXJzaXZlKGwxKQ0KYGBgDQojIyBMaXN0eQ0KYGBge3J9DQpsMiA8LSBsaXN0KGwxLCBpbWlvbmEgPSBjKCJBZGFtIiwgIkV3YSIpLCBuYXp3aXNrYSA9IGMoIktvd2Fsc2tpIiwgIk5vd2FrIikpDQpsMg0KYGBgDQojIyBUYWJsaWNlIHdpZWxvd3ltaWFyb3dlDQpgYGB7cn0NCmExIDwtIGFycmF5KHJub3JtKDEwMCksIGMoMTAsIDUsIDIpKQ0KYTENCmBgYA0KIyMjIFR5cCwgbW9kZSBpIGtsYXNhDQpgYGB7cn0NCnR5cGVvZihhMSkNCm1vZGUoYTEpDQpjbGFzcyhhMSkNCmBgYA0KDQojIyBNYWNpZXJ6ZSBpIHd5YnJhbmUgb3BlcmFjamUgbmEgbmljaA0KYGBge3J9DQptMSA8LSBtYXRyaXgocm5vcm0oMTAwKSwgbmNvbCA9IDEwLCBucm93ID0gMTApDQptMQ0KYGBgDQojIyMgVHlwLCBtb2RlIGkga2xhc2ENCmBgYHtyfQ0KdHlwZW9mKG0xKQ0KbW9kZShtMSkNCmNsYXNzKG0xKQ0KYGBgDQojIyMgV3licmFuZSBvcGVyYWNqZSBuYSBlbGVtZXRhY2ggbWFjaWVyenkNCmBgYHtyfQ0KbTIgPC0gYWJzKG0xKQ0KbTINCmBgYA0KDQpgYGB7cn0NCm0zIDwtIG0xXjINCm0zDQpgYGANCg0KYGBge3J9DQptNCA8LSBtMSAqIG0xDQptNA0KYGBgDQojIyMgV3licmFuZSBvcGVyYWNqZSBuYSBtYWNpZXJ6YWNoDQpgYGB7cn0NCm01IDwtIG0xICUqJSBtMQ0KY29sU3VtcyhtNCkNCnJvd1N1bXMobTQpDQpjb2xNZWFucyhtNCkNCnJvd01lYW5zKG00KQ0KYGBgDQoNCiMjIFJhbWtpIGRhbnljaA0KYGBge3J9DQpkZjEgPC0gZGF0YS5mcmFtZShsenAgPSBybm9ybSgxMCksIA0KICAgICAgICAgICAgICAgICAgbGMgPSBzYW1wbGUoMToxMDAsIDEwKSwgDQogICAgICAgICAgICAgICAgICB3bCA9IHNhbXBsZShjKFRSVUUsIEZBTFNFKSwgMTAsIHJlcGxhY2UgPSBUUlVFKSwgDQogICAgICAgICAgICAgICAgICB6ZiA9IHNhbXBsZShmYWN0b3IoYygiSyIsICJNIikpLCAxMCwgcmVwbGFjZSA9IFRSVUUpKQ0KZGYxDQpgYGANCiMjIyBQb2RzdW1vd2FuaWUNCmBgYHtyfQ0Kc3VtbWFyeShkZjEpDQpgYGANCg==