Ôn lại buổi 1

1. Cài thư mục làm việc (Rscript)

  • Rscript không biết đang ở trong thư mục nào

  • getwd() - thư mục làm việc hiện tại

  • setwd() - cài thư mục làm việc mới (chỉ cần dùng với Rscript)

  • dir() - file folder đang có trong thư mục làm việc

getwd()
[1] "/Users/hoangkhanh/Library/CloudStorage/OneDrive-SciEco/RB-003/buoi_2"
dir()
[1] "Bài tập buổi 2"     "buoi_2.nb.html"     "Buổi_2.pptx"       
[4] "buoi_2.Rmd"         "dat2.dta"           "Data_structure_2.R"
[7] "data.sav"           "VN_GDP_2021.xlsx"  

2. Khai báo biến

Toán tử khai báo biến <- -> =

a <- 12
c = 13
10 -> b
a; b; c
[1] 12
[1] 10
[1] 13

3. Kiểu dữ liệu

3.1. Character

Viết trong dấu ngoặc kép hoặc đơn "đoạn text", 'đoạn text thứ 2'

Các hàm cần nhớ

  • paste(str1, str2, sep = ''): nối các chuỗi làm 1

  • cat(str1, str2, sep = ''): in chuỗi được nối ra màn hình

  • grep(pattern, x)grepl(pattern, x): kiểm tra kí tự có trong chuỗi hay không

  • sub(pattern, replacement, x)gsub(pattern, replacement, x): thay thế chuỗi được tìm bằng chuỗi mới

Ví dụ:

paste('Hoàng', 'Văn', 'A', sep = ' ')
[1] "Hoàng Văn A"
cat('Hoàng', 'Văn', 'A', sep = ' ')
Hoàng Văn A
grep(pattern = 'Nam', x = 'Hoàng Văn Nam')
[1] 1
grep(pattern = 'Nam', x = 'Nguyễn Thị Hiền')
integer(0)
grepl(pattern = 'Nam', x = 'Hoàng Văn Nam')
[1] TRUE
grepl(pattern = 'Nam', x = 'Nguyễn Thị Hiền')
[1] FALSE
sub(pattern = '/', replacement = '-', x = '20/10/2022')
[1] "20-10/2022"
gsub(pattern = '/', replacement = '-', x = '20/10/2022')
[1] "20-10-2022"


3.2. Numeric

a <- 1.5
print(a)

Gồm 2 kiểu:

  • double: số thực (mặc định khi tạo một số thì sẽ là kiểu double)

  • integer: số nguyên

Giá trị đặc biệt: Inf, -Inf, NaN, pi

Toán tử số học: + - * / %% %/% ^ **

Toán tử so sánh:

  • > >= < <= ==

  • | & !: or, and, not

Hàm tính toán thông dụng:

  • log(10): \(\log_e10\) hay \(\ln(10)\)

  • log(n, base = x): \(\log_xn\)

  • log10(100): \(\log_{10}⁡100\)

  • sqrt(10): \(\sqrt{10}\)

  • exp(10): \(e^{10}\)

  • cos(pi), sin(pi), …


3.3. Logical

Biến Logical : Biến chỉ có hai định dạng là TRUE hoặc FALSE

Giá trị đặc biệt: NA (được xem là missing value trong dữ liệu)

TRUE hoặc FALSE hay có thể viết tắt T hoặc F

a <- T
b <- F
a; b
[1] TRUE
[1] FALSE


3.4. Integer

Biến integer: biến số nguyên (nguyên âm, nguyên dương)

  • Lưu ý: Khai báo biến integer trong R ta thêm chữ “L”vào cuối cùng của giá trị.
a <- 1L
print(a)
class(a)


3.5. Complex

Biến complex: biến số phức gồm phần thực và phần ảo

c <- 10 + 5i
print(c)
class(c)


3.6. Raw

Biến raw: là kiểu định dạng mã hoá các biến

Hàm thường sử dụng

  • charToRaw() – Chuyển chuỗi về dạng raw

  • rawToChar() – Chuyển dạng raw về chuỗi

  • numToBits() – Chuyển dạng numeric về raw

  • intToBits() – Chuyển dạng integer về raw


3.7. Làm việc với đa kiểu dữ liệu

Kiểu dữ liệu

  • class(): cho biết kiểu của dữ liệu đó

  • typeof(): cho biết kiểu của dữ liệu đó khi được lưu vào bộ nhớ máy tính

  • class() và typeof() sẽ khác nhau rõ hơn khi dùng với các cấu trúc dữ liệu khác như Data.frame hay Matrix, …

Kiểm tra

  • is.logical() – Kiểm tra có phải logical không

  • is.numeric() – Kiểm tra có phải numeric không

  • is.character() – Kiểm tra có phải character không

  • is.integer() – Kiểm tra có phải integer không

  • is.raw() – Kiểm tra có phải raw không

Chuyển đổi kiểu dữ liệu

  • as.logical() – Chuyển về dạng logical

  • as.integer() – Chuyển về dạng integer

  • as. numeric() – Chuyển về dạng numeric

  • as.character() – Chuyển về dạng character

3.8. Date

Biến date: là biến có dữ liệu biểu thị cho 1 ngày

Ngoài ra còn có kiểu Date-time là biểu thị cho thời gian trong ngày (chi tiết hơn)

ISO 8601: quy chuẩn về trình bày ngày tháng (yyyy-mm-dd) Ví dụ: 2003-02-01

Các hàm thường dùng

  • as.Date(x, …)

  • as.Date.character(x, format, …): chuyển kiểu character về date

  • as.Date.numeric(x, origin, …): chuyển kiểu numeric về date

  • Sys.Date(): lấy ngày hiện tại trên máy

  • Sys.time(): lấy giờ hiện tại trên máy

  • Sys.timezone(): lấy timezone hiện tại trên máy

Ví dụ

date <- as.Date('22/09/2022', format = '%d/%m/%Y')
print(date)
[1] "2022-09-22"
class(date)
[1] "Date"
typeof(date) # R hiểu nó là Date nhưng thực chất nó chỉ lưu một con số thực trên máy
[1] "double"

Cài đặt

  • x Đối tượng được truyền vào

  • format Định dạng ngày được nhập (kiểu character)

  • origin Ngày làm gốc so sánh (kiểu numeric)



Buổi 2: Data Structure

Cấu trúc dữ liệu: là cách các dữ liệu được sắp xếp một cách có cấu trúc.

Cấu tử: là các dữ liệu đơn lẻ trong cấu trúc dữ liệu lớn

Ngôn ngữ hướng đối tượng OOP

  • Lập trình hướng đối tượng là một mẫu hình lập trình dựa trên khái niệm “công nghệ đối tượng”, mà trong đó, đối tượng chứa đựng các dữ liệu, trên các trường, thường được gọi là các thuộc tính; và mã nguồn, được tổ chức thành các phương thức.

  • R cũng là một ngôn ngữ hướng đối tượng, vì vậy có thể nói mọi thứ R trong R đều là một object (đối tượng) và được cung cấp các thuộc tính cũng như method riêng biệt

Mọi thứ trong R đều là một đối tượng (R Objects)

Do đó mọi thứ trong R đều sẽ có thể có các thuộc tính (attributes) đi kèm

1. Vector

Dạng cấu trức dữ liệu mà ở đây dữ liệu được sắp xếp vị trí theo thứ tự từ trái sang phải

Các công việc cần làm

  • Tạo vector (Create)

  • Truy cập (Access)

  • Chỉnh sửa (Modify)

Lưu ý khác với vector trong toán

  • Vector này ở đây là dữ liệu một chiều, còn trong toán là số chiều tùy vào số phần tử có trong vector
dim(c(1, 2)) # null
NULL


1.1. Tạo một vector

Cú pháp: variable_name <- c(data1, data2, …)

x <- c(2,5,7,8,3)
x
[1] 2 5 7 8 3


Tạo nhanh một vector

Dùng cú pháp start:end hoặc dùng hàm seq(start, end, by)

# Creating a sequence from 5 to 13. 
v <- 5:13 
print(v) 
[1]  5  6  7  8  9 10 11 12 13
# Creating a sequence from 6.6 to 12.6. 
v <- 6.6:12.6 
print(v) 
[1]  6.6  7.6  8.6  9.6 10.6 11.6 12.6
# If the final element specified does not belong to the sequence then it is discarded. 
v <- 3.8:11.4 
print(v)
[1]  3.8  4.8  5.8  6.8  7.8  8.8  9.8 10.8
seq(1, 3 , by = 0.2)
 [1] 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0
seq(from = 1, to = 10, by = 2)
[1] 1 3 5 7 9


1.2. Truy cập các phần tử trong vector

x
[1]  0  2  4  6  8 10
x[3] # truy cập phần tử thứ 3
[1] 4
x[c(2, 4)] # truy cập phần tử thứ 2 và 4
[1] 2 6
x[-1] # truy cập tất cả phần tử trừ phần tử đầu tiên
[1]  2  4  6  8 10
# Sử dụng vector chứa các phần tử là logical để truy cập
# Lấy phần tử đầu tiên
x[c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE)]
[1] 0


Hàm names()

# Tạo vector dt gồm 3 phần tử 20, 30, 25
# Đặt tên tương ứng với diện tích phòng ngủ, phòng khách, phòng bếp.
dt <- c(20, 30, 25)
names(dt) <- c("phòng ngủ", "phòng khách", "phòng bếp")
print(dt)
  phòng ngủ phòng khách   phòng bếp 
         20          30          25 
# Cách 2: nhanh hơn
dt2 <- c("phòng ngủ"= 20, "phòng khách"= 30, "phòng bếp"= 25)
print(dt2)
  phòng ngủ phòng khách   phòng bếp 
         20          30          25 
# Truy cập các phần tử
dt["phòng ngủ"]
phòng ngủ 
       20 


1.3. Chỉnh sửa vector


Chỉnh sửa các phần tử

h2 <- c(-3,-2,-1) # tạo vector h2
h2
[1] -3 -2 -1
# sửa phần tử thứ 3 thành 1
h2[3] <- 1
h2
[1] -3 -2  1


Tính toán trên vector

x <- seq(10, 40, 10)
y <- 1:4
x; y
[1] 10 20 30 40
[1] 1 2 3 4
x + 1
[1] 11 21 31 41
x + y # lưu ý số lượng phần tử của x và y phải BẰNG nhau
[1] 11 22 33 44


So sánh các vector với điều kiện

x; y
[1] 10 20 30 40
[1] 1 2 3 4
x > y # tất cả phần tử của x đều lớn hơn y
[1] TRUE TRUE TRUE TRUE
x > 10 # phần tử đầu tiên không lớn hơn 10
[1] FALSE  TRUE  TRUE  TRUE
# Lấy ra các phần tử lớn hơn 10 của x
x[x > 10]
[1] 20 30 40

1.4. Một số hàm thường dùng

  • sum(x) – tính tổng

  • mean(x) – tính trung bình

  • length(x) – đếm số lượng phần tử

  • median(x) – tính trung vị

  • quantile(x, probs) – tính phân vị

  • var(x) – tính phương sai

  • sd(x) – tính độ lệch chuẩn

  • cov(x) – tính hiệp phương sai

  • cor(x) – tính hệ số.tương quan

  • sort(x, …) – sắp xếp thứ tự

  • order(x, …) – sắp xếp thứ tự và trả về vị trí mới

  • summary(x) – thống kê mô tả

LS0tCnRpdGxlOiAiQnXhu5VpIDI6IERhdGEgU3RydWN0dXJlIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdGhlbWU6IGx1bWVuCi0tLQoKIyMgw5RuIGzhuqFpIGJ14buVaSAxCgojIyMgMS4gQ8OgaSB0aMawIG3hu6VjIGzDoG0gdmnhu4djIChSc2NyaXB0KQoKLSBSc2NyaXB0IGtow7RuZyBiaeG6v3QgxJFhbmcg4bufIHRyb25nIHRoxrAgbeG7pWMgbsOgbwoKLSBgZ2V0d2QoKWAgLSB0aMawIG3hu6VjIGzDoG0gdmnhu4djIGhp4buHbiB04bqhaQoKLSBgc2V0d2QoKWAgLSBjw6BpIHRoxrAgbeG7pWMgbMOgbSB2aeG7h2MgbeG7m2kgKGNo4buJIGPhuqduIGTDuW5nIHbhu5tpIFJzY3JpcHQpCgotIGBkaXIoKWAgLSBmaWxlIGZvbGRlciDEkWFuZyBjw7MgdHJvbmcgdGjGsCBt4bulYyBsw6BtIHZp4buHYwoKYGBge3J9CmdldHdkKCkKYGBgCgpgYGB7cn0KZGlyKCkKYGBgCgojIyMgMi4gS2hhaSBiw6FvIGJp4bq/bgoKVG/DoW4gdOG7rSBraGFpIGLDoW8gYmnhur9uIGA8LWAgYC0+YCBgPWAKCmBgYHtyfQphIDwtIDEyCmMgPSAxMwoxMCAtPiBiCmBgYAoKYGBge3J9CmE7IGI7IGMKYGBgCgoKIyMjIDMuIEtp4buDdSBk4buvIGxp4buHdQojIyMjIDMuMS4gQ2hhcmFjdGVyCgo+IFZp4bq/dCB0cm9uZyBk4bqldSBuZ2/hurdjIGvDqXAgaG/hurdjIMSRxqFuIGAixJFv4bqhbiB0ZXh0ImAsIGAnxJFv4bqhbiB0ZXh0IHRo4bupIDInYAoKKipDw6FjIGjDoG0gY+G6p24gbmjhu5sqKgoKLSBgcGFzdGUoc3RyMSwgc3RyMiwgc2VwID0gJycpYDogbuG7kWkgY8OhYyBjaHXhu5dpIGzDoG0gMQoKLSBgY2F0KHN0cjEsIHN0cjIsIHNlcCA9ICcnKWA6IGluIGNodeG7l2kgxJHGsOG7o2MgbuG7kWkgcmEgbcOgbiBow6xuaAoKLSBgZ3JlcChwYXR0ZXJuLCB4KWAgdsOgIGBncmVwbChwYXR0ZXJuLCB4KWA6IGtp4buDbSB0cmEga8OtIHThu7EgY8OzIHRyb25nIGNodeG7l2kgaGF5IGtow7RuZwoKLSBgc3ViKHBhdHRlcm4sIHJlcGxhY2VtZW50LCB4KWAgdsOgIGBnc3ViKHBhdHRlcm4sIHJlcGxhY2VtZW50LCB4KWA6IHRoYXkgdGjhur8gY2h14buXaSDEkcaw4bujYyB0w6xtIGLhurFuZyBjaHXhu5dpIG3hu5tpCgoqKlbDrSBk4bulOioqCgpgYGB7cn0KcGFzdGUoJ0hvw6BuZycsICdWxINuJywgJ0EnLCBzZXAgPSAnICcpCmBgYApgYGB7cn0KY2F0KCdIb8OgbmcnLCAnVsSDbicsICdBJywgc2VwID0gJyAnKQpgYGAKCmBgYHtyfQpncmVwKHBhdHRlcm4gPSAnTmFtJywgeCA9ICdIb8OgbmcgVsSDbiBOYW0nKQpncmVwKHBhdHRlcm4gPSAnTmFtJywgeCA9ICdOZ3V54buFbiBUaOG7iyBIaeG7gW4nKQpgYGAKCmBgYHtyfQpncmVwbChwYXR0ZXJuID0gJ05hbScsIHggPSAnSG/DoG5nIFbEg24gTmFtJykKZ3JlcGwocGF0dGVybiA9ICdOYW0nLCB4ID0gJ05ndXnhu4VuIFRo4buLIEhp4buBbicpCmBgYAoKYGBge3J9CnN1YihwYXR0ZXJuID0gJy8nLCByZXBsYWNlbWVudCA9ICctJywgeCA9ICcyMC8xMC8yMDIyJykKZ3N1YihwYXR0ZXJuID0gJy8nLCByZXBsYWNlbWVudCA9ICctJywgeCA9ICcyMC8xMC8yMDIyJykKYGBgCjxicj4KCgojIyMjIDMuMi4gTnVtZXJpYwoKYGBge3J9CmEgPC0gMS41CnByaW50KGEpCmBgYAoKR+G7k20gMiBraeG7g3U6CgotIGRvdWJsZTogc+G7kSB0aOG7sWMgKG3hurdjIMSR4buLbmgga2hpIHThuqFvIG3hu5l0IHPhu5EgdGjDrCBz4bq9IGzDoCBraeG7g3UgZG91YmxlKQoKLSBpbnRlZ2VyOiBz4buRIG5ndXnDqm4KCkdpw6EgdHLhu4sgxJHhurdjIGJp4buHdDogYEluZmAsIGAtSW5mYCwgYE5hTmAsIGBwaWAKClRvw6FuIHThu60gc+G7kSBo4buNYzogYCtgIGAtYCBgKmAgYC9gIGAlJWAgYCUvJWAgYF5gIGAqKmAKClRvw6FuIHThu60gc28gc8Ohbmg6IAoKLSBgPmAgYD49YCBgPGAgYDw9YCBgPT1gCgotIGB8YCBgJmAgYCFgOiBvciwgYW5kLCBub3QKCioqSMOgbSB0w61uaCB0b8OhbiB0aMO0bmcgZOG7pW5nKio6CgotIGBsb2coMTApYDogJFxsb2dfZTEwJCBoYXkgJFxsbigxMCkkCgotIGBsb2cobiwgYmFzZSA9IHgpYDogJFxsb2dfeG4kCgotIGBsb2cxMCgxMDApYDogJFxsb2dfezEwfeKBoTEwMCQKCi0gYHNxcnQoMTApYDogJFxzcXJ0ezEwfSQKCi0gYGV4cCgxMClgOiAkZV57MTB9JAoKLSBgY29zKHBpKWAsIGBzaW4ocGkpYCwg4oCmCgo8YnI+CgoKIyMjIyAzLjMuIExvZ2ljYWwKCj4gQmnhur9uIExvZ2ljYWwgOiBCaeG6v24gY2jhu4kgY8OzIGhhaSDEkeG7i25oIGThuqFuZyBsw6AgVFJVRSBob+G6t2MgRkFMU0UKCioqR2nDoSB0cuG7iyDEkeG6t2MgYmnhu4d0Kio6IE5BICjEkcaw4bujYyB4ZW0gbMOgIG1pc3NpbmcgdmFsdWUgdHJvbmcgZOG7ryBsaeG7h3UpCgpgVFJVRWAgaG/hurdjIGBGQUxTRWAgaGF5IGPDsyB0aOG7gyB2aeG6v3QgdOG6r3QgYFRgIGhv4bq3YyBgRmAKCmBgYHtyfQphIDwtIFQKYiA8LSBGCmE7IGIKYGBgCgoKPGJyPgoKCiMjIyMgMy40LiBJbnRlZ2VyCgo+IEJp4bq/biBpbnRlZ2VyOiBiaeG6v24gc+G7kSBuZ3V5w6puIChuZ3V5w6puIMOibSwgbmd1ecOqbiBkxrDGoW5nKSAKCi0gTMawdSDDvTogS2hhaSBiw6FvIGJp4bq/biBpbnRlZ2VyIHRyb25nIFIgdGEgdGjDqm0gY2jhu68g4oCcTOKAnXbDoG8gY3Xhu5FpIGPDuW5nIGPhu6dhIGdpw6EgdHLhu4suCgoKYGBge3J9CmEgPC0gMUwKcHJpbnQoYSkKY2xhc3MoYSkKYGBgCgo8YnI+CgoKIyMjIyAzLjUuIENvbXBsZXgKCj4gQmnhur9uIGNvbXBsZXg6IGJp4bq/biBz4buRIHBo4bupYyBn4buTbSBwaOG6p24gdGjhu7FjIHbDoCBwaOG6p24g4bqjbwoKYGBge3J9CmMgPC0gMTAgKyA1aQpwcmludChjKQpjbGFzcyhjKQpgYGAKCgo8YnI+CgoKIyMjIyAzLjYuIFJhdwoKPiBCaeG6v24gcmF3OiBsw6Aga2nhu4N1IMSR4buLbmggZOG6oW5nIG3DoyBob8OhIGPDoWMgYmnhur9uCgpIw6BtIHRoxrDhu51uZyBz4butIGThu6VuZwoKLSBgY2hhclRvUmF3KClgIOKAkyBDaHV54buDbiBjaHXhu5dpIHbhu4EgZOG6oW5nIHJhdyAKCi0gYHJhd1RvQ2hhcigpYCDigJMgQ2h1eeG7g24gZOG6oW5nIHJhdyB24buBIGNodeG7l2kKCi0gYG51bVRvQml0cygpYCDigJMgQ2h1eeG7g24gZOG6oW5nIG51bWVyaWMgduG7gSByYXcKCi0gYGludFRvQml0cygpYCDigJMgQ2h1eeG7g24gZOG6oW5nIGludGVnZXIgduG7gSByYXcKCjxicj4KCgoKCiMjIyMgMy43LiBMw6BtIHZp4buHYyB24bubaSDEkWEga2nhu4N1IGThu68gbGnhu4d1CgoqKktp4buDdSBk4buvIGxp4buHdSoqCgotIGBjbGFzcygpYDogY2hvIGJp4bq/dCBraeG7g3UgY+G7p2EgZOG7ryBsaeG7h3UgxJHDswoKLSBgdHlwZW9mKClgOiBjaG8gYmnhur90IGtp4buDdSBj4bunYSBk4buvIGxp4buHdSDEkcOzIGtoaSDEkcaw4bujYyBsxrB1IHbDoG8gYuG7mSBuaOG7myBtw6F5IHTDrW5oCgotIGBjbGFzcygpYCB2w6AgdHlwZW9mKCkgc+G6vSBraMOhYyBuaGF1IHLDtSBoxqFuIGtoaSBkw7luZyB24bubaSBjw6FjIGPhuqV1IHRyw7pjIGThu68gbGnhu4d1IGtow6FjIG5oxrAgRGF0YS5mcmFtZSBoYXkgTWF0cml4LCAuLi4KCioqS2nhu4NtIHRyYSoqCgotIGBpcy5sb2dpY2FsKClgIOKAkyBLaeG7g20gdHJhIGPDsyBwaOG6o2kgbG9naWNhbCBraMO0bmcKCi0gYGlzLm51bWVyaWMoKWAg4oCTIEtp4buDbSB0cmEgY8OzIHBo4bqjaSBudW1lcmljIGtow7RuZwoKLSBgaXMuY2hhcmFjdGVyKClgIOKAkyBLaeG7g20gdHJhIGPDsyBwaOG6o2kgY2hhcmFjdGVyIGtow7RuZwoKLSBgaXMuaW50ZWdlcigpYCDigJMgS2nhu4NtIHRyYSBjw7MgcGjhuqNpIGludGVnZXIga2jDtG5nCgotIGBpcy5yYXcoKWAg4oCTIEtp4buDbSB0cmEgY8OzIHBo4bqjaSByYXcga2jDtG5nCgoqKkNodXnhu4NuIMSR4buVaSBraeG7g3UgZOG7ryBsaeG7h3UqKgoKLSBgYXMubG9naWNhbCgpYCDigJMgQ2h1eeG7g24gduG7gSBk4bqhbmcgbG9naWNhbAoKLSBgYXMuaW50ZWdlcigpYCDigJMgQ2h1eeG7g24gduG7gSBk4bqhbmcgaW50ZWdlcgoKLSBgYXMuIG51bWVyaWMoKWAg4oCTIENodXnhu4NuIHbhu4EgZOG6oW5nIG51bWVyaWMKCi0gYGFzLmNoYXJhY3RlcigpYCDigJMgQ2h1eeG7g24gduG7gSBk4bqhbmcgY2hhcmFjdGVyCgojIyMjIDMuOC4gRGF0ZQoKPiBCaeG6v24gZGF0ZTogbMOgIGJp4bq/biBjw7MgZOG7ryBsaeG7h3UgYmnhu4N1IHRo4buLIGNobyAxIG5nw6B5CgoqTmdvw6BpIHJhIGPDsm4gY8OzIGtp4buDdSBEYXRlLXRpbWUgbMOgIGJp4buDdSB0aOG7iyBjaG8gdGjhu51pIGdpYW4gdHJvbmcgbmfDoHkgKGNoaSB0aeG6v3QgaMahbikqCgo+IElTTyA4NjAxOiBxdXkgY2h14bqpbiB24buBIHRyw6xuaCBiw6B5IG5nw6B5IHRow6FuZyAoeXl5eS1tbS1kZCkKVsOtIGThu6U6IDIwMDMtMDItMDEKCioqQ8OhYyBow6BtIHRoxrDhu51uZyBkw7luZyoqCgotIGBhcy5EYXRlKHgsIOKApilgCgotIGBhcy5EYXRlLmNoYXJhY3Rlcih4LCBmb3JtYXQsIOKApilgOiBjaHV54buDbiBraeG7g3UgY2hhcmFjdGVyIHbhu4EgZGF0ZQoKLSBgYXMuRGF0ZS5udW1lcmljKHgsIG9yaWdpbiwg4oCmKWA6IGNodXnhu4NuIGtp4buDdSBudW1lcmljIHbhu4EgZGF0ZQoKLSBgU3lzLkRhdGUoKWA6IGzhuqV5IG5nw6B5IGhp4buHbiB04bqhaSB0csOqbiBtw6F5CgotIGBTeXMudGltZSgpYDogbOG6pXkgZ2nhu50gaGnhu4duIHThuqFpIHRyw6puIG3DoXkKCi0gYFN5cy50aW1lem9uZSgpYDogbOG6pXkgdGltZXpvbmUgaGnhu4duIHThuqFpIHRyw6puIG3DoXkKCioqVsOtIGThu6UqKgoKYGBge3J9CmRhdGUgPC0gYXMuRGF0ZSgnMjIvMDkvMjAyMicsIGZvcm1hdCA9ICclZC8lbS8lWScpCnByaW50KGRhdGUpCmNsYXNzKGRhdGUpCnR5cGVvZihkYXRlKSAjIFIgaGnhu4N1IG7DsyBsw6AgRGF0ZSBuaMawbmcgdGjhu7FjIGNo4bqldCBuw7MgY2jhu4kgbMawdSBt4buZdCBjb24gc+G7kSB0aOG7sWMgdHLDqm4gbcOheQpgYGAKCioqQ8OgaSDEkeG6t3QqKgoKLSBgeGAgxJDhu5FpIHTGsOG7o25nIMSRxrDhu6NjIHRydXnhu4FuIHbDoG8KCi0gYGZvcm1hdGAgxJDhu4tuaCBk4bqhbmcgbmfDoHkgxJHGsOG7o2Mgbmjhuq1wIChraeG7g3UgY2hhcmFjdGVyKQoKLSBgb3JpZ2luYCBOZ8OgeSBsw6BtIGfhu5FjIHNvIHPDoW5oIChraeG7g3UgbnVtZXJpYykKCgoKPGJyPgo8aHI+CiMjIEJ14buVaSAyOiBEYXRhIFN0cnVjdHVyZQoKPkPhuqV1IHRyw7pjIGThu68gbGnhu4d1OiBsw6AgY8OhY2ggY8OhYyBk4buvIGxp4buHdSDEkcaw4bujYyBz4bqvcCB44bq/cCBt4buZdCBjw6FjaCBjw7MgY+G6pXUgdHLDumMuCgo+IEPhuqV1IHThu606IGzDoCBjw6FjIGThu68gbGnhu4d1IMSRxqFuIGzhursgdHJvbmcgY+G6pXUgdHLDumMgZOG7ryBsaeG7h3UgbOG7m24KCiMjIyBOZ8O0biBuZ+G7ryBoxrDhu5tuZyDEkeG7kWkgdMaw4bujbmcgT09QCgotIEzhuq1wIHRyw6xuaCBoxrDhu5tuZyDEkeG7kWkgdMaw4bujbmcgbMOgIG3hu5l0IG3huqt1IGjDrG5oIGzhuq1wIHRyw6xuaCBk4buxYSB0csOqbiBraMOhaSBuaeG7h20gImPDtG5nIG5naOG7hyDEkeG7kWkgdMaw4bujbmciLCBtw6AgdHJvbmcgxJHDsywgxJHhu5FpIHTGsOG7o25nIGNo4bupYSDEkeG7sW5nIGPDoWMgZOG7ryBsaeG7h3UsIHRyw6puIGPDoWMgdHLGsOG7nW5nLCB0aMaw4budbmcgxJHGsOG7o2MgZ+G7jWkgbMOgIGPDoWMgKip0aHXhu5ljIHTDrW5oKio7IHbDoCBtw6Mgbmd14buTbiwgxJHGsOG7o2MgdOG7lSBjaOG7qWMgdGjDoG5oIGPDoWMgcGjGsMahbmcgdGjhu6ljLgoKLSBSIGPFqW5nIGzDoCBt4buZdCBuZ8O0biBuZ+G7ryBoxrDhu5tuZyDEkeG7kWkgdMaw4bujbmcsIHbDrCB24bqteSBjw7MgdGjhu4MgbsOzaSBt4buNaSB0aOG7qSBSIHRyb25nIFIgxJHhu4F1IGzDoCBt4buZdCBvYmplY3QgKMSR4buRaSB0xrDhu6NuZykgdsOgIMSRxrDhu6NjIGN1bmcgY+G6pXAgY8OhYyB0aHXhu5ljIHTDrW5oIGPFqW5nIG5oxrAgbWV0aG9kIHJpw6puZyBiaeG7h3QKCioqTeG7jWkgdGjhu6kgdHJvbmcgUiDEkeG7gXUgbMOgIG3hu5l0IMSR4buRaSB0xrDhu6NuZyAoUiBPYmplY3RzKSoqCgoqKkRvIMSRw7MgbeG7jWkgdGjhu6kgdHJvbmcgUiDEkeG7gXUgc+G6vSBjw7MgdGjhu4MgY8OzIGPDoWMgdGh14buZYyB0w61uaCAoYXR0cmlidXRlcykgxJFpIGvDqG0qKgoKIyMjIDEuIFZlY3RvcgoKPiBE4bqhbmcgY+G6pXUgdHLhu6ljIGThu68gbGnhu4d1IG3DoCDhu58gxJHDonkgZOG7ryBsaeG7h3UgxJHGsOG7o2Mgc+G6r3AgeOG6v3AgduG7iyB0csOtIHRoZW8gdGjhu6kgdOG7sSB04burIHRyw6FpIHNhbmcgcGjhuqNpCgoqKkPDoWMgY8O0bmcgdmnhu4djIGPhuqduIGzDoG0qKgoKLSBU4bqhbyB2ZWN0b3IgKENyZWF0ZSkKCi0gVHJ1eSBj4bqtcCAoQWNjZXNzKQoKLSBDaOG7iW5oIHPhu61hIChNb2RpZnkpCgoqKkzGsHUgw70ga2jDoWMgduG7m2kgdmVjdG9yIHRyb25nIHRvw6FuKioKCi0gVmVjdG9yIG7DoHkg4bufIMSRw6J5IGzDoCBk4buvIGxp4buHdSBt4buZdCBjaGnhu4F1LCBjw7JuIHRyb25nIHRvw6FuIGzDoCBz4buRIGNoaeG7gXUgdMO5eSB2w6BvIHPhu5EgcGjhuqduIHThu60gY8OzIHRyb25nIHZlY3RvcgoKYGBge3J9CmRpbShjKDEsIDIpKSAjIG51bGwKYGBgCgo8YnI+CgojIyMjIDEuMS4gVOG6oW8gbeG7mXQgdmVjdG9yCgpDw7ogcGjDoXA6IGB2YXJpYWJsZV9uYW1lIDwtIGMoZGF0YTEsIGRhdGEyLCDigKYpYAoKYGBge3J9CnggPC0gYygyLDUsNyw4LDMpCngKYGBgCjxicj4KCioqVOG6oW8gbmhhbmggbeG7mXQgdmVjdG9yKioKCkTDuW5nIGPDuiBwaMOhcCBgc3RhcnQ6ZW5kYCBob+G6t2MgZMO5bmcgaMOgbSBgc2VxKHN0YXJ0LCBlbmQsIGJ5KWAKCmBgYHtyfQojIENyZWF0aW5nIGEgc2VxdWVuY2UgZnJvbSA1IHRvIDEzLiAKdiA8LSA1OjEzIApwcmludCh2KSAKIyBDcmVhdGluZyBhIHNlcXVlbmNlIGZyb20gNi42IHRvIDEyLjYuIAp2IDwtIDYuNjoxMi42IApwcmludCh2KSAKIyBJZiB0aGUgZmluYWwgZWxlbWVudCBzcGVjaWZpZWQgZG9lcyBub3QgYmVsb25nIHRvIHRoZSBzZXF1ZW5jZSB0aGVuIGl0IGlzIGRpc2NhcmRlZC4gCnYgPC0gMy44OjExLjQgCnByaW50KHYpCmBgYAoKYGBge3J9CnNlcSgxLCAzICwgYnkgPSAwLjIpCmBgYAoKYGBge3J9CnNlcShmcm9tID0gMSwgdG8gPSAxMCwgYnkgPSAyKQpgYGAKCjxicj4KCiMjIyMgMS4yLiBUcnV5IGPhuq1wIGPDoWMgcGjhuqduIHThu60gdHJvbmcgdmVjdG9yCgpgYGB7cn0KeCA8LSBzZXEoMCwgMTAsIDIpCngKYGBgCgpgYGB7cn0KeFszXSAjIHRydXkgY+G6rXAgcGjhuqduIHThu60gdGjhu6kgMwpgYGAKCmBgYHtyfQp4W2MoMiwgNCldICMgdHJ1eSBj4bqtcCBwaOG6p24gdOG7rSB0aOG7qSAyIHbDoCA0CmBgYAoKYGBge3J9CnhbLTFdICMgdHJ1eSBj4bqtcCB04bqldCBj4bqjIHBo4bqnbiB04butIHRy4burIHBo4bqnbiB04butIMSR4bqndSB0acOqbgpgYGAKCmBgYHtyfQojIFPhu60gZOG7pW5nIHZlY3RvciBjaOG7qWEgY8OhYyBwaOG6p24gdOG7rSBsw6AgbG9naWNhbCDEkeG7gyB0cnV5IGPhuq1wCiMgTOG6pXkgcGjhuqduIHThu60gxJHhuqd1IHRpw6puCnhbYyhUUlVFLCBGQUxTRSwgRkFMU0UsIEZBTFNFLCBGQUxTRSwgRkFMU0UpXQpgYGAKPGJyPgoKKipIw6BtIGBuYW1lcygpYCoqCgpgYGB7cn0KIyBU4bqhbyB2ZWN0b3IgZHQgZ+G7k20gMyBwaOG6p24gdOG7rSAyMCwgMzAsIDI1CiMgxJDhurd0IHTDqm4gdMawxqFuZyDhu6luZyB24bubaSBkaeG7h24gdMOtY2ggcGjDsm5nIG5n4bunLCBwaMOybmcga2jDoWNoLCBwaMOybmcgYuG6v3AuCmR0IDwtIGMoMjAsIDMwLCAyNSkKbmFtZXMoZHQpIDwtIGMoInBow7JuZyBuZ+G7pyIsICJwaMOybmcga2jDoWNoIiwgInBow7JuZyBi4bq/cCIpCnByaW50KGR0KQpgYGAKCmBgYHtyfQojIEPDoWNoIDI6IG5oYW5oIGjGoW4KZHQyIDwtIGMoInBow7JuZyBuZ+G7pyI9IDIwLCAicGjDsm5nIGtow6FjaCI9IDMwLCAicGjDsm5nIGLhur9wIj0gMjUpCnByaW50KGR0MikKYGBgCgpgYGB7cn0KIyBUcnV5IGPhuq1wIGPDoWMgcGjhuqduIHThu60KZHRbInBow7JuZyBuZ+G7pyJdCmBgYAoKPGJyPgoKIyMjIyAxLjMuIENo4buJbmggc+G7rWEgdmVjdG9yCgo8YnI+CioqQ2jhu4luaCBz4butYSBjw6FjIHBo4bqnbiB04butKioKCmBgYHtyfQpoMiA8LSBjKC0zLC0yLC0xKSAjIHThuqFvIHZlY3RvciBoMgpoMgpgYGAKCmBgYHtyfQojIHPhu61hIHBo4bqnbiB04butIHRo4bupIDMgdGjDoG5oIDEKaDJbM10gPC0gMQpoMgpgYGAKCjxicj4KCioqVMOtbmggdG/DoW4gdHLDqm4gdmVjdG9yKioKCmBgYHtyfQp4IDwtIHNlcSgxMCwgNDAsIDEwKQp5IDwtIDE6NAp4OyB5CmBgYAoKYGBge3J9CnggKyAxCmBgYAoKYGBge3J9CnggKyB5ICMgbMawdSDDvSBz4buRIGzGsOG7o25nIHBo4bqnbiB04butIGPhu6dhIHggdsOgIHkgcGjhuqNpIELhurBORyBuaGF1CmBgYAoKPGJyPgoqKlNvIHPDoW5oIGPDoWMgdmVjdG9yIHbhu5tpIMSRaeG7gXUga2nhu4duKioKCmBgYHtyfQp4OyB5CmBgYAoKYGBge3J9CnggPiB5ICMgdOG6pXQgY+G6oyBwaOG6p24gdOG7rSBj4bunYSB4IMSR4buBdSBs4bubbiBoxqFuIHkKYGBgCgpgYGB7cn0KeCA+IDEwICMgcGjhuqduIHThu60gxJHhuqd1IHRpw6puIGtow7RuZyBs4bubbiBoxqFuIDEwCmBgYAoKYGBge3J9CiMgTOG6pXkgcmEgY8OhYyBwaOG6p24gdOG7rSBs4bubbiBoxqFuIDEwIGPhu6dhIHgKeFt4ID4gMTBdCmBgYAoKIyMjIyAxLjQuIE3hu5l0IHPhu5EgaMOgbSB0aMaw4budbmcgZMO5bmcKCi0gYHN1bSh4KWAg4oCTIHTDrW5oIHThu5VuZwoKLSBgbWVhbih4KWAg4oCTIHTDrW5oIHRydW5nIGLDrG5oCgotIGBsZW5ndGgoeClgIOKAkyDEkeG6v20gc+G7kSBsxrDhu6NuZyBwaOG6p24gdOG7rQoKLSBgbWVkaWFuKHgpYCDigJMgdMOtbmggdHJ1bmcgduG7iwoKLSBgcXVhbnRpbGUoeCwgcHJvYnMpYCDigJMgdMOtbmggcGjDom4gduG7iwoKLSBgdmFyKHgpYCDigJMgdMOtbmggcGjGsMahbmcgc2FpCgotIGBzZCh4KWAg4oCTIHTDrW5oIMSR4buZIGzhu4djaCBjaHXhuqluCgotIGBjb3YoeClgIOKAkyB0w61uaCBoaeG7h3AgcGjGsMahbmcgc2FpCgotIGBjb3IoeClgIOKAkyB0w61uaCBo4buHIHPhu5EudMawxqFuZyBxdWFuCgotIGBzb3J0KHgsIOKApilgIOKAkyBz4bqvcCB44bq/cCB0aOG7qSB04buxCgotIGBvcmRlcih4LCDigKYpYCDigJMgc+G6r3AgeOG6v3AgdGjhu6kgdOG7sSB2w6AgdHLhuqMgduG7gSB24buLIHRyw60gbeG7m2kKCi0gYHN1bW1hcnkoeClgIOKAkyB0aOG7kW5nIGvDqiBtw7QgdOG6owo=