INTRODUCTION R

Algoritma Dan Struktur Data


*Kontak : \(\downarrow\)*
Email
Instagram https://www.instagram.com/m_naufalardiansyah/
RPubs https://rpubs.com/muhamad_naufal/

R Vs Python

R dan Python adalah bahasa pemrograman yang sangat populer, dinamis, digunakan secara luas dalam komunitas data science. R lebih banyak digunakan dalam analisis statistik sementara Python menyediakan pendekatan yang lebih umum mengenai sains data (sehingga dianggap lebih mudah untuk digunakan oleh pemula). Mempelajari kedua bahasa pemrograman ini adalah solusi yang lebih bijak karena keduanya mempunyai kelebihan dan kekurangan masing-masing. R dan Python membutuhkan investasi waktu, latihan dengan tutorial, dan melakukan projek-projek kecil berbasis LAB hingga penerapan sais data pada kasus-kasus yang sebenarnya.

Persamaan

  • R dan Python adalah bahasa pemrograman multi-paradigma. Keduanya mendukung Pemrograman Berorientasi Objek, Pemrograman Imperatif, Pemrograman Prosedural, dll.
  • Keduanya adalah bahasa yang ditafsirkan.
  • Keduanya dapat digunakan untuk mengembangkan algoritme.
  • Keduanya adalah bahasa pemrograman tingkat tinggi.
  • Keduanya gratis dan open source.
  • Keduanya dapat diintegrasikan dengan aplikasi lain seperti MySQL, Oracle, GitHub, dll.
  • Keduanya mendukung file yang berbeda seperti file CSV, file excel, file XML dan file JSON.
  • Kedua bahasa tersebut mudah digunakan dan dipelajari.

Perbedaan

Berikut adalah tabel yang secara ringkas membandingkan dua bahasa pemrograman Python dan R:


Sintaks Dasar

Suatu program di R dan Python terdiri dari tiga hal mendasar: Variabel, operan (nilai) dan Komentar. Variabel digunakan untuk menyimpan suatu nilai, sedangkan Komentar digunakan untuk meningkatkan pemahaman pengguna mengenai skrip atau koding.

Penugasan Variabel

Dalam R, penugasan suatu program biasanya menggunakan suatu variabel yang dicadangkan untuk dapat merekam berbagai jenis data sesuai nama yang diberikan ke lokasi penyimpanan/memori. Perintah penugasan variabel ini, dapat dinotasikan dengan tiga cara:

  • =, digunakan untuk penugasan sederhana
  • <-, digunakan untuk penugasan dari sisi kiri
  • ->, digunakan untuk penugasan dari sisi kanan
x = 2 
y <- 3
5 -> z
print(c(x,y,z))
## [1] 2 3 5

Menambahkan Komentar

Menambahkan/Memberikan komentar dalam skrip/koding R adalah untuk memudahkan dalam memahami arti/makna penggunaan suatu perintah/program. Komentar yang ditulis dalam sebuah program tersebut hanya bersifat penjelasan tentang apa yang dilakukannya atau apa yang seharusnya dilakukan oleh sebuah skrip/koding. Perlu dicatat bahwa komentar yang bersifat informasi tidak ada hubungannya dengan logika pemrogaram yang sedang anda gunakan. Mereka benar-benar diabaikan oleh kompiler dan dengan demikian tidak pernah tercermin pada input. Biasanya komentar dituliskan pada satu baris yang tersedia di R atau Python, dengan menggunakan # di awal maupun di akhir pernyataan.

#mengganti nilai x yang sudah direkam 
x=12
z <- x + y #mengganti nilai z yang sudah direkam
x + y -> z #sama dengan diatas

Operator

Operator adalah simbol yang mengarahkan compiler untuk melakukan berbagai macam operasi terhadap beberapa penugasan. Operator mensimulasikan berbagai operasi matematis, logika, dan keputusan yang dilakukan pada sekumpulan Bilangan Kompleks, Integer, dan Numerik sebagai penugasan masukan (input). R dan Python mendukung sebagian besar empat jenis operator biner antara satu set penugasan. Dalam ini, kita akan melihat berbagai jenis operator yang tersedia di R dan Python dan penggunaannya.

Aritmatika

Penggunaan operator aritmatika dalam program R dan Python adalah untuk mensimulasikan berbagai operasi matematika, seperti penambahan, pengurangan, perkalian, pembagian, dan modulo. Operator aritmatika yang dilakukan bisa saja berupa nilai skalar, bilangan kompleks, atau vektor.

Operator R Python
Penjumlahan + +
pengurangan - -
perkalian * *
Pembagian / /
Pemangkatan ^ **
Modulo %% %

Penerapan Aritmatika pada R

Untuk pemahaman lebih lanjut, pahami sintaks di bawah ini :

x <- c(4,8,2)      # memuat vektor x
y <- c(5,9,6)      # memuat vektor y
x+y                # hasil penjumlahan vektor x dan y
## [1]  9 17  8

Penjumlahan pada R

print(x+y)         # hasil penjumlahan vektor x dan y
## [1]  9 17  8

Pengurangan pada R

print(x-y)         # hasil pengurangan vektor x dan y
## [1] -1 -1 -4

Pembagian pada R

print(x/y)         # hasil pembagian vektor x dan y
## [1] 0.8000000 0.8888889 0.3333333

Perkaliann pada R

print(x*y)         # hasil perkalian vektor x dan y
## [1] 20 72 12

Pembagian pada R

print(x%%y)         # hasil modulo vektor x dan y
## [1] 4 8 2

Pemangkatan pada R

print(x^y)         # hasil pemangkatan vektor x dan y
## [1]      1024 134217728        64

Modulo pada R

print(x%%y)         # hasil modulo vektor x dan y
## [1] 4 8 2

Relasional

Operator relasional melakukan operasi perbandingan antara elemen yang bersesuaian pada setiap operan. Mengembalikan nilai Boolean TRUE jika operan pertama memenuhi relasi dibandingkan dengan operan kedua. Nilai TRUE selalu dianggap lebih besar dari FALSE.

Operator R Python Keterangan
Kurang dari < < Mengembalikan TRUE jika elemen yang bersesuaian pada operan pertama lebih kecil dari operan kedua. Selain itu akan mengembalikan FALSE
Kurang dari sama dengan <= <= Mengembalikan TRUE jika elemen yang bersesuaian pada operan pertama kurang dari atau sama dengan elemen operan kedua. Selain itu akan mengembalikan FALSE
Lebih besar dari > > Mengembalikan TRUE jika elemen yang bersesuaian pada operan pertama lebih besar dari operan kedua. Selain itu akan mengembalikan FALSE
Lebih besar dari sama dengan >= >= Mengembalikan BENAR jika elemen yang bersesuaian pada operan pertama lebih besar atau sama dengan dari operan kedua. Selain itu akan mengembalikan FALSE
Sama dengan == == Mengembalikan BENAR jika dan hanya jika kedua sisi bernilai sama
Tidak Sama dengan != != Mengembalikan BENAR jika elemen yang bersesuaian pada operan pertama tidak sama dengan dari operan kedua
x <- c(2,3,5)  #membuat vektor x
y <- c(2,4,6)  #membuat vektor y
cat("vektor x kurang dari vektor y:", x < y, "\n")
## vektor x kurang dari vektor y: FALSE TRUE TRUE
cat("vektor x kurang dari sama dengan vektor y :", x <= y, "\n")
## vektor x kurang dari sama dengan vektor y : TRUE TRUE TRUE
cat("vektor x lebih besar dari vektor y :", x > y, "\n")
## vektor x lebih besar dari vektor y : FALSE FALSE FALSE
cat("vektor x lebih besar sama dengan vektor y :", x >= y, "\n")
## vektor x lebih besar sama dengan vektor y : TRUE FALSE FALSE
cat("vektor x sama dengan vektor y :", x == y, "\n")
## vektor x sama dengan vektor y : TRUE FALSE FALSE
cat("vektor x tidak sama dengan vektor y :", x != y, "\n")
## vektor x tidak sama dengan vektor y : FALSE TRUE TRUE

Logika

Operator logis mensimulasikan operasi keputusan, berdasarkan operator yang ditentukan antara operan, yang kemudian dievaluasi ke nilai Boolean Benar atau Salah. Nilai bilangan bulat bukan nol dianggap sebagai nilai BENAR, baik itu bilangan kompleks atau bilangan real.

Operator R Python Keterangan
NOT ! ! Operasi negasi/kebalikan pada status elemen operan
AND & & Mengembalikan TRUE jika kedua operan bernilai Benar
OR $ $ Mengembalikan TRUE jika salah satu operan adalah Benar
XOR ^ ^ Mengembalikan TRUE jika salah satu dari kedua elemen pertama operan bernilai Benar
x <- c(0,TRUE,FALSE)
y <- c(TRUE,0.1,4+3i)

#Melakukan operasi logika
cat("Logika Negasi (~) untuk vektor x:", !x, "\n")
## Logika Negasi (~) untuk vektor x: TRUE FALSE TRUE
cat("Logika Negasi (~) untuk vektor y:", !y, "\n")
## Logika Negasi (~) untuk vektor y: FALSE FALSE FALSE
cat("Logika konjungsi (Dan) :", x & y, "\n")
## Logika konjungsi (Dan) : FALSE TRUE FALSE
cat("Logika disjungsi (Atau) :", x | y, "\n")
## Logika disjungsi (Atau) : TRUE TRUE TRUE
cat("Logika disjungsi parsial :", x || y)
## Warning in x || y: 'length(x) = 3 > 1' in coercion to 'logical(1)'

## Warning in x || y: 'length(x) = 3 > 1' in coercion to 'logical(1)'
## Logika disjungsi parsial : TRUE

Tipe Data

Dalam pemrograman seperti R dan Python, tipe data merupakan konsep penting. Keduanya dapat menggunakan variabel untuk menyimpan tipe yang berbeda-beda, berikut adalah tipe data paling mendasar yang harus diketahui:

Operator R Python Penjelasan
Double/Flat 5.6 5.6 Bilangan yang mempunyai koma
Integer 5 5 Bilangan bulat 1,2,…,n
Bolean/Logical TRUE/FALSE True/False Benar bernilai 1 dan Salah bernilai 0
String/Character ‘Dscienlabs’ Dscienlabs’ karakter/kalimat bisa berupa huruf angka, dll (diapit tanda ” atau ’)
Complex 1 + 5j 1 + 5j Pasangan angka real dan imajiner

Berikut ini adalah koding R yang dapat digunakan untuk menetapkan kelima tipe data diatas:

d1 = 5.6                 #menetapkan nilai desimal
d2 = as.integer(5)       #menetapkan nilai integer
d2 = 5L                  #cara lain membuat nilai integer di R
d3 = c(TRUE,FALSE)       #logical
d3 = as.logical(c(0,1))  #cara lain membuat logical
d4 = c("a",'b','123')    #string/character
d5 = 1 + 5i              #complex

Untuk memeriksa 5 tipe di atas dapat menggunakan :

class(d1)   #mencetak nama kelas variabel
## [1] "numeric"
typeof(d1)  #cetak type variabel
## [1] "double"

Bantuan

Salah satu bagian terpenting dalam bekerja dengan bahasa R adalah mengetahui di mana mencari bantuan. R memiliki beberapa fasilitas in-line, selain berbagai sumber daya bantuan di ekosistem R. Anda dapat menggunakan bantuan untuk fungsi tertentu.

help.start()            #menu di mana dapat menavigasi bantuan lokal berbasis web
## starting httpd help server ... done
## If nothing happens, you should open
## 'http://127.0.0.1:26989/doc/html/index.html' yourself
?help                   #menu di mana dapat menavigasi bantuan lokal berbasis web
?class                  #mendapatkan bantuan untuk fungsi 'class'
help(class)             #mendapatkan bantuan untuk fungsi 'class'
??class                 #Untuk mengetahui nama fungsi yang tidak diketahui
help.search('class')    #Untuk mengetahui nama fungsi yang tidak diketahui
LS0tDQp0aXRsZTogIklOVFJPRFVDVElPTiBSICINCnN1YnRpdGxlOiAiQWxnb3JpdG1hIERhbiBTdHJ1a3R1ciBEYXRhIg0KYXV0aG9yOiAiTXVoYW1tYWQgTmF1ZmFsIEFyZGlhbnN5YWggKEFoYWRlbXkpIg0KZGF0ZTogICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVkLCAlWScpYCINCm91dHB1dDoNCiAgcm1kZm9ybWF0czo6cm9ib2Jvb2s6ICAgIyBodHRwczovL2dpdGh1Yi5jb20vanViYS9ybWRmb3JtYXRzDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICB0aHVtYm5haWxzOiB0cnVlDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbGliX2RpcjogbGlicw0KICAgIGRmX3ByaW50OiAicGFnZWQiDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBjc3M6ICJzdHlsZS5jc3MiDQoNCi0tLQ0KDQoNCg0KDQo8YnI+DQoNCg0KPGltZyBzdHlsZT0iZmxvYXQ6IHJpZ2h0OyBtYXJnaW46IC01MHB4IDUwcHggMHB4IDUwcHg7IHdpZHRoOjI1JSIgc3JjPSJuYXVmYWwuanBlZyIvPiANCg0KfA0KOi0tLS0gfDotLS0tDQoqS29udGFrfCAqOiAqJFxkb3duYXJyb3ckKg0KRW1haWx8IG5hdWZhbDM0MzNAZ21haWwuY29tDQpJbnN0YWdyYW0gfCBodHRwczovL3d3dy5pbnN0YWdyYW0uY29tL21fbmF1ZmFsYXJkaWFuc3lhaC8gDQpSUHVicyAgfCBodHRwczovL3JwdWJzLmNvbS9tdWhhbWFkX25hdWZhbC8gDQoNCioqKg0KDQojIFIgVnMgUHl0aG9uDQoNClIgZGFuIFB5dGhvbiBhZGFsYWggYmFoYXNhIHBlbXJvZ3JhbWFuIHlhbmcgc2FuZ2F0IHBvcHVsZXIsIGRpbmFtaXMsIGRpZ3VuYWthbiBzZWNhcmEgbHVhcyBkYWxhbSBrb211bml0YXMgZGF0YSBzY2llbmNlLiBSIGxlYmloIGJhbnlhayBkaWd1bmFrYW4gZGFsYW0gYW5hbGlzaXMgc3RhdGlzdGlrIHNlbWVudGFyYSBQeXRob24gbWVueWVkaWFrYW4gcGVuZGVrYXRhbiB5YW5nIGxlYmloIHVtdW0gbWVuZ2VuYWkgc2FpbnMgZGF0YSAoc2VoaW5nZ2EgZGlhbmdnYXAgbGViaWggbXVkYWggdW50dWsgZGlndW5ha2FuIG9sZWggcGVtdWxhKS4gTWVtcGVsYWphcmkga2VkdWEgYmFoYXNhIHBlbXJvZ3JhbWFuIGluaSBhZGFsYWggc29sdXNpIHlhbmcgbGViaWggYmlqYWsga2FyZW5hIGtlZHVhbnlhIG1lbXB1bnlhaSBrZWxlYmloYW4gZGFuIGtla3VyYW5nYW4gbWFzaW5nLW1hc2luZy4gUiBkYW4gUHl0aG9uIG1lbWJ1dHVoa2FuIGludmVzdGFzaSB3YWt0dSwgbGF0aWhhbiBkZW5nYW4gdHV0b3JpYWwsIGRhbiBtZWxha3VrYW4gcHJvamVrLXByb2playBrZWNpbCBiZXJiYXNpcyBMQUIgaGluZ2dhIHBlbmVyYXBhbiBzYWlzIGRhdGEgcGFkYSBrYXN1cy1rYXN1cyB5YW5nIHNlYmVuYXJueWEuDQoNCiMjIFBlcnNhbWFhbg0KDQotIFIgZGFuIFB5dGhvbiBhZGFsYWggYmFoYXNhIHBlbXJvZ3JhbWFuIG11bHRpLXBhcmFkaWdtYS4gS2VkdWFueWEgbWVuZHVrdW5nIFBlbXJvZ3JhbWFuIEJlcm9yaWVudGFzaSBPYmplaywgUGVtcm9ncmFtYW4gSW1wZXJhdGlmLCBQZW1yb2dyYW1hbiBQcm9zZWR1cmFsLCBkbGwuDQotIEtlZHVhbnlhIGFkYWxhaCBiYWhhc2EgeWFuZyBkaXRhZnNpcmthbi4NCi0gS2VkdWFueWEgZGFwYXQgZGlndW5ha2FuIHVudHVrIG1lbmdlbWJhbmdrYW4gYWxnb3JpdG1lLg0KLSBLZWR1YW55YSBhZGFsYWggYmFoYXNhIHBlbXJvZ3JhbWFuIHRpbmdrYXQgdGluZ2dpLg0KLSBLZWR1YW55YSBncmF0aXMgZGFuIG9wZW4gc291cmNlLg0KLSBLZWR1YW55YSBkYXBhdCBkaWludGVncmFzaWthbiBkZW5nYW4gYXBsaWthc2kgbGFpbiBzZXBlcnRpIE15U1FMLCBPcmFjbGUsIEdpdEh1YiwgZGxsLg0KLSBLZWR1YW55YSBtZW5kdWt1bmcgZmlsZSB5YW5nIGJlcmJlZGEgc2VwZXJ0aSBmaWxlIENTViwgZmlsZSBleGNlbCwgZmlsZSBYTUwgZGFuIGZpbGUgSlNPTi4NCi0gS2VkdWEgYmFoYXNhIHRlcnNlYnV0IG11ZGFoIGRpZ3VuYWthbiBkYW4gZGlwZWxhamFyaS4NCg0KIyMgUGVyYmVkYWFuDQoNCkJlcmlrdXQgYWRhbGFoIHRhYmVsIHlhbmcgc2VjYXJhIHJpbmdrYXMgbWVtYmFuZGluZ2thbiBkdWEgYmFoYXNhIHBlbXJvZ3JhbWFuIFB5dGhvbiBkYW4gUjoNCg0KPGltZyBzdHlsZT0iZmxvYXQ6IG1pZGxlOyBtYXJnaW46IDBweCAxMDBweCAwcHggMHB4OyB3aWR0aDo5MCUiIHNyYz0iZ2FtYmFyMS5wbmciLz4gDQoNCioqKg0KIyBTaW50YWtzIERhc2FyIA0KDQpTdWF0dSBwcm9ncmFtIGRpIFIgZGFuIFB5dGhvbiB0ZXJkaXJpIGRhcmkgdGlnYSBoYWwgbWVuZGFzYXI6IFZhcmlhYmVsLCBvcGVyYW4gKG5pbGFpKSBkYW4gS29tZW50YXIuIFZhcmlhYmVsIGRpZ3VuYWthbiB1bnR1ayBtZW55aW1wYW4gc3VhdHUgbmlsYWksIHNlZGFuZ2thbiBLb21lbnRhciBkaWd1bmFrYW4gdW50dWsgbWVuaW5na2F0a2FuIHBlbWFoYW1hbiBwZW5nZ3VuYSBtZW5nZW5haSBza3JpcCBhdGF1IGtvZGluZy4NCg0KIyMgUGVudWdhc2FuIFZhcmlhYmVsDQoNCkRhbGFtIFIsIHBlbnVnYXNhbiBzdWF0dSBwcm9ncmFtIGJpYXNhbnlhIG1lbmdndW5ha2FuIHN1YXR1IHZhcmlhYmVsIHlhbmcgZGljYWRhbmdrYW4gdW50dWsgZGFwYXQgbWVyZWthbSBiZXJiYWdhaSBqZW5pcyBkYXRhIHNlc3VhaSBuYW1hIHlhbmcgZGliZXJpa2FuIGtlIGxva2FzaSBwZW55aW1wYW5hbi9tZW1vcmkuIFBlcmludGFoIHBlbnVnYXNhbiB2YXJpYWJlbCBpbmksIGRhcGF0IGRpbm90YXNpa2FuIGRlbmdhbiB0aWdhIGNhcmE6DQoNCi0gYD1gLCBkaWd1bmFrYW4gdW50dWsgcGVudWdhc2FuIHNlZGVyaGFuYQ0KLSBgPC1gLCBkaWd1bmFrYW4gdW50dWsgcGVudWdhc2FuIGRhcmkgc2lzaSBraXJpDQotIGAtPmAsIGRpZ3VuYWthbiB1bnR1ayBwZW51Z2FzYW4gZGFyaSBzaXNpIGthbmFuDQoNCmBgYHtyfQ0KeCA9IDIgDQp5IDwtIDMNCjUgLT4geg0KcHJpbnQoYyh4LHkseikpDQpgYGANCg0KIyMgTWVuYW1iYWhrYW4gS29tZW50YXINCg0KTWVuYW1iYWhrYW4vTWVtYmVyaWthbiBrb21lbnRhciBkYWxhbSBza3JpcC9rb2RpbmcgUiBhZGFsYWggdW50dWsgbWVtdWRhaGthbiBkYWxhbSBtZW1haGFtaSBhcnRpL21ha25hIHBlbmdndW5hYW4gc3VhdHUgcGVyaW50YWgvcHJvZ3JhbS4gS29tZW50YXIgeWFuZyBkaXR1bGlzIGRhbGFtIHNlYnVhaCBwcm9ncmFtIHRlcnNlYnV0IGhhbnlhIGJlcnNpZmF0IHBlbmplbGFzYW4gdGVudGFuZyBhcGEgeWFuZyBkaWxha3VrYW5ueWEgYXRhdSBhcGEgeWFuZyBzZWhhcnVzbnlhIGRpbGFrdWthbiBvbGVoIHNlYnVhaCBza3JpcC9rb2RpbmcuIFBlcmx1IGRpY2F0YXQgYmFod2Ega29tZW50YXIgeWFuZyBiZXJzaWZhdCBpbmZvcm1hc2kgdGlkYWsgYWRhIGh1YnVuZ2FubnlhIGRlbmdhbiBsb2dpa2EgcGVtcm9nYXJhbSB5YW5nIHNlZGFuZyBhbmRhIGd1bmFrYW4uIE1lcmVrYSBiZW5hci1iZW5hciBkaWFiYWlrYW4gb2xlaCBrb21waWxlciBkYW4gZGVuZ2FuIGRlbWlraWFuIHRpZGFrIHBlcm5haCB0ZXJjZXJtaW4gcGFkYSBpbnB1dC4gQmlhc2FueWEga29tZW50YXIgZGl0dWxpc2thbiBwYWRhIHNhdHUgYmFyaXMgeWFuZyB0ZXJzZWRpYSBkaSBSIGF0YXUgUHl0aG9uLCBkZW5nYW4gbWVuZ2d1bmFrYW4gYCNgIGRpIGF3YWwgbWF1cHVuIGRpIGFraGlyIHBlcm55YXRhYW4uDQoNCmBgYHtyfQ0KI21lbmdnYW50aSBuaWxhaSB4IHlhbmcgc3VkYWggZGlyZWthbSANCng9MTINCnogPC0geCArIHkgI21lbmdnYW50aSBuaWxhaSB6IHlhbmcgc3VkYWggZGlyZWthbQ0KeCArIHkgLT4geiAjc2FtYSBkZW5nYW4gZGlhdGFzDQpgYGANCg0KIyBPcGVyYXRvciANCg0KT3BlcmF0b3IgYWRhbGFoIHNpbWJvbCB5YW5nIG1lbmdhcmFoa2FuIGNvbXBpbGVyIHVudHVrIG1lbGFrdWthbiBiZXJiYWdhaSBtYWNhbSBvcGVyYXNpIHRlcmhhZGFwIGJlYmVyYXBhIHBlbnVnYXNhbi4gT3BlcmF0b3IgbWVuc2ltdWxhc2lrYW4gYmVyYmFnYWkgb3BlcmFzaSBtYXRlbWF0aXMsIGxvZ2lrYSwgZGFuIGtlcHV0dXNhbiB5YW5nIGRpbGFrdWthbiBwYWRhIHNla3VtcHVsYW4gQmlsYW5nYW4gS29tcGxla3MsIEludGVnZXIsIGRhbiBOdW1lcmlrIHNlYmFnYWkgcGVudWdhc2FuIG1hc3VrYW4gKGlucHV0KS4gUiBkYW4gUHl0aG9uIG1lbmR1a3VuZyBzZWJhZ2lhbiBiZXNhciBlbXBhdCBqZW5pcyBvcGVyYXRvciBiaW5lciBhbnRhcmEgc2F0dSBzZXQgcGVudWdhc2FuLiBEYWxhbSBpbmksIGtpdGEgYWthbiBtZWxpaGF0IGJlcmJhZ2FpIGplbmlzIG9wZXJhdG9yIHlhbmcgdGVyc2VkaWEgZGkgUiBkYW4gUHl0aG9uIGRhbiBwZW5nZ3VuYWFubnlhLg0KDQojIyBBcml0bWF0aWthDQoNClBlbmdndW5hYW4gb3BlcmF0b3IgYXJpdG1hdGlrYSBkYWxhbSBwcm9ncmFtIFIgZGFuIFB5dGhvbiBhZGFsYWggdW50dWsgbWVuc2ltdWxhc2lrYW4gYmVyYmFnYWkgb3BlcmFzaSBtYXRlbWF0aWthLCBzZXBlcnRpIHBlbmFtYmFoYW4sIHBlbmd1cmFuZ2FuLCBwZXJrYWxpYW4sIHBlbWJhZ2lhbiwgZGFuIG1vZHVsby4gT3BlcmF0b3IgYXJpdG1hdGlrYSB5YW5nIGRpbGFrdWthbiBiaXNhIHNhamEgYmVydXBhIG5pbGFpIHNrYWxhciwgYmlsYW5nYW4ga29tcGxla3MsIGF0YXUgdmVrdG9yLg0KDQp8fHwNCnwtLS0tfC0tLS18LS0tLXwNCnwqT3BlcmF0b3IqfCAgKlIqICB8KlB5dGhvbip8DQp8UGVuanVtbGFoYW58ICsgfCArIHwNCnxwZW5ndXJhbmdhbnwgLSB8IC0gfA0KfHBlcmthbGlhbnwgKiB8ICogfA0KfFBlbWJhZ2lhbnwgLyB8IC8gfA0KfFBlbWFuZ2thdGFufCBeIHwgKiogfA0KfE1vZHVsb3wgJSUgfCAlIHwNCg0KPGgyIGNsYXNzPSJ0YWJzZXQgdGFic2V0LXBpbGxzIj5QZW5lcmFwYW4gQXJpdG1hdGlrYSBwYWRhIFI8L2gyPg0KDQpVbnR1ayBwZW1haGFtYW4gbGViaWggbGFuanV0LCBwYWhhbWkgc2ludGFrcyBkaSBiYXdhaCBpbmkgOg0KDQpgYGB7cn0NCnggPC0gYyg0LDgsMikgICAgICAjIG1lbXVhdCB2ZWt0b3IgeA0KeSA8LSBjKDUsOSw2KSAgICAgICMgbWVtdWF0IHZla3RvciB5DQp4K3kgICAgICAgICAgICAgICAgIyBoYXNpbCBwZW5qdW1sYWhhbiB2ZWt0b3IgeCBkYW4geQ0KYGBgDQoNCioqUGVuanVtbGFoYW4gcGFkYSBSKioNCg0KYGBge3J9DQpwcmludCh4K3kpICAgICAgICAgIyBoYXNpbCBwZW5qdW1sYWhhbiB2ZWt0b3IgeCBkYW4geQ0KYGBgDQoNCioqUGVuZ3VyYW5nYW4gcGFkYSBSKioNCg0KYGBge3J9DQpwcmludCh4LXkpICAgICAgICAgIyBoYXNpbCBwZW5ndXJhbmdhbiB2ZWt0b3IgeCBkYW4geQ0KYGBgDQoNCioqUGVtYmFnaWFuIHBhZGEgUioqDQoNCmBgYHtyfQ0KcHJpbnQoeC95KSAgICAgICAgICMgaGFzaWwgcGVtYmFnaWFuIHZla3RvciB4IGRhbiB5DQpgYGANCg0KKipQZXJrYWxpYW5uIHBhZGEgUioqDQoNCmBgYHtyfQ0KcHJpbnQoeCp5KSAgICAgICAgICMgaGFzaWwgcGVya2FsaWFuIHZla3RvciB4IGRhbiB5DQpgYGANCg0KKipQZW1iYWdpYW4gcGFkYSBSKioNCg0KYGBge3J9DQpwcmludCh4JSV5KSAgICAgICAgICMgaGFzaWwgbW9kdWxvIHZla3RvciB4IGRhbiB5DQpgYGANCg0KKipQZW1hbmdrYXRhbiBwYWRhIFIqKg0KDQpgYGB7cn0NCnByaW50KHheeSkgICAgICAgICAjIGhhc2lsIHBlbWFuZ2thdGFuIHZla3RvciB4IGRhbiB5DQpgYGANCg0KKipNb2R1bG8gcGFkYSBSKioNCg0KYGBge3J9DQpwcmludCh4JSV5KSAgICAgICAgICMgaGFzaWwgbW9kdWxvIHZla3RvciB4IGRhbiB5DQpgYGANCg0KIyMgUmVsYXNpb25hbA0KDQpPcGVyYXRvciByZWxhc2lvbmFsIG1lbGFrdWthbiBvcGVyYXNpIHBlcmJhbmRpbmdhbiBhbnRhcmEgZWxlbWVuIHlhbmcgYmVyc2VzdWFpYW4gcGFkYSBzZXRpYXAgb3BlcmFuLiBNZW5nZW1iYWxpa2FuIG5pbGFpIEJvb2xlYW4gVFJVRSBqaWthIG9wZXJhbiBwZXJ0YW1hIG1lbWVudWhpIHJlbGFzaSBkaWJhbmRpbmdrYW4gZGVuZ2FuIG9wZXJhbiBrZWR1YS4gTmlsYWkgVFJVRSBzZWxhbHUgZGlhbmdnYXAgbGViaWggYmVzYXIgZGFyaSBGQUxTRS4NCg0KfHx8DQp8LS0tLXwtLS0tfC0tLS18LS0tfA0KfCpPcGVyYXRvcip8ICAqUiogIHwqUHl0aG9uKnwqS2V0ZXJhbmdhbip8DQp8S3VyYW5nIGRhcml8IDwgfCA8IHxNZW5nZW1iYWxpa2FuIFRSVUUgamlrYSBlbGVtZW4geWFuZyBiZXJzZXN1YWlhbiBwYWRhIG9wZXJhbiBwZXJ0YW1hIGxlYmloIGtlY2lsIGRhcmkgb3BlcmFuIGtlZHVhLiBTZWxhaW4gaXR1IGFrYW4gbWVuZ2VtYmFsaWthbiBGQUxTRXwNCnxLdXJhbmcgZGFyaSBzYW1hIGRlbmdhbnwgPD0gfCA8PSB8TWVuZ2VtYmFsaWthbiBUUlVFIGppa2EgZWxlbWVuIHlhbmcgYmVyc2VzdWFpYW4gcGFkYSBvcGVyYW4gcGVydGFtYSBrdXJhbmcgZGFyaSBhdGF1IHNhbWEgZGVuZ2FuIGVsZW1lbiBvcGVyYW4ga2VkdWEuIFNlbGFpbiBpdHUgYWthbiBtZW5nZW1iYWxpa2FuIEZBTFNFfA0KfExlYmloIGJlc2FyIGRhcml8ID4gfCA+IHxNZW5nZW1iYWxpa2FuIFRSVUUgamlrYSBlbGVtZW4geWFuZyBiZXJzZXN1YWlhbiBwYWRhIG9wZXJhbiBwZXJ0YW1hIGxlYmloIGJlc2FyIGRhcmkgb3BlcmFuIGtlZHVhLiBTZWxhaW4gaXR1IGFrYW4gbWVuZ2VtYmFsaWthbiBGQUxTRXwNCnxMZWJpaCBiZXNhciBkYXJpIHNhbWEgZGVuZ2FufCA+PSB8ID49IHxNZW5nZW1iYWxpa2FuIEJFTkFSIGppa2EgZWxlbWVuIHlhbmcgYmVyc2VzdWFpYW4gcGFkYSBvcGVyYW4gcGVydGFtYSBsZWJpaCBiZXNhciBhdGF1IHNhbWEgZGVuZ2FuIGRhcmkgb3BlcmFuIGtlZHVhLiBTZWxhaW4gaXR1IGFrYW4gbWVuZ2VtYmFsaWthbiBGQUxTRXwNCnxTYW1hIGRlbmdhbnwgPT0gfCA9PSB8TWVuZ2VtYmFsaWthbiBCRU5BUiBqaWthIGRhbiBoYW55YSBqaWthIGtlZHVhIHNpc2kgYmVybmlsYWkgc2FtYXwNCnxUaWRhayBTYW1hIGRlbmdhbnwgIT0gfCAhPSB8TWVuZ2VtYmFsaWthbiBCRU5BUiBqaWthIGVsZW1lbiB5YW5nIGJlcnNlc3VhaWFuIHBhZGEgb3BlcmFuIHBlcnRhbWEgdGlkYWsgc2FtYSBkZW5nYW4gZGFyaSBvcGVyYW4ga2VkdWF8DQoNCmBgYHtyfQ0KeCA8LSBjKDIsMyw1KSAgI21lbWJ1YXQgdmVrdG9yIHgNCnkgPC0gYygyLDQsNikgICNtZW1idWF0IHZla3RvciB5DQpjYXQoInZla3RvciB4IGt1cmFuZyBkYXJpIHZla3RvciB5OiIsIHggPCB5LCAiXG4iKQ0KYGBgDQoNCmBgYHtyfQ0KY2F0KCJ2ZWt0b3IgeCBrdXJhbmcgZGFyaSBzYW1hIGRlbmdhbiB2ZWt0b3IgeSA6IiwgeCA8PSB5LCAiXG4iKQ0KYGBgDQoNCmBgYHtyfQ0KY2F0KCJ2ZWt0b3IgeCBsZWJpaCBiZXNhciBkYXJpIHZla3RvciB5IDoiLCB4ID4geSwgIlxuIikNCmBgYA0KDQpgYGB7cn0NCmNhdCgidmVrdG9yIHggbGViaWggYmVzYXIgc2FtYSBkZW5nYW4gdmVrdG9yIHkgOiIsIHggPj0geSwgIlxuIikNCmBgYA0KDQpgYGB7cn0NCmNhdCgidmVrdG9yIHggc2FtYSBkZW5nYW4gdmVrdG9yIHkgOiIsIHggPT0geSwgIlxuIikNCmBgYA0KDQpgYGB7cn0NCmNhdCgidmVrdG9yIHggdGlkYWsgc2FtYSBkZW5nYW4gdmVrdG9yIHkgOiIsIHggIT0geSwgIlxuIikNCmBgYA0KDQojIyBMb2dpa2ENCg0KT3BlcmF0b3IgbG9naXMgbWVuc2ltdWxhc2lrYW4gb3BlcmFzaSBrZXB1dHVzYW4sIGJlcmRhc2Fya2FuIG9wZXJhdG9yIHlhbmcgZGl0ZW50dWthbiBhbnRhcmEgb3BlcmFuLCB5YW5nIGtlbXVkaWFuIGRpZXZhbHVhc2kga2UgbmlsYWkgQm9vbGVhbiBCZW5hciBhdGF1IFNhbGFoLiBOaWxhaSBiaWxhbmdhbiBidWxhdCBidWthbiBub2wgZGlhbmdnYXAgc2ViYWdhaSBuaWxhaSBCRU5BUiwgYmFpayBpdHUgYmlsYW5nYW4ga29tcGxla3MgYXRhdSBiaWxhbmdhbiByZWFsLg0KDQp8fHwNCnwtLS0tfC0tLS18LS0tLXwtLS18DQp8Kk9wZXJhdG9yKnwgICpSKiAgfCpQeXRob24qfCpLZXRlcmFuZ2FuKnwNCnxOT1R8ICEgfCAhIHxPcGVyYXNpIG5lZ2FzaS9rZWJhbGlrYW4gcGFkYSBzdGF0dXMgZWxlbWVuIG9wZXJhbnwNCnxBTkR8ICYgfCAmIHxNZW5nZW1iYWxpa2FuIFRSVUUgamlrYSBrZWR1YSBvcGVyYW4gYmVybmlsYWkgQmVuYXJ8DQp8T1J8ICQgfCAkIHxNZW5nZW1iYWxpa2FuIFRSVUUgamlrYSBzYWxhaCBzYXR1IG9wZXJhbiBhZGFsYWggQmVuYXJ8DQp8WE9SfCBeIHwgXiB8TWVuZ2VtYmFsaWthbiBUUlVFIGppa2Egc2FsYWggc2F0dSBkYXJpIGtlZHVhIGVsZW1lbiBwZXJ0YW1hIG9wZXJhbiBiZXJuaWxhaSBCZW5hcnwNCg0KYGBge3J9DQp4IDwtIGMoMCxUUlVFLEZBTFNFKQ0KeSA8LSBjKFRSVUUsMC4xLDQrM2kpDQoNCiNNZWxha3VrYW4gb3BlcmFzaSBsb2dpa2ENCmNhdCgiTG9naWthIE5lZ2FzaSAofikgdW50dWsgdmVrdG9yIHg6IiwgIXgsICJcbiIpDQpgYGANCg0KYGBge3J9DQpjYXQoIkxvZ2lrYSBOZWdhc2kgKH4pIHVudHVrIHZla3RvciB5OiIsICF5LCAiXG4iKQ0KYGBgDQoNCmBgYHtyfQ0KY2F0KCJMb2dpa2Ega29uanVuZ3NpIChEYW4pIDoiLCB4ICYgeSwgIlxuIikNCmBgYA0KDQpgYGB7cn0NCmNhdCgiTG9naWthIGRpc2p1bmdzaSAoQXRhdSkgOiIsIHggfCB5LCAiXG4iKQ0KYGBgDQoNCmBgYHtyfQ0KY2F0KCJMb2dpa2EgZGlzanVuZ3NpIHBhcnNpYWwgOiIsIHggfHwgeSkNCmBgYA0KDQojIFRpcGUgRGF0YQ0KDQpEYWxhbSBwZW1yb2dyYW1hbiBzZXBlcnRpIFIgZGFuIFB5dGhvbiwgdGlwZSBkYXRhIG1lcnVwYWthbiBrb25zZXAgcGVudGluZy4gS2VkdWFueWEgZGFwYXQgbWVuZ2d1bmFrYW4gdmFyaWFiZWwgdW50dWsgbWVueWltcGFuIHRpcGUgeWFuZyBiZXJiZWRhLWJlZGEsIGJlcmlrdXQgYWRhbGFoIHRpcGUgZGF0YSBwYWxpbmcgbWVuZGFzYXIgeWFuZyBoYXJ1cyBkaWtldGFodWk6DQoNCnx8fA0KfC0tLS18LS0tLXwtLS0tfC0tLXwNCnwqT3BlcmF0b3IqfCAgKlIqICB8KlB5dGhvbip8KlBlbmplbGFzYW4qfA0KfERvdWJsZS9GbGF0fCA1LjYgfCA1LjYgfEJpbGFuZ2FuIHlhbmcgbWVtcHVueWFpIGtvbWF8DQp8SW50ZWdlcnwgNSB8IDUgfEJpbGFuZ2FuIGJ1bGF0IDEsMizigKYsbnwNCnxCb2xlYW4vTG9naWNhbHwgVFJVRS9GQUxTRSB8IFRydWUvRmFsc2UgfEJlbmFyIGJlcm5pbGFpIDEgZGFuIFNhbGFoIGJlcm5pbGFpIDB8DQp8U3RyaW5nL0NoYXJhY3RlcnwgJ0RzY2llbmxhYnMnIHwgRHNjaWVubGFicycgfGthcmFrdGVyL2thbGltYXQgYmlzYSBiZXJ1cGEgaHVydWYgYW5na2EsIGRsbCAoZGlhcGl0IHRhbmRhICIgYXRhdSDigJkpfA0KfENvbXBsZXh8IDEgKyA1aiB8IDEgKyA1aiB8UGFzYW5nYW4gYW5na2EgcmVhbCBkYW4gaW1hamluZXJ8DQoNCkJlcmlrdXQgaW5pIGFkYWxhaCBrb2RpbmcgUiB5YW5nIGRhcGF0IGRpZ3VuYWthbiB1bnR1ayBtZW5ldGFwa2FuIGtlbGltYSB0aXBlIGRhdGEgZGlhdGFzOg0KDQpgYGB7cn0NCmQxID0gNS42ICAgICAgICAgICAgICAgICAjbWVuZXRhcGthbiBuaWxhaSBkZXNpbWFsDQpkMiA9IGFzLmludGVnZXIoNSkgICAgICAgI21lbmV0YXBrYW4gbmlsYWkgaW50ZWdlcg0KZDIgPSA1TCAgICAgICAgICAgICAgICAgICNjYXJhIGxhaW4gbWVtYnVhdCBuaWxhaSBpbnRlZ2VyIGRpIFINCmQzID0gYyhUUlVFLEZBTFNFKSAgICAgICAjbG9naWNhbA0KZDMgPSBhcy5sb2dpY2FsKGMoMCwxKSkgICNjYXJhIGxhaW4gbWVtYnVhdCBsb2dpY2FsDQpkNCA9IGMoImEiLCdiJywnMTIzJykgICAgI3N0cmluZy9jaGFyYWN0ZXINCmQ1ID0gMSArIDVpICAgICAgICAgICAgICAjY29tcGxleA0KYGBgDQoNClVudHVrIG1lbWVyaWtzYSA1IHRpcGUgZGkgYXRhcyBkYXBhdCBtZW5nZ3VuYWthbiA6DQoNCmBgYHtyfQ0KY2xhc3MoZDEpICAgI21lbmNldGFrIG5hbWEga2VsYXMgdmFyaWFiZWwNCmBgYA0KDQpgYGB7cn0NCnR5cGVvZihkMSkgICNjZXRhayB0eXBlIHZhcmlhYmVsDQpgYGANCg0KIyBCYW50dWFuDQoNClNhbGFoIHNhdHUgYmFnaWFuIHRlcnBlbnRpbmcgZGFsYW0gYmVrZXJqYSBkZW5nYW4gYmFoYXNhIFIgYWRhbGFoIG1lbmdldGFodWkgZGkgbWFuYSBtZW5jYXJpIGJhbnR1YW4uIFIgbWVtaWxpa2kgYmViZXJhcGEgZmFzaWxpdGFzIGluLWxpbmUsIHNlbGFpbiBiZXJiYWdhaSBzdW1iZXIgZGF5YSBiYW50dWFuIGRpIGVrb3Npc3RlbSBSLiBBbmRhIGRhcGF0IG1lbmdndW5ha2FuIGJhbnR1YW4gdW50dWsgZnVuZ3NpIHRlcnRlbnR1Lg0KDQpgYGB7cn0NCmhlbHAuc3RhcnQoKSAgICAgICAgICAgICNtZW51IGRpIG1hbmEgZGFwYXQgbWVuYXZpZ2FzaSBiYW50dWFuIGxva2FsIGJlcmJhc2lzIHdlYg0KP2hlbHAgICAgICAgICAgICAgICAgICAgI21lbnUgZGkgbWFuYSBkYXBhdCBtZW5hdmlnYXNpIGJhbnR1YW4gbG9rYWwgYmVyYmFzaXMgd2ViDQo/Y2xhc3MgICAgICAgICAgICAgICAgICAjbWVuZGFwYXRrYW4gYmFudHVhbiB1bnR1ayBmdW5nc2kgJ2NsYXNzJw0KaGVscChjbGFzcykgICAgICAgICAgICAgI21lbmRhcGF0a2FuIGJhbnR1YW4gdW50dWsgZnVuZ3NpICdjbGFzcycNCj8/Y2xhc3MgICAgICAgICAgICAgICAgICNVbnR1ayBtZW5nZXRhaHVpIG5hbWEgZnVuZ3NpIHlhbmcgdGlkYWsgZGlrZXRhaHVpDQpoZWxwLnNlYXJjaCgnY2xhc3MnKSAgICAjVW50dWsgbWVuZ2V0YWh1aSBuYW1hIGZ1bmdzaSB5YW5nIHRpZGFrIGRpa2V0YWh1aQ0KYGBgDQoNCg0K