UTS Pemrograman Data Science
Data Science Programming
1 1. Operasi dan Tipe Data Dasar
# a. Menerima dua bilangan dari pengguna
A <- as.integer(readline(prompt = "Masukkan bilangan pertama (int): "))
## Masukkan bilangan pertama (int):
## Masukkan bilangan kedua (int):
# b. Menghitung hasil operasi
penjumlahan <- A + B
perkalian <- A * B
pembagian <- A/B
pangkat <- A ^ B
# c. Menampilkan hasil dan tipe datanya
cat("\nHasil Operasi:\n")
##
## Hasil Operasi:
## Penjumlahan: NA (tipe: integer )
## Perkalian: NA (tipe: integer )
cat("Pembagian:", pembagian, "(tipe:", if (is.numeric(pembagian)) typeof(pembagian) else typeof(as.character(pembagian)), ")\n")
## Pembagian: NA (tipe: double )
## Pangkat: NA (tipe: double )
2 2. Struktur Kendali (Control Flow)
## Masukkan nilai ujian (0–100):
# Menentukan keterangan nilai
if (!is.na(nilai)) {
if (nilai >= 0 && nilai < 60) {
keterangan <- "Perlu Perbaikan"
} else if (nilai <= 69) {
keterangan <- "Cukup"
} else if (nilai <= 84) {
keterangan <- "Baik"
} else if (nilai <= 100) {
keterangan <- "Sangat Baik"
} else {
keterangan <- "Nilai tidak valid (di luar 0–100)"
}
} else {
keterangan <- "Input tidak valid (bukan angka)"
}
# Tampilkan hasil
cat("Nilai Anda:", nilai, "\n")
## Nilai Anda: NA
## Keterangan: Input tidak valid (bukan angka)
3 3. Fungsi dan Perulangan
# a. Menerima input integer n
if (interactive()) {
n <- as.integer(readline(prompt = "Masukkan bilangan bulat n: "))
} else {
n <- 40 # Nilai default saat proses knit
}
# b. Menggunakan loop untuk mencetak semua bilangan genap kelipatan 4 dari 1 hingga n
cat(sprintf("Semua bilangan genap kelipatan 4 dari 1 hingga %d:\n", n))
## Semua bilangan genap kelipatan 4 dari 1 hingga 40:
## 4, 8, 12, 16, 20, 24, 28, 32, 36, 40
4 4. Studi Kasus
Bagian 1 Data Collection
## Warning: package 'readr' was built under R version 4.4.3
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
## Rows: 50 Columns: 9
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (7): Tanggal, Produk, Kategori, Harga, Jumlah, Pembeli, Kota
## dbl (1): OrderID
## lgl (1): Total
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 50 Columns: 9
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (7): Tanggal, Produk, Kategori, Harga, Jumlah, Pembeli, Kota
## dbl (1): OrderID
## lgl (1): Total
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Rows: 50 Columns: 9
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (7): Tanggal, Produk, Kategori, Harga, Jumlah, Pembeli, Kota
## dbl (1): OrderID
## lgl (1): Total
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Gabungkan ketiga data menjadi satu dataset
gabungan_df <- bind_rows(januari_df, februari_df, maret_df)
# Tampilkan jumlah total baris dan kolom setelah digabung
jumlah_baris_kolom <- dim(gabungan_df)
print(jumlah_baris_kolom)
## [1] 150 9
Bagian 2 Data Cleaning
## Warning: package 'lubridate' was built under R version 4.4.3
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
library(readr)
library(stringr)
# 1. Baca file CSV
januari_df <- read_csv("Januari.csv", show_col_types = FALSE)
februari_df <- read_csv("Februari.csv", show_col_types = FALSE)
maret_df <- read_csv("Maret.csv", show_col_types = FALSE)
# 2. Gabungkan ketiga data
gabungan_df <- bind_rows(januari_df, februari_df, maret_df)
# 3. a. Standarkan format tanggal ke YYYY-MM-DD
gabungan_df$Tanggal <- dmy(gabungan_df$Tanggal)
# 4. b & d. Bersihkan Harga dan Jumlah → hilangkan karakter non-numerik lalu ubah ke numerik
gabungan_df <- gabungan_df %>%
mutate(
Harga = str_replace_all(Harga, "[^0-9]", ""),
Jumlah = str_replace_all(Jumlah, "[^0-9]", ""),
Harga = as.numeric(Harga),
Jumlah = as.numeric(Jumlah)
)
# 5. c. Hitung ulang kolom Total
gabungan_df <- gabungan_df %>%
mutate(Total = Harga * Jumlah)
# 6. e. Hapus baris yang Produk-nya kosong atau "-"
gabungan_df <- gabungan_df %>%
filter(!is.na(Produk) & Produk != "" & Produk != "-")
# 7. Opsional: Buang baris dengan Harga atau Jumlah kosong (supaya Total valid)
gabungan_df <- gabungan_df %>%
filter(!is.na(Harga), !is.na(Jumlah), !is.na(Total))
# 8. Tampilkan hasil bersih
head(gabungan_df)
Bagian 3 Data Transformation
library(dplyr)
library(lubridate)
library(readr)
library(stringr)
# 1. Baca data
januari_df <- read_csv("Januari.csv", show_col_types = FALSE)
februari_df <- read_csv("Februari.csv", show_col_types = FALSE)
maret_df <- read_csv("Maret.csv", show_col_types = FALSE)
# 2. Gabungkan data
gabungan_df <- bind_rows(januari_df, februari_df, maret_df)
# 3. Bersihkan kolom Harga dan Jumlah
gabungan_df <- gabungan_df %>%
mutate(
Tanggal = dmy(Tanggal),
Harga = str_replace_all(Harga, "[^0-9]", ""),
Jumlah = str_replace_all(Jumlah, "[^0-9]", ""),
Harga = as.numeric(Harga),
Jumlah = as.numeric(Jumlah),
Total = Harga * Jumlah
)
# 4. Filter data valid (tanpa NA dan tanpa 0)
gabungan_df <- gabungan_df %>%
filter(
!is.na(Tanggal),
!is.na(Produk), Produk != "", Produk != "-",
!is.na(Harga), Harga > 0,
!is.na(Jumlah), Jumlah > 0,
!is.na(Total), Total > 0
)
# 5. Tambah kolom Bulan
gabungan_df <- gabungan_df %>%
mutate(Bulan = format(Tanggal, "%Y-%m"))
# 6. Analisis
# a. Total penjualan per kategori produk
total_per_kategori <- gabungan_df %>%
group_by(Produk) %>%
summarise(Total_Penjualan = sum(Total)) %>%
filter(Total_Penjualan > 0)
# b. Jumlah transaksi per kota
jumlah_transaksi_per_kota <- gabungan_df %>%
group_by(Kota) %>%
summarise(Jumlah_Transaksi = n()) %>%
filter(Jumlah_Transaksi > 0)
# c. Ringkasan total penjualan per bulan
ringkasan_bulanan <- gabungan_df %>%
group_by(Bulan) %>%
summarise(Total_Penjualan_Bulanan = sum(Total)) %>%
filter(Total_Penjualan_Bulanan > 0)
# 7. Tampilkan hasil
cat("\n=== Total Penjualan per Kategori Produk ===\n")
##
## === Total Penjualan per Kategori Produk ===
## # A tibble: 5 × 2
## Produk Total_Penjualan
## <chr> <dbl>
## 1 Kemeja 302200000
## 2 Laptop A 163150000
## 3 Sepatu 'Nike' 111900000
## 4 Smartphone X 114000000
## 5 Tas Branded 239950000
##
## === Jumlah Transaksi per Kota ===
## # A tibble: 4 × 2
## Kota Jumlah_Transaksi
## <chr> <int>
## 1 - 19
## 2 Bandung 22
## 3 Jakarta 18
## 4 Surabaya 20
##
## === Ringkasan Total Penjualan per Bulan ===
## # A tibble: 4 × 2
## Bulan Total_Penjualan_Bulanan
## <chr> <dbl>
## 1 2024-01 211650000
## 2 2024-02 311200000
## 3 2024-03 350250000
## 4 2024-04 58100000
LS0tDQp0aXRsZTogIlVUUyBQZW1yb2dyYW1hbiBEYXRhIFNjaWVuY2UiDQpzdWJ0aXRsZTogIkRhdGEgU2NpZW5jZSBQcm9ncmFtbWluZyINCmF1dGhvcjogDQogIC0gIkNoZWxsbyBGcmhpbm8gTWlrZSBNICg1MjI0MDAzMSkiDQpkYXRlOiAgImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjogICAjIGh0dHBzOi8vZ2l0aHViLmNvbS9qdWJhL3JtZGZvcm1hdHMNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIHRodW1ibmFpbHM6IHRydWUNCiAgICBsaWdodGJveDogdHJ1ZQ0KICAgIGdhbGxlcnk6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBsaWJfZGlyOiBsaWJzDQogICAgZGZfcHJpbnQ6ICJwYWdlZCINCiAgICBjb2RlX2ZvbGRpbmc6ICJzaG93Ig0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIA0KLS0tDQoNCiMgKioxLiBPcGVyYXNpIGRhbiBUaXBlIERhdGEgRGFzYXIqKg0KDQpgYGB7cix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0V9DQojIGEuIE1lbmVyaW1hIGR1YSBiaWxhbmdhbiBkYXJpIHBlbmdndW5hDQpBIDwtIGFzLmludGVnZXIocmVhZGxpbmUocHJvbXB0ID0gIk1hc3Vra2FuIGJpbGFuZ2FuIHBlcnRhbWEgKGludCk6ICIpKQ0KQiA8LSBhcy5pbnRlZ2VyKHJlYWRsaW5lKHByb21wdCA9ICJNYXN1a2thbiBiaWxhbmdhbiBrZWR1YSAoaW50KTogIikpDQoNCiMgYi4gTWVuZ2hpdHVuZyBoYXNpbCBvcGVyYXNpDQpwZW5qdW1sYWhhbiA8LSBBICsgQg0KcGVya2FsaWFuIDwtIEEgKiBCDQpwZW1iYWdpYW4gPC0gQS9CDQpwYW5na2F0IDwtIEEgXiBCDQoNCiMgYy4gTWVuYW1waWxrYW4gaGFzaWwgZGFuIHRpcGUgZGF0YW55YQ0KY2F0KCJcbkhhc2lsIE9wZXJhc2k6XG4iKQ0KY2F0KCJQZW5qdW1sYWhhbjoiLCBwZW5qdW1sYWhhbiwgIih0aXBlOiIsIHR5cGVvZihwZW5qdW1sYWhhbiksICIpXG4iKQ0KY2F0KCJQZXJrYWxpYW46IiwgcGVya2FsaWFuLCAiKHRpcGU6IiwgdHlwZW9mKHBlcmthbGlhbiksICIpXG4iKQ0KY2F0KCJQZW1iYWdpYW46IiwgcGVtYmFnaWFuLCAiKHRpcGU6IiwgaWYgKGlzLm51bWVyaWMocGVtYmFnaWFuKSkgdHlwZW9mKHBlbWJhZ2lhbikgZWxzZSB0eXBlb2YoYXMuY2hhcmFjdGVyKHBlbWJhZ2lhbikpLCAiKVxuIikNCmNhdCgiUGFuZ2thdDoiLCBwYW5na2F0LCAiKHRpcGU6IiwgdHlwZW9mKHBhbmdrYXQpLCAiKVxuIikNCg0KYGBgDQoNCiMgKioyLiBTdHJ1a3R1ciBLZW5kYWxpIChDb250cm9sIEZsb3cpKioNCg0KYGBge3J9DQojIElucHV0IG5pbGFpDQpuaWxhaSA8LSBhcy5pbnRlZ2VyKHJlYWRsaW5lKHByb21wdCA9ICJNYXN1a2thbiBuaWxhaSB1amlhbiAoMOKAkzEwMCk6ICIpKQ0KDQojIE1lbmVudHVrYW4ga2V0ZXJhbmdhbiBuaWxhaQ0KaWYgKCFpcy5uYShuaWxhaSkpIHsNCiAgaWYgKG5pbGFpID49IDAgJiYgbmlsYWkgPCA2MCkgew0KICAgIGtldGVyYW5nYW4gPC0gIlBlcmx1IFBlcmJhaWthbiINCiAgfSBlbHNlIGlmIChuaWxhaSA8PSA2OSkgew0KICAgIGtldGVyYW5nYW4gPC0gIkN1a3VwIg0KICB9IGVsc2UgaWYgKG5pbGFpIDw9IDg0KSB7DQogICAga2V0ZXJhbmdhbiA8LSAiQmFpayINCiAgfSBlbHNlIGlmIChuaWxhaSA8PSAxMDApIHsNCiAgICBrZXRlcmFuZ2FuIDwtICJTYW5nYXQgQmFpayINCiAgfSBlbHNlIHsNCiAgICBrZXRlcmFuZ2FuIDwtICJOaWxhaSB0aWRhayB2YWxpZCAoZGkgbHVhciAw4oCTMTAwKSINCiAgfQ0KfSBlbHNlIHsNCiAga2V0ZXJhbmdhbiA8LSAiSW5wdXQgdGlkYWsgdmFsaWQgKGJ1a2FuIGFuZ2thKSINCn0NCg0KIyBUYW1waWxrYW4gaGFzaWwNCmNhdCgiTmlsYWkgQW5kYToiLCBuaWxhaSwgIlxuIikNCmNhdCgiS2V0ZXJhbmdhbjoiLCBrZXRlcmFuZ2FuLCAiXG4iKQ0KDQpgYGANCg0KIyAqKjMuIEZ1bmdzaSBkYW4gUGVydWxhbmdhbioqDQoNCmBgYHtyfQ0KIyBhLiBNZW5lcmltYSBpbnB1dCBpbnRlZ2VyIG4NCmlmIChpbnRlcmFjdGl2ZSgpKSB7DQogIG4gPC0gYXMuaW50ZWdlcihyZWFkbGluZShwcm9tcHQgPSAiTWFzdWtrYW4gYmlsYW5nYW4gYnVsYXQgbjogIikpDQp9IGVsc2Ugew0KICBuIDwtIDQwICAjIE5pbGFpIGRlZmF1bHQgc2FhdCBwcm9zZXMga25pdA0KfQ0KDQojIGIuIE1lbmdndW5ha2FuIGxvb3AgdW50dWsgbWVuY2V0YWsgc2VtdWEgYmlsYW5nYW4gZ2VuYXAga2VsaXBhdGFuIDQgZGFyaSAxIGhpbmdnYSBuDQpjYXQoc3ByaW50ZigiU2VtdWEgYmlsYW5nYW4gZ2VuYXAga2VsaXBhdGFuIDQgZGFyaSAxIGhpbmdnYSAlZDpcbiIsIG4pKQ0KZm9yIChpIGluIHNlcSg0LCBuLCBieSA9IDQpKSB7DQogIGlmIChpICsgNCA8PSBuKSB7DQogICAgY2F0KGksICIsICIsIHNlcCA9ICIiKQ0KICB9IGVsc2Ugew0KICAgIGNhdChpLCAiXG4iKQ0KICB9DQp9DQoNCmBgYA0KDQojICoqNC4gU3R1ZGkgS2FzdXMqKg0KQmFnaWFuIDEgRGF0YSBDb2xsZWN0aW9uDQpgYGB7cn0NCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KDQojIE1lbmd1bmdnYWggZmlsZSBDU1YNCmphbnVhcmlfZGYgPC0gcmVhZF9jc3YoIkphbnVhcmkuY3N2IikNCmZlYnJ1YXJpX2RmIDwtIHJlYWRfY3N2KCJGZWJydWFyaS5jc3YiKQ0KbWFyZXRfZGYgPC0gcmVhZF9jc3YoIk1hcmV0LmNzdiIpDQoNCiMgR2FidW5na2FuIGtldGlnYSBkYXRhIG1lbmphZGkgc2F0dSBkYXRhc2V0DQpnYWJ1bmdhbl9kZiA8LSBiaW5kX3Jvd3MoamFudWFyaV9kZiwgZmVicnVhcmlfZGYsIG1hcmV0X2RmKQ0KDQojIFRhbXBpbGthbiBqdW1sYWggdG90YWwgYmFyaXMgZGFuIGtvbG9tIHNldGVsYWggZGlnYWJ1bmcNCmp1bWxhaF9iYXJpc19rb2xvbSA8LSBkaW0oZ2FidW5nYW5fZGYpDQpwcmludChqdW1sYWhfYmFyaXNfa29sb20pDQoNCiMgVGFtcGlsa2FuIGJlYmVyYXBhIGJhcmlzIHBlcnRhbWEgZGFyaSBkYXRhc2V0DQpoZWFkKGdhYnVuZ2FuX2RmKQ0KDQpgYGANCg0KQmFnaWFuIDIgRGF0YSBDbGVhbmluZw0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KHN0cmluZ3IpDQoNCiMgMS4gQmFjYSBmaWxlIENTVg0KamFudWFyaV9kZiA8LSByZWFkX2NzdigiSmFudWFyaS5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQ0KZmVicnVhcmlfZGYgPC0gcmVhZF9jc3YoIkZlYnJ1YXJpLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQptYXJldF9kZiA8LSByZWFkX2NzdigiTWFyZXQuY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkNCg0KIyAyLiBHYWJ1bmdrYW4ga2V0aWdhIGRhdGENCmdhYnVuZ2FuX2RmIDwtIGJpbmRfcm93cyhqYW51YXJpX2RmLCBmZWJydWFyaV9kZiwgbWFyZXRfZGYpDQoNCiMgMy4gYS4gU3RhbmRhcmthbiBmb3JtYXQgdGFuZ2dhbCBrZSBZWVlZLU1NLUREDQpnYWJ1bmdhbl9kZiRUYW5nZ2FsIDwtIGRteShnYWJ1bmdhbl9kZiRUYW5nZ2FsKQ0KDQojIDQuIGIgJiBkLiBCZXJzaWhrYW4gSGFyZ2EgZGFuIEp1bWxhaCDihpIgaGlsYW5na2FuIGthcmFrdGVyIG5vbi1udW1lcmlrIGxhbHUgdWJhaCBrZSBudW1lcmlrDQpnYWJ1bmdhbl9kZiA8LSBnYWJ1bmdhbl9kZiAlPiUNCiAgbXV0YXRlKA0KICAgIEhhcmdhID0gc3RyX3JlcGxhY2VfYWxsKEhhcmdhLCAiW14wLTldIiwgIiIpLA0KICAgIEp1bWxhaCA9IHN0cl9yZXBsYWNlX2FsbChKdW1sYWgsICJbXjAtOV0iLCAiIiksDQogICAgSGFyZ2EgPSBhcy5udW1lcmljKEhhcmdhKSwNCiAgICBKdW1sYWggPSBhcy5udW1lcmljKEp1bWxhaCkNCiAgKQ0KDQojIDUuIGMuIEhpdHVuZyB1bGFuZyBrb2xvbSBUb3RhbA0KZ2FidW5nYW5fZGYgPC0gZ2FidW5nYW5fZGYgJT4lDQogIG11dGF0ZShUb3RhbCA9IEhhcmdhICogSnVtbGFoKQ0KDQojIDYuIGUuIEhhcHVzIGJhcmlzIHlhbmcgUHJvZHVrLW55YSBrb3NvbmcgYXRhdSAiLSINCmdhYnVuZ2FuX2RmIDwtIGdhYnVuZ2FuX2RmICU+JQ0KICBmaWx0ZXIoIWlzLm5hKFByb2R1aykgJiBQcm9kdWsgIT0gIiIgJiBQcm9kdWsgIT0gIi0iKQ0KDQojIDcuIE9wc2lvbmFsOiBCdWFuZyBiYXJpcyBkZW5nYW4gSGFyZ2EgYXRhdSBKdW1sYWgga29zb25nIChzdXBheWEgVG90YWwgdmFsaWQpDQpnYWJ1bmdhbl9kZiA8LSBnYWJ1bmdhbl9kZiAlPiUNCiAgZmlsdGVyKCFpcy5uYShIYXJnYSksICFpcy5uYShKdW1sYWgpLCAhaXMubmEoVG90YWwpKQ0KDQojIDguIFRhbXBpbGthbiBoYXNpbCBiZXJzaWgNCmhlYWQoZ2FidW5nYW5fZGYpDQoNCmBgYA0KDQpCYWdpYW4gMyBEYXRhIFRyYW5zZm9ybWF0aW9uDQoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoc3RyaW5ncikNCg0KIyAxLiBCYWNhIGRhdGENCmphbnVhcmlfZGYgPC0gcmVhZF9jc3YoIkphbnVhcmkuY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkNCmZlYnJ1YXJpX2RmIDwtIHJlYWRfY3N2KCJGZWJydWFyaS5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQ0KbWFyZXRfZGYgPC0gcmVhZF9jc3YoIk1hcmV0LmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpDQoNCiMgMi4gR2FidW5na2FuIGRhdGENCmdhYnVuZ2FuX2RmIDwtIGJpbmRfcm93cyhqYW51YXJpX2RmLCBmZWJydWFyaV9kZiwgbWFyZXRfZGYpDQoNCiMgMy4gQmVyc2loa2FuIGtvbG9tIEhhcmdhIGRhbiBKdW1sYWgNCmdhYnVuZ2FuX2RmIDwtIGdhYnVuZ2FuX2RmICU+JQ0KICBtdXRhdGUoDQogICAgVGFuZ2dhbCA9IGRteShUYW5nZ2FsKSwNCiAgICBIYXJnYSA9IHN0cl9yZXBsYWNlX2FsbChIYXJnYSwgIlteMC05XSIsICIiKSwNCiAgICBKdW1sYWggPSBzdHJfcmVwbGFjZV9hbGwoSnVtbGFoLCAiW14wLTldIiwgIiIpLA0KICAgIEhhcmdhID0gYXMubnVtZXJpYyhIYXJnYSksDQogICAgSnVtbGFoID0gYXMubnVtZXJpYyhKdW1sYWgpLA0KICAgIFRvdGFsID0gSGFyZ2EgKiBKdW1sYWgNCiAgKQ0KDQojIDQuIEZpbHRlciBkYXRhIHZhbGlkICh0YW5wYSBOQSBkYW4gdGFucGEgMCkNCmdhYnVuZ2FuX2RmIDwtIGdhYnVuZ2FuX2RmICU+JQ0KICBmaWx0ZXIoDQogICAgIWlzLm5hKFRhbmdnYWwpLA0KICAgICFpcy5uYShQcm9kdWspLCBQcm9kdWsgIT0gIiIsIFByb2R1ayAhPSAiLSIsDQogICAgIWlzLm5hKEhhcmdhKSwgSGFyZ2EgPiAwLA0KICAgICFpcy5uYShKdW1sYWgpLCBKdW1sYWggPiAwLA0KICAgICFpcy5uYShUb3RhbCksIFRvdGFsID4gMA0KICApDQoNCiMgNS4gVGFtYmFoIGtvbG9tIEJ1bGFuDQpnYWJ1bmdhbl9kZiA8LSBnYWJ1bmdhbl9kZiAlPiUNCiAgbXV0YXRlKEJ1bGFuID0gZm9ybWF0KFRhbmdnYWwsICIlWS0lbSIpKQ0KDQojIDYuIEFuYWxpc2lzDQoNCiMgYS4gVG90YWwgcGVuanVhbGFuIHBlciBrYXRlZ29yaSBwcm9kdWsNCnRvdGFsX3Blcl9rYXRlZ29yaSA8LSBnYWJ1bmdhbl9kZiAlPiUNCiAgZ3JvdXBfYnkoUHJvZHVrKSAlPiUNCiAgc3VtbWFyaXNlKFRvdGFsX1Blbmp1YWxhbiA9IHN1bShUb3RhbCkpICU+JQ0KICBmaWx0ZXIoVG90YWxfUGVuanVhbGFuID4gMCkNCg0KIyBiLiBKdW1sYWggdHJhbnNha3NpIHBlciBrb3RhDQpqdW1sYWhfdHJhbnNha3NpX3Blcl9rb3RhIDwtIGdhYnVuZ2FuX2RmICU+JQ0KICBncm91cF9ieShLb3RhKSAlPiUNCiAgc3VtbWFyaXNlKEp1bWxhaF9UcmFuc2Frc2kgPSBuKCkpICU+JQ0KICBmaWx0ZXIoSnVtbGFoX1RyYW5zYWtzaSA+IDApDQoNCiMgYy4gUmluZ2thc2FuIHRvdGFsIHBlbmp1YWxhbiBwZXIgYnVsYW4NCnJpbmdrYXNhbl9idWxhbmFuIDwtIGdhYnVuZ2FuX2RmICU+JQ0KICBncm91cF9ieShCdWxhbikgJT4lDQogIHN1bW1hcmlzZShUb3RhbF9QZW5qdWFsYW5fQnVsYW5hbiA9IHN1bShUb3RhbCkpICU+JQ0KICBmaWx0ZXIoVG90YWxfUGVuanVhbGFuX0J1bGFuYW4gPiAwKQ0KDQojIDcuIFRhbXBpbGthbiBoYXNpbA0KY2F0KCJcbj09PSBUb3RhbCBQZW5qdWFsYW4gcGVyIEthdGVnb3JpIFByb2R1ayA9PT1cbiIpDQpwcmludCh0b3RhbF9wZXJfa2F0ZWdvcmkpDQoNCmNhdCgiXG49PT0gSnVtbGFoIFRyYW5zYWtzaSBwZXIgS290YSA9PT1cbiIpDQpwcmludChqdW1sYWhfdHJhbnNha3NpX3Blcl9rb3RhKQ0KDQpjYXQoIlxuPT09IFJpbmdrYXNhbiBUb3RhbCBQZW5qdWFsYW4gcGVyIEJ1bGFuID09PVxuIikNCnByaW50KHJpbmdrYXNhbl9idWxhbmFuKQ0KDQoNCmBgYA0KDQo=