Algoritma & Struktur Data

~ Ujian Tengah Semester ~


Kontak : \(\downarrow\)
Email
Instagram https://www.instagram.com/saram.05/
RPubs https://rpubs.com/sausanramadhani/

Pendahuluan

Salah satu hal dasar dalam pengolahan data yaitu terhubung dengan data. Untuk mengetahui caranya, kita akan mempelajari proses antarmuka data menggunakan program R. Sebagai pemula, kita cukup mengetahui proses sederhananya terlebih dahulu. Program R dapat membaca data dari suatu file yang tersimpan dimanapun serta dalam berbagai formatnya seperti csv, excel, txt, rds, xml, json, dan lain-lain serta dapat menyimpannya kembali.

Impor/Ekspor CSV

Proses impor/ekspor data menggunakan R bisa dengan berbagai cara. Hal ini juga harus diperhatikan format filenya karena tiap format menggunakan cara yang berbeda. Untuk file yang berformat csv bisa menggunakan 3 cara berikut ini :

Cara 1

Mula-mula kita perhatikan apakah direktori kerjanya sudah benar atau belum yaitu dengan memeriksannya menggunakan fungsi ‘getwd()’. Setelah itu, kita sudah bisa mengatur direktori kerja baru dengan fungsi ‘setwd()’. Kemudian, impor data tersebut dengan fungsi ‘read.csv()’. Sedangkan, untuk mengekspor data tersebut bisa menggunakan fungsi ‘write.csv()’ dan setelahnya yaitu bisa menggunakan fungsi ‘write.csv2()’. Sesuaikan juga dengan pemisahnya antara koma ‘(“,”)’ atau semicolon ‘(“;”)’.

print(getwd())
## [1] "C:/Users/Lenovo/Documents/data"
getwd()
## [1] "C:/Users/Lenovo/Documents/data"
setwd(getwd())

df1 <-read.csv("input/input1.csv",sep = ",")          # format pemisah koma 
df2 <-read.csv("input/input2.csv",sep = ";")          # format pemisah titik koma

write.csv(df1,"output/test1.csv", row.names = TRUE)
write.csv(df2,"output/test2.csv", row.names = TRUE) 

Cara 2

Cara kedua merupakan cara yang bijak dan praktis yaitu koneksi direktorinya secara automatis. Simak caranya berikut ini :

# setting direktori
(WD <- getwd())
## [1] "C:/Users/Lenovo/Documents/data"
if (!is.null(WD)) setwd(WD)

# impor data
df1 <- read.csv(file.path(WD, 'input', 'input1.csv'))
df2 <- read.csv(file.path(WD, 'input', 'input2.csv'))

# ekspor data
write.csv(df1, file.path(WD, 'output', 'output1.csv'), row.names = FALSE)
write.csv(df2, file.path(WD, 'output', 'output2.csv'), row.names = FALSE)

cara 3

Cara ketiga dapat digunakan kita yang menggunakan file atau data yang tersimpan di komputer. Berbeda dengan sebelumnya yang memerlukan koneksi direktori, cukup memilih file yang diperlukan maka kita bisa melakukan proses impor data.

df3 <- read.csv(file.choose())

Untuk proses antarmuka data lainnya hanya menggunakan satu cara saja.

Impor/Ekspor Excel

Microsoft excel sering digunakan untuk menyimpan data. Biasanya data tersimpan dalam format .xls atau .xlsx. Untuk mengimpor atau mengekspor excel menggunakan R bisa menggunakan cara sebagai berikut :

#install.packages(c("readxl", "writexl"))       # install `readxl & writexl` 
pacman::p_load(readxl, writexl)                 # load `readxl & writexl`

# impor data
df3<-read_excel("input/input4.xls")             # impor data xls (97-2003)
df4<-read_excel("input/input3.xlsx",sheet=1)    # impor data xlsx (2003-up)

# ekspor data
write_xlsx(df3,"output/output4.xls") 
write_xlsx(df4,"output/output3.xlsx")

Impor/Ekspor TXT and RDS

Ukuran file TXT dan RDS lebih ringan daripada CSV ataupun XLSX. Maka, cara ini sangat sesuai dengan kita yang tidak ingin menyimpan file dengan ukuran besar. Berikut cara impor/ekspor TXT dan RDS :

# impor data
df5 <- read.table("input/input5.txt")                # format TXT (notepad)
df6 <- source("input/input6.Rdmpd")                  # format TXT (Rdmpd)
df7 <- readRDS("input/input7.rds")                   # format binary RDS
df8 <- readRDS("input/input8.ascii")                 # format binary ASCII

# ekspor data
write.table(df5,"output/output5.txt")
dump("df6", "output/output6.Rdmpd")
saveRDS(df7, "output/output7.rds")
saveRDS(df8, "output/output8.ascii", ascii = TRUE)

Impor/Ekspor XML

Extensible Markup Language (XML) bisa membantu kita memahami struktur data dasar suatu file. XML mirip dengan HTML hanya saja fungsinya berbeda. XML berfungsi untuk menyimpan dan mengirimkan data (impor/ekspor). Sedangkan, HTML berfungsi untuk menampilkan data. Untuk mengetahui proses impor/ekspor XML, perhatikan cara berikut ini :

library("XML")
library("kulife")
library("methods")

df9 <- xmlParse("input/input9.xml")
xml_dataframe <- xmlToDataFrame(df9)
write.xml(xml_dataframe, "output/output9.xml")

Impor/Ekspor JSON

JavaScript Object Notation (JSON) biasanya digunakan untuk mentransfer data dan bisa dibaca oleh penerima data. Untuk membaca file JSON bisa menggunakan R dengan paket ‘jsonlite’. Perhatikan cara impor/ekspor berikut ini :

library("jsonlite")

df10 <- fromJSON("input/input10.json")
json_dataframe <- as.data.frame(df10)
write_json(json_dataframe, "output/output10.json")

Impor Data dari Web

Dalam internet terdapat website yang memberikan informasi suatu data. Biasanya data tersebut digunakan oleh penggunanya. Kita bisa mengimpor data tersebut menggunakan R dengan cara berikut ini :

CSV

web_csv <- read.csv("https://github.com/Bakti-Siregar/dataset/raw/master/Bookdown-Data-Science-for-Beginners/csv1.csv")

XLSX

library(rio)
install_formats()
## [1] TRUE
web_xlsx <- rio::import("https://github.com/Bakti-Siregar/dataset/blob/master/Bookdown-Data-Science-for-Beginners/xlsx1.xlsx?raw=true")

Basis Data R

Sistem ialah kumpulan komponen saling berhubungan yang disatukan dengan suatu tujuan. Basis data ialah objek yang membutuhkan program sebagai pengelolanya. Maka dihasilkanlah sistem basis data dari basis data dan program tersebut. Sistem basis data adalah sistem yang terdiri atas kumpulan tabel data yang saling berhubungan dan kumpulan program yang memungkinkan beberapa pemakai atau program lain untuk mengakses dan memanipulasi tabel tabel data tersebut.

Kita bisa menghubungkan suatu data ke database relasional misalnya MySql, Oracle, SQL Server, dan sebagainya menggunakan R. Lalu kita ubah basis datanya menjadi data frame. Jika data sudah terdapat dalam R, data tersebut bisa dianalisis bahkan dimanipulasi.

Menambang Data Web

Webscraping Data ialah proses pengambilan data dari sebuah website. Berbeda dengan web scraping (hanya menyalin piksel yang ditampilkan), web scraping mengekstrak kode HTML yang mendasarinya yang pada dasarnya disimpan dalam database. Pengikisan data ini dapat mereplikasi seluruh konten dari berbagai situs web yang target.

LS0tDQp0aXRsZTogIkFsZ29yaXRtYSAmIFN0cnVrdHVyIERhdGEiDQpzdWJ0aXRsZTogIn4gVWppYW4gVGVuZ2FoIFNlbWVzdGVyIH4iDQphdXRob3I6ICJTYXVzYW4gUmFtYWRoYW5pIg0KZGF0ZTogICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgcm1kZm9ybWF0czo6cm9ib2Jvb2s6ICAgIyBodHRwczovL2dpdGh1Yi5jb20vanViYS9ybWRmb3JtYXRzDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICB0aHVtYm5haWxzOiB0cnVlDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbGliX2RpcjogbGlicw0KICAgIGRmX3ByaW50OiAicGFnZWQiDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBjc3M6ICJzdHlsZS5jc3MiDQoNCi0tLQ0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNsYXNzLnNvdXJjZSA9ICJub2NvcHkiLA0KICAgICAgICAgICAgICAgICAgICAgIGNsYXNzLm91dHB1dCA9ICJub2NvcHkiLA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGLA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGKQ0KDQpsaWJyYXJ5KHJldGljdWxhdGUpDQpsaWJyYXJ5KFJjcHApDQp1c2VfY29uZGFlbnYoInB5MzgiLCByZXF1aXJlZCA9IFRSVUUpDQpgYGANCg0KPGJyPg0KDQo8aW1nIHN0eWxlPSJmbG9hdDogcmlnaHQ7IG1hcmdpbjogLTUwcHggNTBweCAwcHggNTBweDsgd2lkdGg6MjUlIiBzcmM9ImxvZ29tYXRhbmEucG5nIi8+DQoNCnwNCjotLS0tIHw6LS0tLQ0KKipLb250YWsqKnwgKio6ICRcZG93bmFycm93JCoqDQpFbWFpbHwgbXVnZW1pc2F1c2FuMDVAZ21haWwuY29tDQpJbnN0YWdyYW0gfCBodHRwczovL3d3dy5pbnN0YWdyYW0uY29tL3NhcmFtLjA1LyANClJQdWJzICB8IGh0dHBzOi8vcnB1YnMuY29tL3NhdXNhbnJhbWFkaGFuaS8gDQoNCioqKg0KDQojIFBlbmRhaHVsdWFuDQoNClNhbGFoIHNhdHUgaGFsIGRhc2FyIGRhbGFtIHBlbmdvbGFoYW4gZGF0YSB5YWl0dSB0ZXJodWJ1bmcgZGVuZ2FuIGRhdGEuIFVudHVrIG1lbmdldGFodWkgY2FyYW55YSwga2l0YSBha2FuIG1lbXBlbGFqYXJpIHByb3NlcyBhbnRhcm11a2EgZGF0YSBtZW5nZ3VuYWthbiBwcm9ncmFtIFIuIFNlYmFnYWkgcGVtdWxhLCBraXRhIGN1a3VwIG1lbmdldGFodWkgcHJvc2VzIHNlZGVyaGFuYW55YSB0ZXJsZWJpaCBkYWh1bHUuIFByb2dyYW0gUiBkYXBhdCBtZW1iYWNhIGRhdGEgZGFyaSBzdWF0dSBmaWxlIHlhbmcgdGVyc2ltcGFuIGRpbWFuYXB1biBzZXJ0YSBkYWxhbSBiZXJiYWdhaSBmb3JtYXRueWEgc2VwZXJ0aSBjc3YsIGV4Y2VsLCB0eHQsIHJkcywgeG1sLCBqc29uLCBkYW4gbGFpbi1sYWluIHNlcnRhIGRhcGF0IG1lbnlpbXBhbm55YSBrZW1iYWxpLg0KDQojIEltcG9yL0Vrc3BvciBDU1YNCg0KUHJvc2VzIGltcG9yL2Vrc3BvciBkYXRhIG1lbmdndW5ha2FuIFIgYmlzYSBkZW5nYW4gYmVyYmFnYWkgY2FyYS4gSGFsIGluaSBqdWdhIGhhcnVzIGRpcGVyaGF0aWthbiBmb3JtYXQgZmlsZW55YSBrYXJlbmEgdGlhcCBmb3JtYXQgbWVuZ2d1bmFrYW4gY2FyYSB5YW5nIGJlcmJlZGEuIFVudHVrIGZpbGUgeWFuZyBiZXJmb3JtYXQgY3N2IGJpc2EgbWVuZ2d1bmFrYW4gMyBjYXJhIGJlcmlrdXQgaW5pIDoNCg0KIyMgQ2FyYSAxDQoNCk11bGEtbXVsYSBraXRhIHBlcmhhdGlrYW4gYXBha2FoIGRpcmVrdG9yaSBrZXJqYW55YSBzdWRhaCBiZW5hciBhdGF1IGJlbHVtIHlhaXR1IGRlbmdhbiBtZW1lcmlrc2FubnlhIG1lbmdndW5ha2FuIGZ1bmdzaSAnZ2V0d2QoKScuIFNldGVsYWggaXR1LCBraXRhIHN1ZGFoIGJpc2EgbWVuZ2F0dXIgZGlyZWt0b3JpIGtlcmphIGJhcnUgZGVuZ2FuIGZ1bmdzaSAnc2V0d2QoKScuIEtlbXVkaWFuLCBpbXBvciBkYXRhIHRlcnNlYnV0IGRlbmdhbiBmdW5nc2kgJ3JlYWQuY3N2KCknLiBTZWRhbmdrYW4sIHVudHVrIG1lbmdla3Nwb3IgZGF0YSB0ZXJzZWJ1dCBiaXNhIG1lbmdndW5ha2FuIGZ1bmdzaSAnd3JpdGUuY3N2KCknIGRhbiBzZXRlbGFobnlhIHlhaXR1IGJpc2EgbWVuZ2d1bmFrYW4gZnVuZ3NpICd3cml0ZS5jc3YyKCknLiBTZXN1YWlrYW4ganVnYSBkZW5nYW4gcGVtaXNhaG55YSBhbnRhcmEga29tYSAnKCIsIiknIGF0YXUgc2VtaWNvbG9uICcoIjsiKScuDQoNCmBgYHtyfQ0KcHJpbnQoZ2V0d2QoKSkNCmdldHdkKCkNCnNldHdkKGdldHdkKCkpDQoNCmRmMSA8LXJlYWQuY3N2KCJpbnB1dC9pbnB1dDEuY3N2IixzZXAgPSAiLCIpICAgICAgICAgICMgZm9ybWF0IHBlbWlzYWgga29tYSANCmRmMiA8LXJlYWQuY3N2KCJpbnB1dC9pbnB1dDIuY3N2IixzZXAgPSAiOyIpICAgICAgICAgICMgZm9ybWF0IHBlbWlzYWggdGl0aWsga29tYQ0KDQp3cml0ZS5jc3YoZGYxLCJvdXRwdXQvdGVzdDEuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCndyaXRlLmNzdihkZjIsIm91dHB1dC90ZXN0Mi5jc3YiLCByb3cubmFtZXMgPSBUUlVFKSANCmBgYA0KDQojIyBDYXJhIDINCg0KQ2FyYSBrZWR1YSBtZXJ1cGFrYW4gY2FyYSB5YW5nIGJpamFrIGRhbiBwcmFrdGlzIHlhaXR1IGtvbmVrc2kgZGlyZWt0b3JpbnlhIHNlY2FyYSBhdXRvbWF0aXMuIFNpbWFrIGNhcmFueWEgYmVyaWt1dCBpbmkgOg0KDQpgYGB7cn0NCiMgc2V0dGluZyBkaXJla3RvcmkNCihXRCA8LSBnZXR3ZCgpKQ0KaWYgKCFpcy5udWxsKFdEKSkgc2V0d2QoV0QpDQoNCiMgaW1wb3IgZGF0YQ0KZGYxIDwtIHJlYWQuY3N2KGZpbGUucGF0aChXRCwgJ2lucHV0JywgJ2lucHV0MS5jc3YnKSkNCmRmMiA8LSByZWFkLmNzdihmaWxlLnBhdGgoV0QsICdpbnB1dCcsICdpbnB1dDIuY3N2JykpDQoNCiMgZWtzcG9yIGRhdGENCndyaXRlLmNzdihkZjEsIGZpbGUucGF0aChXRCwgJ291dHB1dCcsICdvdXRwdXQxLmNzdicpLCByb3cubmFtZXMgPSBGQUxTRSkNCndyaXRlLmNzdihkZjIsIGZpbGUucGF0aChXRCwgJ291dHB1dCcsICdvdXRwdXQyLmNzdicpLCByb3cubmFtZXMgPSBGQUxTRSkNCmBgYA0KDQojIyBjYXJhIDMNCg0KQ2FyYSBrZXRpZ2EgZGFwYXQgZGlndW5ha2FuIGtpdGEgeWFuZyBtZW5nZ3VuYWthbiBmaWxlIGF0YXUgZGF0YSB5YW5nIHRlcnNpbXBhbiBkaSBrb21wdXRlci4gQmVyYmVkYSBkZW5nYW4gc2ViZWx1bW55YSB5YW5nIG1lbWVybHVrYW4ga29uZWtzaSBkaXJla3RvcmksIGN1a3VwIG1lbWlsaWggZmlsZSB5YW5nIGRpcGVybHVrYW4gbWFrYSBraXRhIGJpc2EgbWVsYWt1a2FuIHByb3NlcyBpbXBvciBkYXRhLg0KDQpgYGB7cn0NCmRmMyA8LSByZWFkLmNzdihmaWxlLmNob29zZSgpKQ0KYGBgDQoNClVudHVrIHByb3NlcyBhbnRhcm11a2EgZGF0YSBsYWlubnlhIGhhbnlhIG1lbmdndW5ha2FuIHNhdHUgY2FyYSBzYWphLg0KDQojIEltcG9yL0Vrc3BvciBFeGNlbA0KDQpNaWNyb3NvZnQgZXhjZWwgc2VyaW5nIGRpZ3VuYWthbiB1bnR1ayBtZW55aW1wYW4gZGF0YS4gQmlhc2FueWEgZGF0YSB0ZXJzaW1wYW4gZGFsYW0gZm9ybWF0IC54bHMgYXRhdSAueGxzeC4gVW50dWsgbWVuZ2ltcG9yIGF0YXUgbWVuZ2Vrc3BvciBleGNlbCBtZW5nZ3VuYWthbiBSIGJpc2EgbWVuZ2d1bmFrYW4gY2FyYSBzZWJhZ2FpIGJlcmlrdXQgOg0KDQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKGMoInJlYWR4bCIsICJ3cml0ZXhsIikpICAgICAgICMgaW5zdGFsbCBgcmVhZHhsICYgd3JpdGV4bGAgDQpwYWNtYW46OnBfbG9hZChyZWFkeGwsIHdyaXRleGwpICAgICAgICAgICAgICAgICAjIGxvYWQgYHJlYWR4bCAmIHdyaXRleGxgDQoNCiMgaW1wb3IgZGF0YQ0KZGYzPC1yZWFkX2V4Y2VsKCJpbnB1dC9pbnB1dDQueGxzIikgICAgICAgICAgICAgIyBpbXBvciBkYXRhIHhscyAoOTctMjAwMykNCmRmNDwtcmVhZF9leGNlbCgiaW5wdXQvaW5wdXQzLnhsc3giLHNoZWV0PTEpICAgICMgaW1wb3IgZGF0YSB4bHN4ICgyMDAzLXVwKQ0KDQojIGVrc3BvciBkYXRhDQp3cml0ZV94bHN4KGRmMywib3V0cHV0L291dHB1dDQueGxzIikgDQp3cml0ZV94bHN4KGRmNCwib3V0cHV0L291dHB1dDMueGxzeCIpDQpgYGANCg0KIyBJbXBvci9Fa3Nwb3IgVFhUIGFuZCBSRFMNCg0KVWt1cmFuIGZpbGUgVFhUIGRhbiBSRFMgbGViaWggcmluZ2FuIGRhcmlwYWRhIENTViBhdGF1cHVuIFhMU1guIE1ha2EsIGNhcmEgaW5pIHNhbmdhdCBzZXN1YWkgZGVuZ2FuIGtpdGEgeWFuZyB0aWRhayBpbmdpbiBtZW55aW1wYW4gZmlsZSBkZW5nYW4gdWt1cmFuIGJlc2FyLiBCZXJpa3V0IGNhcmEgaW1wb3IvZWtzcG9yIFRYVCBkYW4gUkRTIDoNCg0KYGBge3J9DQojIGltcG9yIGRhdGENCmRmNSA8LSByZWFkLnRhYmxlKCJpbnB1dC9pbnB1dDUudHh0IikgICAgICAgICAgICAgICAgIyBmb3JtYXQgVFhUIChub3RlcGFkKQ0KZGY2IDwtIHNvdXJjZSgiaW5wdXQvaW5wdXQ2LlJkbXBkIikgICAgICAgICAgICAgICAgICAjIGZvcm1hdCBUWFQgKFJkbXBkKQ0KZGY3IDwtIHJlYWRSRFMoImlucHV0L2lucHV0Ny5yZHMiKSAgICAgICAgICAgICAgICAgICAjIGZvcm1hdCBiaW5hcnkgUkRTDQpkZjggPC0gcmVhZFJEUygiaW5wdXQvaW5wdXQ4LmFzY2lpIikgICAgICAgICAgICAgICAgICMgZm9ybWF0IGJpbmFyeSBBU0NJSQ0KDQojIGVrc3BvciBkYXRhDQp3cml0ZS50YWJsZShkZjUsIm91dHB1dC9vdXRwdXQ1LnR4dCIpDQpkdW1wKCJkZjYiLCAib3V0cHV0L291dHB1dDYuUmRtcGQiKQ0Kc2F2ZVJEUyhkZjcsICJvdXRwdXQvb3V0cHV0Ny5yZHMiKQ0Kc2F2ZVJEUyhkZjgsICJvdXRwdXQvb3V0cHV0OC5hc2NpaSIsIGFzY2lpID0gVFJVRSkNCmBgYA0KDQojIEltcG9yL0Vrc3BvciBYTUwNCg0KRXh0ZW5zaWJsZSBNYXJrdXAgTGFuZ3VhZ2UgKFhNTCkgYmlzYSBtZW1iYW50dSBraXRhIG1lbWFoYW1pIHN0cnVrdHVyIGRhdGEgZGFzYXIgc3VhdHUgZmlsZS4gWE1MIG1pcmlwIGRlbmdhbiBIVE1MIGhhbnlhIHNhamEgZnVuZ3NpbnlhIGJlcmJlZGEuIFhNTCBiZXJmdW5nc2kgdW50dWsgbWVueWltcGFuIGRhbiBtZW5naXJpbWthbiBkYXRhIChpbXBvci9la3Nwb3IpLiBTZWRhbmdrYW4sIEhUTUwgYmVyZnVuZ3NpIHVudHVrIG1lbmFtcGlsa2FuIGRhdGEuIFVudHVrIG1lbmdldGFodWkgcHJvc2VzIGltcG9yL2Vrc3BvciBYTUwsIHBlcmhhdGlrYW4gY2FyYSBiZXJpa3V0IGluaSA6DQoNCmBgYHtyfQ0KbGlicmFyeSgiWE1MIikNCmxpYnJhcnkoImt1bGlmZSIpDQpsaWJyYXJ5KCJtZXRob2RzIikNCg0KZGY5IDwtIHhtbFBhcnNlKCJpbnB1dC9pbnB1dDkueG1sIikNCnhtbF9kYXRhZnJhbWUgPC0geG1sVG9EYXRhRnJhbWUoZGY5KQ0Kd3JpdGUueG1sKHhtbF9kYXRhZnJhbWUsICJvdXRwdXQvb3V0cHV0OS54bWwiKQ0KYGBgDQoNCiMgSW1wb3IvRWtzcG9yIEpTT04NCg0KSmF2YVNjcmlwdCBPYmplY3QgTm90YXRpb24gKEpTT04pIGJpYXNhbnlhIGRpZ3VuYWthbiB1bnR1ayBtZW50cmFuc2ZlciBkYXRhIGRhbiBiaXNhIGRpYmFjYSBvbGVoIHBlbmVyaW1hIGRhdGEuIFVudHVrIG1lbWJhY2EgZmlsZSBKU09OIGJpc2EgbWVuZ2d1bmFrYW4gUiBkZW5nYW4gcGFrZXQgJ2pzb25saXRlJy4gUGVyaGF0aWthbiBjYXJhIGltcG9yL2Vrc3BvciBiZXJpa3V0IGluaSA6DQoNCmBgYHtyfQ0KbGlicmFyeSgianNvbmxpdGUiKQ0KDQpkZjEwIDwtIGZyb21KU09OKCJpbnB1dC9pbnB1dDEwLmpzb24iKQ0KanNvbl9kYXRhZnJhbWUgPC0gYXMuZGF0YS5mcmFtZShkZjEwKQ0Kd3JpdGVfanNvbihqc29uX2RhdGFmcmFtZSwgIm91dHB1dC9vdXRwdXQxMC5qc29uIikNCmBgYA0KDQojIEltcG9yIERhdGEgZGFyaSBXZWINCg0KRGFsYW0gaW50ZXJuZXQgdGVyZGFwYXQgd2Vic2l0ZSB5YW5nIG1lbWJlcmlrYW4gaW5mb3JtYXNpIHN1YXR1IGRhdGEuIEJpYXNhbnlhIGRhdGEgdGVyc2VidXQgZGlndW5ha2FuIG9sZWggcGVuZ2d1bmFueWEuIEtpdGEgYmlzYSBtZW5naW1wb3IgZGF0YSB0ZXJzZWJ1dCBtZW5nZ3VuYWthbiBSIGRlbmdhbiBjYXJhIGJlcmlrdXQgaW5pIDoNCg0KIyMgQ1NWDQoNCmBgYHtyfQ0Kd2ViX2NzdiA8LSByZWFkLmNzdigiaHR0cHM6Ly9naXRodWIuY29tL0Jha3RpLVNpcmVnYXIvZGF0YXNldC9yYXcvbWFzdGVyL0Jvb2tkb3duLURhdGEtU2NpZW5jZS1mb3ItQmVnaW5uZXJzL2NzdjEuY3N2IikNCmBgYA0KDQojIyBYTFNYDQoNCmBgYHtyfQ0KbGlicmFyeShyaW8pDQppbnN0YWxsX2Zvcm1hdHMoKQ0KDQp3ZWJfeGxzeCA8LSByaW86OmltcG9ydCgiaHR0cHM6Ly9naXRodWIuY29tL0Jha3RpLVNpcmVnYXIvZGF0YXNldC9ibG9iL21hc3Rlci9Cb29rZG93bi1EYXRhLVNjaWVuY2UtZm9yLUJlZ2lubmVycy94bHN4MS54bHN4P3Jhdz10cnVlIikNCmBgYA0KDQojIEJhc2lzIERhdGEgUg0KDQpTaXN0ZW0gaWFsYWgga3VtcHVsYW4ga29tcG9uZW4gc2FsaW5nIGJlcmh1YnVuZ2FuIHlhbmcgZGlzYXR1a2FuIGRlbmdhbiBzdWF0dSB0dWp1YW4uIEJhc2lzIGRhdGEgaWFsYWggb2JqZWsgeWFuZyBtZW1idXR1aGthbiBwcm9ncmFtIHNlYmFnYWkgcGVuZ2Vsb2xhbnlhLiBNYWthIGRpaGFzaWxrYW5sYWggc2lzdGVtIGJhc2lzIGRhdGEgZGFyaSBiYXNpcyBkYXRhIGRhbiBwcm9ncmFtIHRlcnNlYnV0LiBTaXN0ZW0gYmFzaXMgZGF0YSBhZGFsYWggc2lzdGVtIHlhbmcgdGVyZGlyaSBhdGFzIGt1bXB1bGFuIHRhYmVsIGRhdGEgeWFuZyBzYWxpbmcgYmVyaHVidW5nYW4gZGFuIGt1bXB1bGFuIHByb2dyYW0geWFuZyBtZW11bmdraW5rYW4gYmViZXJhcGEgcGVtYWthaSBhdGF1IHByb2dyYW0gbGFpbiB1bnR1ayBtZW5nYWtzZXMgZGFuIG1lbWFuaXB1bGFzaSB0YWJlbCB0YWJlbCBkYXRhIHRlcnNlYnV0Lg0KDQpLaXRhIGJpc2EgbWVuZ2h1YnVuZ2thbiBzdWF0dSBkYXRhIGtlIGRhdGFiYXNlIHJlbGFzaW9uYWwgbWlzYWxueWEgTXlTcWwsIE9yYWNsZSwgU1FMIFNlcnZlciwgZGFuIHNlYmFnYWlueWEgbWVuZ2d1bmFrYW4gUi4gTGFsdSBraXRhIHViYWggYmFzaXMgZGF0YW55YSBtZW5qYWRpIGRhdGEgZnJhbWUuIEppa2EgZGF0YSBzdWRhaCB0ZXJkYXBhdCBkYWxhbSBSLCBkYXRhIHRlcnNlYnV0IGJpc2EgZGlhbmFsaXNpcyBiYWhrYW4gZGltYW5pcHVsYXNpLg0KDQojIE1lbmFtYmFuZyBEYXRhIFdlYg0KDQpXZWJzY3JhcGluZyBEYXRhIGlhbGFoIHByb3NlcyBwZW5nYW1iaWxhbiBkYXRhIGRhcmkgc2VidWFoIHdlYnNpdGUuIEJlcmJlZGEgZGVuZ2FuIHdlYiBzY3JhcGluZyAoaGFueWEgbWVueWFsaW4gcGlrc2VsIHlhbmcgZGl0YW1waWxrYW4pLCB3ZWIgc2NyYXBpbmcgbWVuZ2Vrc3RyYWsga29kZSBIVE1MIHlhbmcgbWVuZGFzYXJpbnlhIHlhbmcgcGFkYSBkYXNhcm55YSBkaXNpbXBhbiBkYWxhbSBkYXRhYmFzZS4gUGVuZ2lraXNhbiBkYXRhIGluaSBkYXBhdCBtZXJlcGxpa2FzaSBzZWx1cnVoIGtvbnRlbiBkYXJpIGJlcmJhZ2FpIHNpdHVzIHdlYiB5YW5nIHRhcmdldC4=