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):
B <- as.integer(readline(prompt = "Masukkan bilangan kedua (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:
cat("Penjumlahan:", penjumlahan, "(tipe:", typeof(penjumlahan), ")\n")
## Penjumlahan: NA (tipe: integer )
cat("Perkalian:", perkalian, "(tipe:", typeof(perkalian), ")\n")
## Perkalian: NA (tipe: integer )
cat("Pembagian:", pembagian, "(tipe:", if (is.numeric(pembagian)) typeof(pembagian) else typeof(as.character(pembagian)), ")\n")
## Pembagian: NA (tipe: double )
cat("Pangkat:", pangkat, "(tipe:", typeof(pangkat), ")\n")
## Pangkat: NA (tipe: double )

2 2. Struktur Kendali (Control Flow)

# Input nilai
nilai <- as.integer(readline(prompt = "Masukkan nilai ujian (0–100): "))
## 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
cat("Keterangan:", keterangan, "\n")
## 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:
for (i in seq(4, n, by = 4)) {
  if (i + 4 <= n) {
    cat(i, ", ", sep = "")
  } else {
    cat(i, "\n")
  }
}
## 4, 8, 12, 16, 20, 24, 28, 32, 36, 40

4 4. Studi Kasus

Bagian 1 Data Collection

library(readr)
## Warning: package 'readr' was built under R version 4.4.3
library(dplyr)
## 
## 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
# Mengunggah file CSV
januari_df <- read_csv("Januari.csv")
## 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.
februari_df <- read_csv("Februari.csv")
## 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.
maret_df <- read_csv("Maret.csv")
## 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
# Tampilkan beberapa baris pertama dari dataset
head(gabungan_df)

Bagian 2 Data Cleaning

library(dplyr)
library(lubridate)
## 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 ===
print(total_per_kategori)
## # 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
cat("\n=== Jumlah Transaksi per Kota ===\n")
## 
## === Jumlah Transaksi per Kota ===
print(jumlah_transaksi_per_kota)
## # A tibble: 4 × 2
##   Kota     Jumlah_Transaksi
##   <chr>               <int>
## 1 -                      19
## 2 Bandung                22
## 3 Jakarta                18
## 4 Surabaya               20
cat("\n=== Ringkasan Total Penjualan per Bulan ===\n")
## 
## === Ringkasan Total Penjualan per Bulan ===
print(ringkasan_bulanan)
## # 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=