# ==========================================
# PERSIAPAN DATA
# ==========================================

# Membuat data produk
produk <- data.frame(
  kode = c(104, 101, 107, 103, 106, 102, 105),
  nama = c("Telur", "Beras", "Kopi", "Minyak",
           "Garam", "Gula", "Tepung"),
  stok = c(25, 40, 18, 30, 50, 35, 28)
)

cat("\n========== DATA PRODUK ==========\n")
## 
## ========== DATA PRODUK ==========
print(produk)
##   kode   nama stok
## 1  104  Telur   25
## 2  101  Beras   40
## 3  107   Kopi   18
## 4  103 Minyak   30
## 5  106  Garam   50
## 6  102   Gula   35
## 7  105 Tepung   28
# Mengurutkan data berdasarkan kode
urutan <- order(produk$kode)

produk_urut <- produk[urutan, , drop = FALSE]

cat("\n========== DATA SETELAH SORTING ==========\n")
## 
## ========== DATA SETELAH SORTING ==========
print(produk_urut)
##   kode   nama stok
## 2  101  Beras   40
## 6  102   Gula   35
## 4  103 Minyak   30
## 1  104  Telur   25
## 7  105 Tepung   28
## 5  106  Garam   50
## 3  107   Kopi   18
# ==========================================
# DEFINISI FUNGSI BINARY SEARCH
# ==========================================

# A. Fungsi jejak_binary()

jejak_binary <- function(data, target) {

  if (is.unsorted(data)) {
    stop("Data harus terurut terlebih dahulu!")
  }

  kiri <- 1
  kanan <- length(data)

  jejak <- data.frame(
    kiri = integer(),
    kanan = integer(),
    tengah = integer(),
    nilai_tengah = numeric()
  )

  while (kiri <= kanan) {

    tengah <- floor((kiri + kanan) / 2)

    jejak <- rbind(
      jejak,
      data.frame(
        kiri = kiri,
        kanan = kanan,
        tengah = tengah,
        nilai_tengah = data[tengah]
      )
    )

    if (data[tengah] == target) {
      break
    } else if (data[tengah] < target) {
      kiri <- tengah + 1
    } else {
      kanan <- tengah - 1
    }
  }

  return(jejak)
}


# B. Fungsi bin_boolean()

bin_boolean <- function(data, target) {

  if (is.unsorted(data)) {
    stop("Data harus terurut terlebih dahulu!")
  }

  kiri <- 1
  kanan <- length(data)

  while (kiri <= kanan) {

    tengah <- floor((kiri + kanan) / 2)

    if (data[tengah] == target) {
      return(TRUE)
    } else if (data[tengah] < target) {
      kiri <- tengah + 1
    } else {
      kanan <- tengah - 1
    }
  }

  return(FALSE)
}


# C. Fungsi bin_tanpa_boolean()

bin_tanpa_boolean <- function(data, target) {

  if (is.unsorted(data)) {
    stop("Data harus terurut terlebih dahulu!")
  }

  kiri <- 1
  kanan <- length(data)

  while (kiri <= kanan) {

    tengah <- floor((kiri + kanan) / 2)

    if (data[tengah] == target) {
      return(tengah)
    } else if (data[tengah] < target) {
      kiri <- tengah + 1
    } else {
      kanan <- tengah - 1
    }
  }

  return(NA_integer_)
}


# D. Fungsi bin_pertama()

bin_pertama <- function(data, target) {

  if (is.unsorted(data)) {
    stop("Data harus terurut terlebih dahulu!")
  }

  kiri <- 1
  kanan <- length(data)
  hasil <- NA_integer_

  while (kiri <= kanan) {

    tengah <- floor((kiri + kanan) / 2)

    if (data[tengah] == target) {
      hasil <- tengah
      kanan <- tengah - 1
    } else if (data[tengah] < target) {
      kiri <- tengah + 1
    } else {
      kanan <- tengah - 1
    }
  }

  return(hasil)
}


# ==========================================
# DEFINISI FUNGSI SEQUENTIAL SEARCH
# ==========================================

kunjungan_sequential <- function(data, target) {

  kunjungan <- 0

  for (i in seq_along(data)) {

    kunjungan <- kunjungan + 1

    if (data[i] == target) {
      break
    }
  }

  return(kunjungan)
}
# ==========================================
# 12A. JEJAK PENCARIAN 80
# ==========================================

cat("\n========== LATIHAN 12A ==========\n")
## 
## ========== LATIHAN 12A ==========
lat_urut <- seq(10, 100, by = 10)

cat("\nData terurut:\n")
## 
## Data terurut:
print(lat_urut)
##  [1]  10  20  30  40  50  60  70  80  90 100
cat("\nJejak pencarian angka 80:\n")
## 
## Jejak pencarian angka 80:
print(jejak_binary(lat_urut, 80))
##   kiri kanan tengah nilai_tengah
## 1    1    10      5           50
## 2    6    10      8           80
# ==========================================
# 12B. KASUS BATAS BINARY SEARCH
# ==========================================

cat("\n========== LATIHAN 12B ==========\n")
## 
## ========== LATIHAN 12B ==========
cat("\nMencari angka 10:\n")
## 
## Mencari angka 10:
print(bin_boolean(lat_urut, 10))
## [1] TRUE
cat("\nMencari angka 100:\n")
## 
## Mencari angka 100:
print(bin_tanpa_boolean(lat_urut, 100))
## [1] 10
cat("\nMencari angka 105:\n")
## 
## Mencari angka 105:
print(bin_boolean(lat_urut, 105))
## [1] FALSE
# ==========================================
# 12C. DUPLIKASI DAN POSISI PERTAMA
# ==========================================

cat("\n========== LATIHAN 12C ==========\n")
## 
## ========== LATIHAN 12C ==========
data_duplikat <- c(10, 20, 20, 20, 30)

cat("\nData duplikat:\n")
## 
## Data duplikat:
print(data_duplikat)
## [1] 10 20 20 20 30
cat("\nPencarian menggunakan bin_boolean:\n")
## 
## Pencarian menggunakan bin_boolean:
print(bin_boolean(data_duplikat, 20))
## [1] TRUE
cat("\nPencarian posisi pertama:\n")
## 
## Pencarian posisi pertama:
print(bin_pertama(data_duplikat, 20))
## [1] 2
# ==========================================
# 12D. KODE 103 PADA TABEL PRODUK
# ==========================================

cat("\n========== LATIHAN 12D ==========\n")
## 
## ========== LATIHAN 12D ==========
p <- bin_tanpa_boolean(produk_urut$kode, 103)

cat("\nPosisi setelah sorting:\n")
## 
## Posisi setelah sorting:
print(p)
## [1] 3
cat("\nPosisi pada tabel asli:\n")
## 
## Posisi pada tabel asli:
print(urutan[p])
## [1] 4
cat("\nInformasi produk kode 103:\n")
## 
## Informasi produk kode 103:
print(produk_urut[p, , drop = FALSE])
##   kode   nama stok
## 4  103 Minyak   30
# ==========================================
# 12E. VALIDASI DATA BELUM TERURUT
# ==========================================

cat("\n========== LATIHAN 12E ==========\n")
## 
## ========== LATIHAN 12E ==========
cat("\nData yang belum terurut:\n")
## 
## Data yang belum terurut:
print(c(30, 10, 20))
## [1] 30 10 20
cat("\nHasil validasi:\n")
## 
## Hasil validasi:
print(
  tryCatch(
    bin_boolean(c(30, 10, 20), 20),
    error = function(e) conditionMessage(e)
  )
)
## [1] "Data harus terurut terlebih dahulu!"
# ==========================================
# 12F. PERBANDINGAN KUNJUNGAN TARGET TERAKHIR
# ==========================================

cat("\n========== LATIHAN 12F ==========\n")
## 
## ========== LATIHAN 12F ==========
data_besar <- seq_len(1024)

cat("\nJumlah kunjungan Sequential Search:\n")
## 
## Jumlah kunjungan Sequential Search:
hasil_sequential <- kunjungan_sequential(
  data_besar, 1024
)

print(hasil_sequential)
## [1] 1024
cat("\nJumlah kunjungan Binary Search:\n")
## 
## Jumlah kunjungan Binary Search:
hasil_binary <- nrow(
  jejak_binary(data_besar, 1024)
)

print(hasil_binary)
## [1] 11
cat("\nTabel perbandingan:\n")
## 
## Tabel perbandingan:
print(data.frame(
  Metode = c("Sequential Search", "Binary Search"),
  Jumlah_Kunjungan = c(
    hasil_sequential,
    hasil_binary
  )
))
##              Metode Jumlah_Kunjungan
## 1 Sequential Search             1024
## 2     Binary Search               11