Review objek R

Mode Data

Berikut adalah beberapa mode data yang digunakan dalam objek data

numerik = 1.2e-2 
is.numeric(numerik)
[1] TRUE
kompleks = 1.2e6+2i
is.complex(kompleks)  
[1] TRUE
karakter = "IPB"
is.character(karakter)
[1] TRUE
logis = T
is.logical(logis)
[1] TRUE

Dalam penulisan bilangan float/ memiliki koma menggunakan tanda titik(.), misal 2,3 ditulis 2.3 . bilangan dapat dituliskan dalam notasi scientific. bilangan kompleks memiliki i yang merupakan bilangan imajiner (i=sqrt(-1)). pada mode karakter penulisan kutip harus konsisten tidak boleh "…’ (jenis kutip berbeda). logical/boolean dapat dituliskan seperti berikut T,F,TRUE,FALSE.

Objek Data Standar

Vektor

Vektor merupakan objek data dengan 1 dimensi yang semua anggotanya memiliki mode yang sama. Misal semua anggota vektor memiliki mode numerik atau semua anggota vektor memiliki mode karakter, tidak dapat dicampur

vektor = 1:10
vektor
 [1]  1  2  3  4  5  6  7  8  9 10

Matriks

matriks memiliki 2 dimensi yang dapat berupa kumpulan vektor yang akan membentuk persegi panjang berukuran nxp. Semua elemen matriks memiliki mode yang sama.

matriks = matrix(1:20,ncol=4,byrow = T)
matriks
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8
[3,]    9   10   11   12
[4,]   13   14   15   16
[5,]   17   18   19   20

untuk mengakses elemen matriks dapat digunakan nama.matriks[baris,kolom].

matriks[4,3]
[1] 15

contoh di atas untuk mengambil elemen yang berada pada baris ke-4 dan kolom ke-3.

Array

Array memiliki lebih dari 2 dimensi serta mode yang sama.

array1 = Titanic
array1
, , Age = Child, Survived = No

      Sex
Class  Male Female
  1st     0      0
  2nd     0      0
  3rd    35     17
  Crew    0      0

, , Age = Adult, Survived = No

      Sex
Class  Male Female
  1st   118      4
  2nd   154     13
  3rd   387     89
  Crew  670      3

, , Age = Child, Survived = Yes

      Sex
Class  Male Female
  1st     5      1
  2nd    11     13
  3rd    13     14
  Crew    0      0

, , Age = Adult, Survived = Yes

      Sex
Class  Male Female
  1st    57    140
  2nd    14     80
  3rd    75     76
  Crew  192     20

Array1 memiliki 4 dimensi.

Faktor/Ordered

Faktor untuk data berskala nominal yang memiliki kelompok (levels), namun antar kelompok tidak memiliki urutan

faktor = factor(c("p","l","l","p","l"))
faktor
[1] p l l p l
Levels: l p

Ordered untuk data berskala ordinal yang memiliki kelompok (levels) dan antar kelompok memiliki urutan

ordered1 = ordered(c("SD","SMP","SD","SMA","SMP"),levels=c("SD","SMP","SMA"))
ordered1
[1] SD  SMP SD  SMA SMP
Levels: SD < SMP < SMA

List

List merupakan kumpulan beberapa objek yang dapat memiliki jenis yang berbeda

list1 = list(ordered1,matriks,vektor)
list1
[[1]]
[1] SD  SMP SD  SMA SMP
Levels: SD < SMP < SMA

[[2]]
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8
[3,]    9   10   11   12
[4,]   13   14   15   16
[5,]   17   18   19   20

[[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

untuk mengakses list dapat menggunakan nama.list[[objek]][elemen] seperti berikut

list1[[1]][3]
[1] SD
Levels: SD < SMP < SMA

contoh di atas untuk mengambil objek ke-1 dan elemen yang berada pada urutan ke-3.

Data Frame

Data frame merupakan data dalam format tabel yang semua anggota dalam 1 kolom memiliki mode yang sama sementara antar kolom boleh memiliki mode yang berbeda. setiap kolom harus memiliki jumlah yang sama (jumlah baris sama).

dataframe = data.frame(X=rep(c("A","B","C","D","E"),2),vektor)
dataframe

untuk mengakses data frame dapat menggunakan nama.dataframe$nama.kolom

dataframe$X
 [1] "A" "B" "C" "D" "E" "A" "B" "C"
 [9] "D" "E"

Struktur Kendali: Eksekusi Bersyarat

Pernyataan IF

if (kondisi) ekspresi (T) [else ekspresi (F)]

y=2
if(y>0) y=2*y
y
[1] 4

Fungsi ifelse

x <- ifelse(kondisi, nilai jika T, nilai jika F)

x = 2
nilai <- ifelse(x>0, "positif", "negatif")
nilai
[1] "positif"

Fungsi switch

digunakan untuk mengganti metode perhitugan sesuai dengan tipe yang dipilih.

centre <- function(x, type) {
  switch(type,
         mean = mean(x),
         median = median(x),
         trimmed = mean(x, trim = .1))
}
dt <- c(1, 2, 2, 3, 4, 4, 5, 6, 8, 9)
dt_mean <- centre(dt, "mean")
dt_median <- centre(dt, "median")
dt_trimmed <- centre(dt, "trimmed")
data.frame(dt_mean,dt_median,dt_trimmed)
centre(dt,"median")
[1] 4

Struktur Kendali: Loops

Pernyataan for

digunakan ketika pengulangan diketahui jumlahnya dengan bentuk umum berikut: for (objek in sekuens) ekspresi

kuadrat<-c()
for (i in 1:10){
  kuadrat[i] <- i^2
}
kuadrat
 [1]   1   4   9  16  25  36  49  64
 [9]  81 100

Pernyataan while

digunakan ketika pengulangan tidak diketahui jumlahnya dan minimal pengulangan = 0. ekspresi bisa tidak dijalankan apabila kondisi while tidak terpenuhi (bernilai FALSE). Bentuk umum while: while (condition) ekspresi

i <- length(kuadrat)
akar <- c()
while (i>0){
  akar[i] <- sqrt(kuadrat[i])
  i <- i-1
}
akar
 [1]  1  2  3  4  5  6  7  8  9 10

Pernyataan repeat

digunakan ketika pengulangan tidak diketahui jumlahnya dan minimal pengulangan = 1. Bentuk umum repeat: repeat ekspresi (untuk menghentikan gunakan perintah break)

repeat{
  i<-i+1
  print(kuadrat[i])
  if (i==8) {break()}
}
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
[1] 36
[1] 49
[1] 64

Fungsi di R

Berikut adalah beberapa fungsi yang telah disiapkan oleh R (built-in).

Manajemen data dan utilitas

x = c(1,3,2,4,8,5,6,9,7)
sort(x,decreasing = F)
[1] 1 2 3 4 5 6 7 8 9
rev(x)
[1] 7 9 6 5 8 4 2 3 1

sort untuk mengurutkan data. rev untuk mereverse data, membalik urutan data (data terakhir menjadi data pertama, data kedua terakhir menjadi data kedua, dst).

Aritmetika

log(x)
[1] 0.0000000 1.0986123 0.6931472
[4] 1.3862944 2.0794415 1.6094379
[7] 1.7917595 2.1972246 1.9459101
sqrt(x)
[1] 1.000000 1.732051 1.414214
[4] 2.000000 2.828427 2.236068
[7] 2.449490 3.000000 2.645751

log untuk menghitung nilai logaritma dari data. sqrt untuk menghitung nilai akar kuadrat dari data.

Statistik

sum(x)
[1] 45
mean(x)
[1] 5
var(x)
[1] 7.5
sd(x)
[1] 2.738613

sum untuk menghitung jumlah data. mean untuk menghitung rata-rata data. var untuk menghitung ragam data. sd untuk menghitung standar deviasi data.

grafik

berikut adalah beberapa fungsi untuk membuat grafik.

histogram

hist(x)

Boxplot

boxplot(x)

Menciptakan Fungsi Sendiri

Dapat membuat fungsi sendiri sesuai dengan kebutuhan analisis dengan bentuk umum: namafungsi <- function (argumen) isifungsi

#Membuat fungsi simpangan baku 
simpangan.baku <- function(x) sqrt(var(x))
simpangan.baku(x)
[1] 2.738613

contoh di atas merupakan fungsi untuk menghitung simpangan baku yang memiliki nilai akar dari ragam/var. Penggunaan fungsi dengan memanggil nama fungsi beserta argumennya dengan bentuk umum: namafungsi(arg1, arg2, …)

Argumen Fungsi

Pada contoh sebelumnya fungsi memiliki 1 nilai argumen yaitu x dan tidak diatur nilai defaultnya. Berikut adalah contoh fungsi yang didefinisikan nilai defaultnya, yaitu x=2.

fgs_3 <- function(x=2,y){x*y}
fgs_3(3,3) #argumen lengkap
[1] 9
fgs_3(,3) #argumen tidak lengkap
[1] 6
fgs_3(y=3) #penulisan argumen tidak lengkap yang lebih tepat
[1] 6

Output/Luaran Fungsi

Output/luaran dari fungsi adalah objek

fungsi1 <- function(x) {
  y = x^2
  z = sum(y)
  list(y,z) #dapat ditulis: return(list(y,z))
}
fungsi1(x)
[[1]]
[1]  1  9  4 16 64 25 36 81 49

[[2]]
[1] 285

y merupakan nilai kuadrat dari setiap unsur x dan z merupakan jumlah kuadrat dari x.

Penanganan Kesalahan

try

try: pembungkus untuk menjalankan ekspresi yang mungkin gagal dan memungkinkan kode pengguna untuk menangani pemulihan kesalahan

try(log("not a number"), silent = T)
print("errors can't stop me")
[1] "errors can't stop me"

peringatan error dapat tidak ditampilkan dan langsung menjalankan perintah pada baris berikutnya.

tryCatch

tryCatch: menyediakan mekanisme untuk menangani kondisi yang tidak biasa, termasuk kesalahan dan peringatan

tryCatch(log(10), finally = print("Hello"))
[1] "Hello"
[1] 2.302585

warning

warning: menghasilkan pesan peringatan yang sesuai dengan argumennya

warning("bad weather today, don't forget your umbrella")
bad weather today, don't forget your umbrella

stop

stop: menghentikan eksekusi ekspresi saat ini

if (1 != 2)
  stop("something is wrong")
Error: something is wrong

Teladan Membuat Fungsi

Membuat Fungsi untuk Melakukan Pengujian Hipotesis Nilai Tengah untuk Dua Populasi dengan ragam sama. Algoritma : 1 hitung masing-masing n 2 hitung galat baku 3 hitung statistik uji 4 hitung nilai-p 5 tetapkan keputusan penerimaan atau penolakan H0

ttest <- function(y1,y2,test="dua-arah",alpha=0.05) {
  n1 <- length(y1); n2 <- length(y2)
  ndf <- n1+n2-2
  s2 <- ((n1-1)*var(y1) + (n2-1)*var(y2))/ndf
  tstat <- (mean(y1)-mean(y2))/sqrt(s2*(1/n1+1/n2))
  tail.area <- switch(test,
                      "dua-arah"=2*(1-pt(abs(tstat),ndf)),
                      kecil=pt(tstat,ndf),
                      besar=1-pt(tstat,ndf),
                      {
                        warning("uji harus 'dua-arah', 'kecil' atau 'besar'")
                        NULL
                      }
                      )
  list(tstat=tstat,df=ndf,reject=if(!is.null(tail.area))
    tail.area < alpha, tail.area=tail.area)
}
x <- c(5,6,4,5,3,6,7)
y <- c(6,7,4,6,3,5,4)
ttest(x,y)
$tstat
[1] 0.1936492

$df
[1] 12

$reject
[1] FALSE

$tail.area
[1] 0.8496898

Output fungsi di atas terdiri dari tstat (tvalue), df (derajat bebas), reject (keputusan untuk tolak H0 atau tak tolak H0), dan tail.area (pvalue).

Package R

Sebuah ekstensi dari sistem dasar R dengan kode, data dan dokumentasi dalam format standar. Paket-paket R merupakan cara yang untuk memelihara koleksi fungsi dan data set R dan untuk menyebarluaskannya.

Instalasi Package R

Berikut adalah cara menginstall package R

install.packages("MASS")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into 㤼㸱C:/Users/fahmi/OneDrive/Documents/R/win-library/4.1㤼㸲
(as 㤼㸱lib㤼㸲 is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/MASS_7.3-56.zip'
Content type 'application/zip' length 1189141 bytes (1.1 MB)
downloaded 1.1 MB
package ‘MASS’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\fahmi\AppData\Local\Temp\RtmpoxXATa\downloaded_packages

Menggunakan Package R

Berikut adalah cara menggunakan atau menjalankan package R

library(MASS)
data(npk)
npk

Beberapa package memiliki dataset yang dapat diakses dengan memanggil nama objek dataset tersebut.

Berikut adalah cara untuk melepas (unload) package R

detach("package:MASS")

  1. Mahasiswa Statistika dan Sains Data IPB, ↩︎

LS0tDQp0aXRsZTogIlBlbmdhbnRhciBQZW1yb2dyYW1hbiBGdW5nc2kgUiINCmF1dGhvcjogIkFubmlzc2EgTnVyIEZpdHJpYSBGYXRoaW5hXltNYWhhc2lzd2EgU3RhdGlzdGlrYSBkYW4gU2FpbnMgRGF0YSBJUEIsIGFubmlzc2FfbmZmQGFwcHMuaXBiLmFjLmlkXSINCmRhdGU6ICIzMC8zLzIwMjIiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdGhlbWU6IGJvb3RzdHJhcA0KICAgIGhpZ2hsaWdodDogZXNwcmVzc28NCi0tLQ0KDQojIFJldmlldyBvYmplayBSDQoNCiMjIE1vZGUgRGF0YQ0KDQpCZXJpa3V0IGFkYWxhaCBiZWJlcmFwYSBtb2RlIGRhdGEgeWFuZyBkaWd1bmFrYW4gZGFsYW0gb2JqZWsgZGF0YQ0KDQpgYGB7cn0NCm51bWVyaWsgPSAxLjJlLTIgDQppcy5udW1lcmljKG51bWVyaWspDQprb21wbGVrcyA9IDEuMmU2KzJpDQppcy5jb21wbGV4KGtvbXBsZWtzKSAgDQprYXJha3RlciA9ICJJUEIiDQppcy5jaGFyYWN0ZXIoa2FyYWt0ZXIpDQpsb2dpcyA9IFQNCmlzLmxvZ2ljYWwobG9naXMpDQpgYGANCg0KRGFsYW0gcGVudWxpc2FuIGJpbGFuZ2FuIGZsb2F0LyBtZW1pbGlraSBrb21hIG1lbmdndW5ha2FuIHRhbmRhIHRpdGlrKC4pLCBtaXNhbCAyLDMgZGl0dWxpcyAyLjMgLiBiaWxhbmdhbiBkYXBhdCBkaXR1bGlza2FuIGRhbGFtIG5vdGFzaSBzY2llbnRpZmljLiBiaWxhbmdhbiBrb21wbGVrcyBtZW1pbGlraSBpIHlhbmcgbWVydXBha2FuIGJpbGFuZ2FuIGltYWppbmVyIChpPXNxcnQoLTEpKS4gcGFkYSBtb2RlIGthcmFrdGVyIHBlbnVsaXNhbiBrdXRpcCBoYXJ1cyBrb25zaXN0ZW4gdGlkYWsgYm9sZWggIi4uLicgKGplbmlzIGt1dGlwIGJlcmJlZGEpLiBsb2dpY2FsL2Jvb2xlYW4gZGFwYXQgZGl0dWxpc2thbiBzZXBlcnRpIGJlcmlrdXQgVCxGLFRSVUUsRkFMU0UuDQoNCiMjIE9iamVrIERhdGEgU3RhbmRhcg0KDQojIyMgVmVrdG9yDQoNClZla3RvciBtZXJ1cGFrYW4gb2JqZWsgZGF0YSBkZW5nYW4gMSBkaW1lbnNpIHlhbmcgc2VtdWEgYW5nZ290YW55YSBtZW1pbGlraSBtb2RlIHlhbmcgc2FtYS4gTWlzYWwgc2VtdWEgYW5nZ290YSB2ZWt0b3IgbWVtaWxpa2kgbW9kZSBudW1lcmlrIGF0YXUgc2VtdWEgYW5nZ290YSB2ZWt0b3IgbWVtaWxpa2kgbW9kZSBrYXJha3RlciwgdGlkYWsgZGFwYXQgZGljYW1wdXINCg0KYGBge3J9DQp2ZWt0b3IgPSAxOjEwDQp2ZWt0b3INCmBgYA0KDQojIyMgTWF0cmlrcw0KDQptYXRyaWtzIG1lbWlsaWtpIDIgZGltZW5zaSB5YW5nIGRhcGF0IGJlcnVwYSBrdW1wdWxhbiB2ZWt0b3IgeWFuZyBha2FuIG1lbWJlbnR1ayBwZXJzZWdpIHBhbmphbmcgYmVydWt1cmFuIG54cC4gU2VtdWEgZWxlbWVuIG1hdHJpa3MgbWVtaWxpa2kgbW9kZSB5YW5nIHNhbWEuDQoNCmBgYHtyfQ0KbWF0cmlrcyA9IG1hdHJpeCgxOjIwLG5jb2w9NCxieXJvdyA9IFQpDQptYXRyaWtzDQpgYGANCg0KdW50dWsgbWVuZ2Frc2VzIGVsZW1lbiBtYXRyaWtzIGRhcGF0IGRpZ3VuYWthbiBuYW1hLm1hdHJpa3NbYmFyaXMsa29sb21dLg0KDQpgYGB7cn0NCm1hdHJpa3NbNCwzXQ0KYGBgDQoNCmNvbnRvaCBkaSBhdGFzIHVudHVrIG1lbmdhbWJpbCBlbGVtZW4geWFuZyBiZXJhZGEgcGFkYSBiYXJpcyBrZS00IGRhbiBrb2xvbSBrZS0zLg0KDQojIyMgQXJyYXkNCg0KQXJyYXkgbWVtaWxpa2kgbGViaWggZGFyaSAyIGRpbWVuc2kgc2VydGEgbW9kZSB5YW5nIHNhbWEuDQoNCmBgYHtyfQ0KYXJyYXkxID0gVGl0YW5pYw0KYXJyYXkxDQpgYGANCg0KQXJyYXkxIG1lbWlsaWtpIDQgZGltZW5zaS4NCg0KIyMjIEZha3Rvci9PcmRlcmVkDQoNCkZha3RvciB1bnR1ayBkYXRhIGJlcnNrYWxhIG5vbWluYWwgeWFuZyBtZW1pbGlraSBrZWxvbXBvayAobGV2ZWxzKSwgbmFtdW4gYW50YXIga2Vsb21wb2sgdGlkYWsgbWVtaWxpa2kgdXJ1dGFuDQoNCmBgYHtyfQ0KZmFrdG9yID0gZmFjdG9yKGMoInAiLCJsIiwibCIsInAiLCJsIikpDQpmYWt0b3INCmBgYA0KDQpPcmRlcmVkIHVudHVrIGRhdGEgYmVyc2thbGEgb3JkaW5hbCB5YW5nIG1lbWlsaWtpIGtlbG9tcG9rIChsZXZlbHMpIGRhbiBhbnRhciBrZWxvbXBvayBtZW1pbGlraSB1cnV0YW4NCg0KYGBge3J9DQpvcmRlcmVkMSA9IG9yZGVyZWQoYygiU0QiLCJTTVAiLCJTRCIsIlNNQSIsIlNNUCIpLGxldmVscz1jKCJTRCIsIlNNUCIsIlNNQSIpKQ0Kb3JkZXJlZDENCmBgYA0KDQojIyMgTGlzdA0KDQpMaXN0IG1lcnVwYWthbiBrdW1wdWxhbiBiZWJlcmFwYSBvYmplayB5YW5nIGRhcGF0IG1lbWlsaWtpIGplbmlzIHlhbmcgYmVyYmVkYQ0KDQpgYGB7cn0NCmxpc3QxID0gbGlzdChvcmRlcmVkMSxtYXRyaWtzLHZla3RvcikNCmxpc3QxDQpgYGANCg0KdW50dWsgbWVuZ2Frc2VzIGxpc3QgZGFwYXQgbWVuZ2d1bmFrYW4gbmFtYS5saXN0W1tvYmpla11dW2VsZW1lbl0gc2VwZXJ0aSBiZXJpa3V0DQoNCmBgYHtyfQ0KbGlzdDFbWzFdXVszXQ0KYGBgDQoNCmNvbnRvaCBkaSBhdGFzIHVudHVrIG1lbmdhbWJpbCBvYmplayBrZS0xIGRhbiBlbGVtZW4geWFuZyBiZXJhZGEgcGFkYSB1cnV0YW4ga2UtMy4NCg0KIyMjIERhdGEgRnJhbWUNCg0KRGF0YSBmcmFtZSBtZXJ1cGFrYW4gZGF0YSBkYWxhbSBmb3JtYXQgdGFiZWwgeWFuZyBzZW11YSBhbmdnb3RhIGRhbGFtIDEga29sb20gbWVtaWxpa2kgbW9kZSB5YW5nIHNhbWEgc2VtZW50YXJhIGFudGFyIGtvbG9tIGJvbGVoIG1lbWlsaWtpIG1vZGUgeWFuZyBiZXJiZWRhLiBzZXRpYXAga29sb20gaGFydXMgbWVtaWxpa2kganVtbGFoIHlhbmcgc2FtYSAoanVtbGFoIGJhcmlzIHNhbWEpLg0KDQpgYGB7cn0NCmRhdGFmcmFtZSA9IGRhdGEuZnJhbWUoWD1yZXAoYygiQSIsIkIiLCJDIiwiRCIsIkUiKSwyKSx2ZWt0b3IpDQpkYXRhZnJhbWUNCmBgYA0KDQp1bnR1ayBtZW5nYWtzZXMgZGF0YSBmcmFtZSBkYXBhdCBtZW5nZ3VuYWthbiBuYW1hLmRhdGFmcmFtZVwkbmFtYS5rb2xvbQ0KDQpgYGB7cn0NCmRhdGFmcmFtZSRYDQpgYGANCg0KIyMgU3RydWt0dXIgS2VuZGFsaTogRWtzZWt1c2kgQmVyc3lhcmF0DQoNCiMjIyBQZXJueWF0YWFuIElGDQoNCmlmIChrb25kaXNpKSBla3NwcmVzaSAoVCkgW2Vsc2UgZWtzcHJlc2kgKEYpXQ0KDQpgYGB7cn0NCnk9Mg0KaWYoeT4wKSB5PTIqeQ0KeQ0KYGBgDQoNCiMjIyBGdW5nc2kgaWZlbHNlDQoNCnggXDwtIGlmZWxzZShrb25kaXNpLCBuaWxhaSBqaWthIFQsIG5pbGFpIGppa2EgRikNCg0KYGBge3J9DQp4ID0gMg0KbmlsYWkgPC0gaWZlbHNlKHg+MCwgInBvc2l0aWYiLCAibmVnYXRpZiIpDQpuaWxhaQ0KYGBgDQoNCiMjIyBGdW5nc2kgc3dpdGNoDQoNCmRpZ3VuYWthbiB1bnR1ayBtZW5nZ2FudGkgbWV0b2RlIHBlcmhpdHVnYW4gc2VzdWFpIGRlbmdhbiB0aXBlIHlhbmcgZGlwaWxpaC4NCg0KYGBge3J9DQpjZW50cmUgPC0gZnVuY3Rpb24oeCwgdHlwZSkgew0KICBzd2l0Y2godHlwZSwNCiAgICAgICAgIG1lYW4gPSBtZWFuKHgpLA0KICAgICAgICAgbWVkaWFuID0gbWVkaWFuKHgpLA0KICAgICAgICAgdHJpbW1lZCA9IG1lYW4oeCwgdHJpbSA9IC4xKSkNCn0NCmR0IDwtIGMoMSwgMiwgMiwgMywgNCwgNCwgNSwgNiwgOCwgOSkNCmR0X21lYW4gPC0gY2VudHJlKGR0LCAibWVhbiIpDQpkdF9tZWRpYW4gPC0gY2VudHJlKGR0LCAibWVkaWFuIikNCmR0X3RyaW1tZWQgPC0gY2VudHJlKGR0LCAidHJpbW1lZCIpDQpkYXRhLmZyYW1lKGR0X21lYW4sZHRfbWVkaWFuLGR0X3RyaW1tZWQpDQpgYGANCg0KYGBge3J9DQpjZW50cmUoZHQsIm1lZGlhbiIpDQpgYGANCg0KIyMgU3RydWt0dXIgS2VuZGFsaTogTG9vcHMNCg0KIyMjIFBlcm55YXRhYW4gZm9yDQoNCmRpZ3VuYWthbiBrZXRpa2EgcGVuZ3VsYW5nYW4gZGlrZXRhaHVpIGp1bWxhaG55YSBkZW5nYW4gYmVudHVrIHVtdW0gYmVyaWt1dDogZm9yIChvYmplayBpbiBzZWt1ZW5zKSBla3NwcmVzaQ0KDQpgYGB7cn0NCmt1YWRyYXQ8LWMoKQ0KZm9yIChpIGluIDE6MTApew0KICBrdWFkcmF0W2ldIDwtIGleMg0KfQ0Ka3VhZHJhdA0KYGBgDQoNCiMjIyBQZXJueWF0YWFuIHdoaWxlDQoNCmRpZ3VuYWthbiBrZXRpa2EgcGVuZ3VsYW5nYW4gdGlkYWsgZGlrZXRhaHVpIGp1bWxhaG55YSBkYW4gbWluaW1hbCBwZW5ndWxhbmdhbiA9IDAuIGVrc3ByZXNpIGJpc2EgdGlkYWsgZGlqYWxhbmthbiBhcGFiaWxhIGtvbmRpc2kgd2hpbGUgdGlkYWsgdGVycGVudWhpIChiZXJuaWxhaSBGQUxTRSkuIEJlbnR1ayB1bXVtIHdoaWxlOiB3aGlsZSAoY29uZGl0aW9uKSBla3NwcmVzaQ0KDQpgYGB7cn0NCmkgPC0gbGVuZ3RoKGt1YWRyYXQpDQpha2FyIDwtIGMoKQ0Kd2hpbGUgKGk+MCl7DQogIGFrYXJbaV0gPC0gc3FydChrdWFkcmF0W2ldKQ0KICBpIDwtIGktMQ0KfQ0KYWthcg0KYGBgDQoNCiMjIyBQZXJueWF0YWFuIHJlcGVhdA0KDQpkaWd1bmFrYW4ga2V0aWthIHBlbmd1bGFuZ2FuIHRpZGFrIGRpa2V0YWh1aSBqdW1sYWhueWEgZGFuIG1pbmltYWwgcGVuZ3VsYW5nYW4gPSAxLiBCZW50dWsgdW11bSByZXBlYXQ6IHJlcGVhdCBla3NwcmVzaSAodW50dWsgbWVuZ2hlbnRpa2FuIGd1bmFrYW4gcGVyaW50YWggYnJlYWspDQoNCmBgYHtyfQ0KcmVwZWF0ew0KICBpPC1pKzENCiAgcHJpbnQoa3VhZHJhdFtpXSkNCiAgaWYgKGk9PTgpIHticmVhaygpfQ0KfQ0KYGBgDQoNCiMgRnVuZ3NpIGRpIFINCg0KQmVyaWt1dCBhZGFsYWggYmViZXJhcGEgZnVuZ3NpIHlhbmcgdGVsYWggZGlzaWFwa2FuIG9sZWggUiAoYnVpbHQtaW4pLg0KDQojIyBNYW5hamVtZW4gZGF0YSBkYW4gdXRpbGl0YXMNCg0KYGBge3J9DQp4ID0gYygxLDMsMiw0LDgsNSw2LDksNykNCnNvcnQoeCxkZWNyZWFzaW5nID0gRikNCnJldih4KQ0KYGBgDQoNCnNvcnQgdW50dWsgbWVuZ3VydXRrYW4gZGF0YS4gcmV2IHVudHVrIG1lcmV2ZXJzZSBkYXRhLCBtZW1iYWxpayB1cnV0YW4gZGF0YSAoZGF0YSB0ZXJha2hpciBtZW5qYWRpIGRhdGEgcGVydGFtYSwgZGF0YSBrZWR1YSB0ZXJha2hpciBtZW5qYWRpIGRhdGEga2VkdWEsIGRzdCkuDQoNCiMjIEFyaXRtZXRpa2ENCg0KYGBge3J9DQpsb2coeCkNCnNxcnQoeCkNCmBgYA0KDQpsb2cgdW50dWsgbWVuZ2hpdHVuZyBuaWxhaSBsb2dhcml0bWEgZGFyaSBkYXRhLiBzcXJ0IHVudHVrIG1lbmdoaXR1bmcgbmlsYWkgYWthciBrdWFkcmF0IGRhcmkgZGF0YS4NCg0KIyMgU3RhdGlzdGlrDQoNCmBgYHtyfQ0Kc3VtKHgpDQptZWFuKHgpDQp2YXIoeCkNCnNkKHgpDQpgYGANCg0Kc3VtIHVudHVrIG1lbmdoaXR1bmcganVtbGFoIGRhdGEuIG1lYW4gdW50dWsgbWVuZ2hpdHVuZyByYXRhLXJhdGEgZGF0YS4gdmFyIHVudHVrIG1lbmdoaXR1bmcgcmFnYW0gZGF0YS4gc2QgdW50dWsgbWVuZ2hpdHVuZyBzdGFuZGFyIGRldmlhc2kgZGF0YS4NCg0KIyMgZ3JhZmlrDQoNCmJlcmlrdXQgYWRhbGFoIGJlYmVyYXBhIGZ1bmdzaSB1bnR1ayBtZW1idWF0IGdyYWZpay4NCg0KIyMjIGhpc3RvZ3JhbQ0KDQpgYGB7cn0NCmhpc3QoeCkNCmBgYA0KDQojIyMgQm94cGxvdA0KDQpgYGB7cn0NCmJveHBsb3QoeCkNCmBgYA0KDQojIE1lbmNpcHRha2FuIEZ1bmdzaSBTZW5kaXJpDQoNCkRhcGF0IG1lbWJ1YXQgZnVuZ3NpIHNlbmRpcmkgc2VzdWFpIGRlbmdhbiBrZWJ1dHVoYW4gYW5hbGlzaXMgZGVuZ2FuIGJlbnR1ayB1bXVtOiBuYW1hZnVuZ3NpIFw8LSBmdW5jdGlvbiAoYXJndW1lbikgaXNpZnVuZ3NpDQoNCmBgYHtyfQ0KI01lbWJ1YXQgZnVuZ3NpIHNpbXBhbmdhbiBiYWt1IA0Kc2ltcGFuZ2FuLmJha3UgPC0gZnVuY3Rpb24oeCkgc3FydCh2YXIoeCkpDQpzaW1wYW5nYW4uYmFrdSh4KQ0KYGBgDQoNCmNvbnRvaCBkaSBhdGFzIG1lcnVwYWthbiBmdW5nc2kgdW50dWsgbWVuZ2hpdHVuZyBzaW1wYW5nYW4gYmFrdSB5YW5nIG1lbWlsaWtpIG5pbGFpIGFrYXIgZGFyaSByYWdhbS92YXIuIFBlbmdndW5hYW4gZnVuZ3NpIGRlbmdhbiBtZW1hbmdnaWwgbmFtYSBmdW5nc2kgYmVzZXJ0YSBhcmd1bWVubnlhIGRlbmdhbiBiZW50dWsgdW11bTogbmFtYWZ1bmdzaShhcmcxLCBhcmcyLCAuLi4pDQoNCiMjIEFyZ3VtZW4gRnVuZ3NpDQoNClBhZGEgY29udG9oIHNlYmVsdW1ueWEgZnVuZ3NpIG1lbWlsaWtpIDEgbmlsYWkgYXJndW1lbiB5YWl0dSB4IGRhbiB0aWRhayBkaWF0dXIgbmlsYWkgZGVmYXVsdG55YS4gQmVyaWt1dCBhZGFsYWggY29udG9oIGZ1bmdzaSB5YW5nIGRpZGVmaW5pc2lrYW4gbmlsYWkgZGVmYXVsdG55YSwgeWFpdHUgeD0yLg0KDQpgYGB7cn0NCmZnc18zIDwtIGZ1bmN0aW9uKHg9Mix5KXt4Knl9DQpmZ3NfMygzLDMpICNhcmd1bWVuIGxlbmdrYXANCmZnc18zKCwzKSAjYXJndW1lbiB0aWRhayBsZW5na2FwDQpmZ3NfMyh5PTMpICNwZW51bGlzYW4gYXJndW1lbiB0aWRhayBsZW5na2FwIHlhbmcgbGViaWggdGVwYXQNCmBgYA0KDQojIyBPdXRwdXQvTHVhcmFuIEZ1bmdzaQ0KDQpPdXRwdXQvbHVhcmFuIGRhcmkgZnVuZ3NpIGFkYWxhaCBvYmplaw0KDQpgYGB7cn0NCmZ1bmdzaTEgPC0gZnVuY3Rpb24oeCkgew0KICB5ID0geF4yDQogIHogPSBzdW0oeSkNCiAgbGlzdCh5LHopICNkYXBhdCBkaXR1bGlzOiByZXR1cm4obGlzdCh5LHopKQ0KfQ0KZnVuZ3NpMSh4KQ0KYGBgDQoNCnkgbWVydXBha2FuIG5pbGFpIGt1YWRyYXQgZGFyaSBzZXRpYXAgdW5zdXIgeCBkYW4geiBtZXJ1cGFrYW4ganVtbGFoIGt1YWRyYXQgZGFyaSB4Lg0KDQojIFBlbmFuZ2FuYW4gS2VzYWxhaGFuDQoNCiMjIHRyeQ0KDQp0cnk6IHBlbWJ1bmdrdXMgdW50dWsgbWVuamFsYW5rYW4gZWtzcHJlc2kgeWFuZyBtdW5na2luIGdhZ2FsIGRhbiBtZW11bmdraW5rYW4ga29kZSBwZW5nZ3VuYSB1bnR1ayBtZW5hbmdhbmkgcGVtdWxpaGFuIGtlc2FsYWhhbg0KDQpgYGB7cn0NCnRyeShsb2coIm5vdCBhIG51bWJlciIpLCBzaWxlbnQgPSBUKQ0KcHJpbnQoImVycm9ycyBjYW4ndCBzdG9wIG1lIikNCmBgYA0KDQpwZXJpbmdhdGFuIGVycm9yIGRhcGF0IHRpZGFrIGRpdGFtcGlsa2FuIGRhbiBsYW5nc3VuZyBtZW5qYWxhbmthbiBwZXJpbnRhaCBwYWRhIGJhcmlzIGJlcmlrdXRueWEuDQoNCiMjIHRyeUNhdGNoDQoNCnRyeUNhdGNoOiBtZW55ZWRpYWthbiBtZWthbmlzbWUgdW50dWsgbWVuYW5nYW5pIGtvbmRpc2kgeWFuZyB0aWRhayBiaWFzYSwgdGVybWFzdWsga2VzYWxhaGFuIGRhbiBwZXJpbmdhdGFuDQoNCmBgYHtyfQ0KdHJ5Q2F0Y2gobG9nKDEwKSwgZmluYWxseSA9IHByaW50KCJIZWxsbyIpKQ0KYGBgDQoNCiMjIHdhcm5pbmcNCg0Kd2FybmluZzogbWVuZ2hhc2lsa2FuIHBlc2FuIHBlcmluZ2F0YW4geWFuZyBzZXN1YWkgZGVuZ2FuIGFyZ3VtZW5ueWENCg0KYGBge3J9DQp3YXJuaW5nKCJiYWQgd2VhdGhlciB0b2RheSwgZG9uJ3QgZm9yZ2V0IHlvdXIgdW1icmVsbGEiKQ0KYGBgDQoNCiMjIHN0b3ANCg0Kc3RvcDogbWVuZ2hlbnRpa2FuIGVrc2VrdXNpIGVrc3ByZXNpIHNhYXQgaW5pDQoNCmBgYHtyfQ0KaWYgKDEgIT0gMikNCiAgc3RvcCgic29tZXRoaW5nIGlzIHdyb25nIikNCmBgYA0KDQojIFRlbGFkYW4gTWVtYnVhdCBGdW5nc2kNCg0KTWVtYnVhdCBGdW5nc2kgdW50dWsgTWVsYWt1a2FuIFBlbmd1amlhbiBIaXBvdGVzaXMgTmlsYWkgVGVuZ2FoIHVudHVrIER1YSBQb3B1bGFzaSBkZW5nYW4gcmFnYW0gc2FtYS4gQWxnb3JpdG1hIDogMSBoaXR1bmcgbWFzaW5nLW1hc2luZyBuIDIgaGl0dW5nIGdhbGF0IGJha3UgMyBoaXR1bmcgc3RhdGlzdGlrIHVqaSA0IGhpdHVuZyBuaWxhaS1wIDUgdGV0YXBrYW4ga2VwdXR1c2FuIHBlbmVyaW1hYW4gYXRhdSBwZW5vbGFrYW4gSDANCg0KYGBge3J9DQp0dGVzdCA8LSBmdW5jdGlvbih5MSx5Mix0ZXN0PSJkdWEtYXJhaCIsYWxwaGE9MC4wNSkgew0KICBuMSA8LSBsZW5ndGgoeTEpOyBuMiA8LSBsZW5ndGgoeTIpDQogIG5kZiA8LSBuMStuMi0yDQogIHMyIDwtICgobjEtMSkqdmFyKHkxKSArIChuMi0xKSp2YXIoeTIpKS9uZGYNCiAgdHN0YXQgPC0gKG1lYW4oeTEpLW1lYW4oeTIpKS9zcXJ0KHMyKigxL24xKzEvbjIpKQ0KICB0YWlsLmFyZWEgPC0gc3dpdGNoKHRlc3QsDQogICAgICAgICAgICAgICAgICAgICAgImR1YS1hcmFoIj0yKigxLXB0KGFicyh0c3RhdCksbmRmKSksDQogICAgICAgICAgICAgICAgICAgICAga2VjaWw9cHQodHN0YXQsbmRmKSwNCiAgICAgICAgICAgICAgICAgICAgICBiZXNhcj0xLXB0KHRzdGF0LG5kZiksDQogICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgd2FybmluZygidWppIGhhcnVzICdkdWEtYXJhaCcsICdrZWNpbCcgYXRhdSAnYmVzYXInIikNCiAgICAgICAgICAgICAgICAgICAgICAgIE5VTEwNCiAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgKQ0KICBsaXN0KHRzdGF0PXRzdGF0LGRmPW5kZixyZWplY3Q9aWYoIWlzLm51bGwodGFpbC5hcmVhKSkNCiAgICB0YWlsLmFyZWEgPCBhbHBoYSwgdGFpbC5hcmVhPXRhaWwuYXJlYSkNCn0NCnggPC0gYyg1LDYsNCw1LDMsNiw3KQ0KeSA8LSBjKDYsNyw0LDYsMyw1LDQpDQp0dGVzdCh4LHkpDQpgYGANCg0KT3V0cHV0IGZ1bmdzaSBkaSBhdGFzIHRlcmRpcmkgZGFyaSB0c3RhdCAodHZhbHVlKSwgZGYgKGRlcmFqYXQgYmViYXMpLCByZWplY3QgKGtlcHV0dXNhbiB1bnR1ayB0b2xhayBIMCBhdGF1IHRhayB0b2xhayBIMCksIGRhbiB0YWlsLmFyZWEgKHB2YWx1ZSkuDQoNCiMgUGFja2FnZSBSDQoNClNlYnVhaCBla3N0ZW5zaSBkYXJpIHNpc3RlbSBkYXNhciBSIGRlbmdhbiBrb2RlLCBkYXRhIGRhbiBkb2t1bWVudGFzaSBkYWxhbSBmb3JtYXQgc3RhbmRhci4gUGFrZXQtcGFrZXQgUiBtZXJ1cGFrYW4gY2FyYSB5YW5nIHVudHVrIG1lbWVsaWhhcmEga29sZWtzaSBmdW5nc2kgZGFuIGRhdGEgc2V0IFIgZGFuIHVudHVrIG1lbnllYmFybHVhc2thbm55YS4NCg0KIyMgSW5zdGFsYXNpIFBhY2thZ2UgUg0KDQpCZXJpa3V0IGFkYWxhaCBjYXJhIG1lbmdpbnN0YWxsIHBhY2thZ2UgUg0KDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoIk1BU1MiKQ0KYGBgDQoNCiMjIE1lbmdndW5ha2FuIFBhY2thZ2UgUg0KDQpCZXJpa3V0IGFkYWxhaCBjYXJhIG1lbmdndW5ha2FuIGF0YXUgbWVuamFsYW5rYW4gcGFja2FnZSBSDQoNCmBgYHtyfQ0KbGlicmFyeShNQVNTKQ0KZGF0YShucGspDQpucGsNCmBgYA0KDQpCZWJlcmFwYSBwYWNrYWdlIG1lbWlsaWtpIGRhdGFzZXQgeWFuZyBkYXBhdCBkaWFrc2VzIGRlbmdhbiBtZW1hbmdnaWwgbmFtYSBvYmplayBkYXRhc2V0IHRlcnNlYnV0Lg0KDQpCZXJpa3V0IGFkYWxhaCBjYXJhIHVudHVrIG1lbGVwYXMgKHVubG9hZCkgcGFja2FnZSBSDQoNCmBgYHtyfQ0KZGV0YWNoKCJwYWNrYWdlOk1BU1MiKQ0KYGBgDQo=