#No 1. 
set.seed(123)
## 1. Generate 10.000 angka random dari distribusi Uniform(0,1)
x <- runif(10000, min = 0, max = 1)

## 2. menghitung nilai pendekatan E(X^2)
ekspektasi_x2 <- mean(x^2)
cat("Pendekatan E(X^2):", ekspektasi_x2, "\n")
## Pendekatan E(X^2): 0.3297405
## 4. membandingkan dengan nilai eksak
eksak <- 1/3
cat("Nilai eksak E(X^2):", eksak, "\n")
## Nilai eksak E(X^2): 0.3333333
cat("Selisih:", abs(ekspektasi_x2 - eksak), "\n")
## Selisih: 0.003592882
#No 2 
set.seed(123)

##Parameter distribusi
mean_true <- 100
sd_true <- 15

## Simulasi untuk n1 = 100
n1 <- 100
data1 <- rnorm(n1, mean = mean_true, sd = sd_true)
mean1 <- mean(data1)
sd1 <- sd(data1)

## Simulasi untuk n2 = 1000
n2 <- 1000
data2 <- rnorm(n2, mean = mean_true, sd = sd_true)
mean2 <- mean(data2)
sd2 <- sd(data2)

## Simulasi untuk n3 = 10000
n3 <- 10000
data3 <- rnorm(n3, mean = mean_true, sd = sd_true)
mean3 <- mean(data3)
sd3 <- sd(data3)

## menampilkan hasil ringkasan
cat("n = 100:    Mean =", mean1, ", SD =", sd1, "\n")
## n = 100:    Mean = 101.3561 , SD = 13.69224
cat("n = 1000:   Mean =", mean2, ", SD =", sd2, "\n")
## n = 1000:   Mean = 100.2862 , SD = 15.06891
cat("n = 10000:  Mean =", mean3, ", SD =", sd3, "\n")
## n = 10000:  Mean = 99.96336 , SD = 14.98314
## Plot histogram untuk ketiga sampel
par(mfrow = c(1, 3))
hist(data1, main = "Histogram n = 100", col = "pink", xlab = "Nilai", breaks = 20)
hist(data2, main = "Histogram n = 1000", col = "salmon", xlab = "Nilai", breaks = 30)
hist(data3, main = "Histogram n = 10000", col = "maroon", xlab = "Nilai", breaks = 40)

Pada soal ini, dilakukan simulasi pengambilan data dari distribusi normal N=(100,15^2)dengan tiga ukuran sampel yang berbeda, yaitu𝑛=100, 𝑛=1000, dan𝑛=10000. Tujuannya adalah untuk melihat bagaimana pengaruh besar sampel terhadap estimasi nilai rata-rata dan simpangan baku, serta bentuk distribusi data. Interpretasi Semakin besar ukuran sampel, estimasi semakin mendekati nilai parameter populasi.Rata-rata dan simpangan baku darisampel dengan𝑛=10000hampir sama dengan nilai parameter populasi, yaitu 100 dan 15.

Sebaliknya, pada𝑛=100, nilai estimasi masih cukup bervariasi dan belum stabil (lebih jauh dari parameter sebenarnya).

Variasi hasil lebih besar pada sampel kecil. Histogram untuk𝑛=100tampak kurang simetris dan lebih berombak.Sedangkan histogram untuk 𝑛=1000 dan terutama 𝑛=10000 terlihat semakin simetris dan menyerupai bentuk lonceng khas distribusi normal.

Bentuk distribusi semakin stabil mendekati bentuk teoritis ketika n besar. semakin banyak data, maka estimasi statistik (seperti mean dan SD) semakin mendekati nilai sebenarnya dari populasi.

#No. 3
set.seed(123)

## Simulasi 5000 kali dari distribusi Binomial(n = 30, p = 0.25)
sim_data <- rbinom(5000, size = 30, prob = 0.25)

## Estimasi peluang P(X >= 15)
estimasi_prob <- mean(sim_data >= 15)

## Menampilkan hasil
cat("Estimasi P(X >= 15) dari simulasi:", estimasi_prob, "\n")
## Estimasi P(X >= 15) dari simulasi: 0.0024
## Bandingkan dengan nilai teoritis
nilai_teoritis <- 1 - pbinom(14, size = 30, prob = 0.25)
cat("Nilai teoritis P(X >= 15):", nilai_teoritis, "\n")
## Nilai teoritis P(X >= 15): 0.002749534
#No. 4
## Buat fungsi untuk menghitung simpangan baku sesuai rumus
simpangan_baku_custom <- function(x) {
  n <- length(x)
  sum_x2 <- sum(x^2)
  sum_x <- sum(x)
  s <- sqrt((sum_x2 - (sum_x^2) / n) / (n - 1))
  return(s)
}

## Generate data normal: n = 1000, mean = 89, sd = 10
set.seed(123)
data <- rnorm(1000, mean = 89, sd = 10)

## Hitung simpangan baku menggunakan fungsi
s_custom <- simpangan_baku_custom(data)

## Bandingkan dengan sd() 
s_builtin <- sd(data)

## Tampilkan hasil
cat("Simpangan baku (fungsi custom):", s_custom, "\n")
## Simpangan baku (fungsi custom): 9.91695
cat("Simpangan baku (fungsi sd R):", s_builtin, "\n")
## Simpangan baku (fungsi sd R): 9.91695
#No 5
##a. membuat simulasi antrian selama 20 hari kerja 
set.seed(123)

n_days <- 20                ## Jumlah hari kerja
jam_kerja <- 6 * 60         ## Konversi jam ke menit: 6 jam = 360 menit
arrival_rate <- 1/12        ## Rata-rata 1 nasabah tiap 12 menit (Ξ» = 5/jam)
service_rate <- 1/8         ## Waktu pelayanan eksponensial (mean = 8 menit)
n_teller <- 2               ## Jumlah teller

## Variabel untuk menampung hasil
total_wait_times <- c()     ## Menyimpan waktu tunggu seluruh nasabah
teller_busy_time <- rep(0, n_teller)  ## Waktu sibuk per teller
for (day in 1:n_days) {
  waktu_kedatangan <- cumsum(rexp(1000, rate = arrival_rate))
  waktu_kedatangan <- waktu_kedatangan[waktu_kedatangan <= jam_kerja]
  n_customers <- length(waktu_kedatangan)
  waktu_pelayanan <- rexp(n_customers, rate = service_rate)
  waktu_mulai <- rep(0, n_customers)
  waktu_selesai <- rep(0, n_customers)
  teller_tersedia <- rep(0, n_teller) 

  ## Proses pelayanan tiap nasabah
  for (i in 1:n_customers) {
    teller_dipilih <- which.min(teller_tersedia)  # cari teller yang paling cepat siap
    waktu_mulai[i] <- max(waktu_kedatangan[i], teller_tersedia[teller_dipilih])
    waktu_selesai[i] <- waktu_mulai[i] + waktu_pelayanan[i]
    teller_tersedia[teller_dipilih] <- waktu_selesai[i]
    teller_busy_time[teller_dipilih] <- teller_busy_time[teller_dipilih] + waktu_pelayanan[i]
  }
  
  # b. menghitung berapa lama nasabah menunggu 
  waktu_tunggu <- waktu_mulai - waktu_kedatangan
  total_wait_times <- c(total_wait_times, waktu_tunggu)
}
# c. menghitung berapa lama teller sibuk bekerja 
rata_rata_tunggu <- mean(total_wait_times)
persen_teller_sibuk <- mean(teller_busy_time / (jam_kerja * n_days)) * 100

cat("Rata-rata waktu tunggu nasabah (menit):", round(rata_rata_tunggu, 2), "\n")
## Rata-rata waktu tunggu nasabah (menit): 0.88
cat("Persentase waktu teller sibuk:", round(persen_teller_sibuk, 2), "%\n")
## Persentase waktu teller sibuk: 29.03 %
## Mencoba membandingan jika di tambah dengan satu teller lagi 
n_teller_3 <- 3
teller_busy_time_3 <- rep(0, n_teller_3)
total_wait_times_3 <- c()

for (day in 1:n_days) {
  waktu_kedatangan <- cumsum(rexp(1000, rate = arrival_rate))
  waktu_kedatangan <- waktu_kedatangan[waktu_kedatangan <= jam_kerja]
  n_customers <- length(waktu_kedatangan)
  waktu_pelayanan <- rexp(n_customers, rate = service_rate)
  
  waktu_mulai <- rep(0, n_customers)
  waktu_selesai <- rep(0, n_customers)
  teller_tersedia <- rep(0, n_teller_3)
  
  for (i in 1:n_customers) {
    teller_dipilih <- which.min(teller_tersedia)
    waktu_mulai[i] <- max(waktu_kedatangan[i], teller_tersedia[teller_dipilih])
    waktu_selesai[i] <- waktu_mulai[i] + waktu_pelayanan[i]
    teller_tersedia[teller_dipilih] <- waktu_selesai[i]
    teller_busy_time_3[teller_dipilih] <- teller_busy_time_3[teller_dipilih] + waktu_pelayanan[i]
  }
  
  waktu_tunggu <- waktu_mulai - waktu_kedatangan
  total_wait_times_3 <- c(total_wait_times_3, waktu_tunggu)
}

# Hasil untuk 3 teller
rata_rata_tunggu_3 <- mean(total_wait_times_3)
persen_sibuk_3 <- mean(teller_busy_time_3 / (jam_kerja * n_days)) * 100

cat("Dengan 3 teller:\n")
## Dengan 3 teller:
cat("Rata-rata waktu tunggu:", round(rata_rata_tunggu_3, 2), "menit\n")
## Rata-rata waktu tunggu: 0.07 menit
cat("Persen sibuk teller:", round(persen_sibuk_3, 2), "%\n\n")
## Persen sibuk teller: 21.82 %
  1. Rata-rata waktu tunggu nasabah selama 20 hari kerja dengan 2 teller adalah 0.88 menit, yang tergolong sangat singkat. hal ini mengartikan bahwa sistem layanan sudah berjalan cukup efisien dalam menangani kedatangan nasabah sebanyak rata-rata 5 orang per jam.

  2. Ketika teller ditambah menjadi 3, waktu tunggu nasabah turun drastis menjadi 0.07 menit, artinya hampir tidak ada waktu tunggu. Namun, penurunan ini disertai dengan penurunan tingkat kesibukan teller menjadi hanya 21.82%, artinya sebagian besar waktu teller tidak digunakan secara produktif. Sebaliknya, saat menggunakan 2 teller, tingkat kesibukan berada di 29.03%, yang artinya teller bekerja cukup optimal tanpa terlalu banyak waktu kosong, dan tetap memberikan pelayanan yang cepat. jadi menurut saya walaupun jika teller di tambah 1 untuk mengurangi antrian nasabah dalam menunggu, dengan adanya 2 teller menurut saya masih di cukupkan untuk menjaga efesiensi operasional dan agar waktu kerja teller teetap produktif

#5e. membuat grafik dengan antrian sepanjang hari
set.seed(123)
n_teller <- 2
jam_kerja <- 360
arrival_rate <- 5 / 60    # 5 nasabah per jam β†’ konversi ke per menit
service_rate <- 1 / 6     # rata-rata waktu layanan 6 menit

waktu_kedatangan <- cumsum(rexp(1000, rate = arrival_rate))
waktu_kedatangan <- waktu_kedatangan[waktu_kedatangan <= jam_kerja]
n_customers <- length(waktu_kedatangan)
waktu_pelayanan <- rexp(n_customers, rate = service_rate)

waktu_mulai <- rep(0, n_customers)
waktu_selesai <- rep(0, n_customers)
teller_tersedia <- rep(0, n_teller)
antrian_per_menit <- numeric(jam_kerja)

for (i in 1:n_customers) {
  teller_dipilih <- which.min(teller_tersedia)
  waktu_mulai[i] <- max(waktu_kedatangan[i], teller_tersedia[teller_dipilih])
  waktu_selesai[i] <- waktu_mulai[i] + waktu_pelayanan[i]
  teller_tersedia[teller_dipilih] <- waktu_selesai[i]
  
  for (t in ceiling(waktu_kedatangan[i]):floor(waktu_mulai[i])) {
    if (t <= jam_kerja) {
      antrian_per_menit[t] <- antrian_per_menit[t] + 1
    }
  }
}

# Buat Grafik Antrian
plot(antrian_per_menit, type = "l", col = "blue", lwd = 2,
     main = "Grafik Panjang Antrian Sepanjang Hari",
     xlab = "Menit ke-", ylab = "Jumlah Nasabah dalam Antrian")
abline(h = mean(antrian_per_menit), col = "red", lty = 2)  # garis rata-rata antrian
legend("topright", legend = c("Jumlah Antrian", "Rata-rata"),
       col = c("blue", "red"), lty = c(1, 2), lwd = 2)

# No. 6
#a. mensimulasikan stok beras selama 60 hari
set.seed(123)
stok_awal <- 100
hari_total <- 60
frekuensi_pesan <- 5
jumlah_pesan <- 50
penjualan_per_hari <- sample(8:15, hari_total, replace = TRUE)

## Vektor untuk menyimpan stok harian
stok_harian <- numeric(hari_total)
stok_harian[1] <- stok_awal

## Simulasi stok per hari
for (hari in 2:hari_total) {
  stok_harian[hari] <- stok_harian[hari - 1] - penjualan_per_hari[hari - 1]
  
  if (hari %% frekuensi_pesan == 1) {
    stok_harian[hari] <- stok_harian[hari] + jumlah_pesan
  }
  
  ## Jika stok negatif, anggap habis
  if (stok_harian[hari] < 0) stok_harian[hari] <- 0
}

## Menampilkan stok akhir tiap hari
print(stok_harian)
##  [1] 100  86  72  62  49  89  80  71  58  48  86  75  62  49  41  82  72  57  45
## [20]  35  75  67  56  48  40  78  68  53  44  30  71  63  50  40  29  66  58  48
## [39]  34  22  61  47  32  23  11  47  39  31  22   8  48  37  25  11   0  40  25
## [58]  12   4   0
#b. Menghitung berapa kali toko kehabisan stok
jumlah_kehabisan <- sum(stok_harian == 0)
cat("Jumlah hari kehabisan stok:", jumlah_kehabisan, "hari\n")
## Jumlah hari kehabisan stok: 2 hari

Selama periode simulasi 60 hari, toko Bu Sari mengalami kehabisan stok sebanyak 2 hari. Ini menunjukkan bahwa strategi pemesanan ulang beras sebesar 50 karung setiap 5 hari sekali relatif cukup efektif dalam menjaga ketersediaan stok. Kehabisan stok hanya terjadi sekitar 3,3% dari total waktu operasional (2 dari 60 hari), sehingga risiko kehilangan pelanggan atau potensi kerugian akibat kehabisan barang masih tergolong rendah. Namun dengan adanya kehabisan stok walau hanya beberapa hari tetap perlu diperhatikan, karena dalam kasus ini setiap kehabisan satu karung beras mengakibatkan kerugian sebesar Rp50.000. Oleh karena itu, strategi pemesanan ini masih bisa dioptimalkan dengan cara: meningkatkan jumlah pesan ulang, atau memperpendek interval pemesanan.

#c. mencoba berbagai strategi: pesan 40, 50, atau 60 karung. Manakah yang terbaik?
simulasi_strategi <- function(jumlah_pesan) {
  stok <- numeric(hari_total)
  stok[1] <- stok_awal
  rugi <- 0
  
  for (hari in 2:hari_total) {
    penjualan <- penjualan_per_hari[hari - 1]
    
    if (stok[hari - 1] < penjualan) {
      rugi <- rugi + (penjualan - stok[hari - 1]) * 50000
      stok[hari] <- 0
    } else {
      stok[hari] <- stok[hari - 1] - penjualan
    }
    
    if (hari %% frekuensi_pesan == 1) {
      stok[hari] <- stok[hari] + jumlah_pesan
    }
  }
  
  jumlah_kehabisan <- sum(stok == 0)
  return(list(stok = stok, rugi = rugi, habis = jumlah_kehabisan))
}

## Coba berbagai strategi pesan
strategi <- c(40, 50, 60)
for (j in strategi) {
  hasil <- simulasi_strategi(j)
  cat("Strategi pesan", j, "karung β†’ Hari habis stok:", hasil$habis,
      ", Total rugi: Rp", format(hasil$rugi, big.mark = ","), "\n")
}
## Strategi pesan 40 karung β†’ Hari habis stok: 6 , Total rugi: Rp 5,800,000 
## Strategi pesan 50 karung β†’ Hari habis stok: 0 , Total rugi: Rp 550,000 
## Strategi pesan 60 karung β†’ Hari habis stok: 0 , Total rugi: Rp 0

Strategi 40 karung tidak cukup untuk memenuhi permintaan, karena toko kehabisan stok selama 6 hari, yang menyebabkan kerugian cukup besar (Rp5.800.000). Ini menunjukkan bahwa jumlah tersebut terlalu rendah dibanding kebutuhan harian rata-rata. Strategi 50 karung sudah jauh lebih baik. Meskipun toko tidak mengalami kehabisan stok (0 hari), masih ada sedikit kerugian (Rp550.000 Strategi 60 karung adalah yang paling aman dan efisien, karena toko tidak pernah kehabisan stok dan tidak mengalami kerugian sama sekali.

#d. Mencoba unutk merubah frekuensi pesan: setiap 3, 5, atau 7 hari. Manakah yang paling optimal?
simulasi_frekuensi <- function(freq) {
  stok <- numeric(hari_total)
  stok[1] <- stok_awal
  rugi <- 0
  
  for (hari in 2:hari_total) {
    penjualan <- penjualan_per_hari[hari - 1]
    
    if (stok[hari - 1] < penjualan) {
      rugi <- rugi + (penjualan - stok[hari - 1]) * 50000
      stok[hari] <- 0
    } else {
      stok[hari] <- stok[hari - 1] - penjualan
    }
    
    if (hari %% freq == 1) {
      stok[hari] <- stok[hari] + jumlah_pesan
    }
  }
  
  jumlah_kehabisan <- sum(stok == 0)
  return(list(stok = stok, rugi = rugi, habis = jumlah_kehabisan))
}

## Coba frekuensi pesan: 3, 5, 7
frekuensi <- c(3, 5, 7)
for (f in frekuensi) {
  hasil <- simulasi_frekuensi(f)
  cat("Frekuensi pesan tiap", f, "hari β†’ Hari habis stok:", hasil$habis,
      ", Total rugi: Rp", format(hasil$rugi, big.mark = ","), "\n")
}
## Frekuensi pesan tiap 3 hari β†’ Hari habis stok: 0 , Total rugi: Rp 0 
## Frekuensi pesan tiap 5 hari β†’ Hari habis stok: 0 , Total rugi: Rp 550,000 
## Frekuensi pesan tiap 7 hari β†’ Hari habis stok: 12 , Total rugi: Rp 8,800,000

Frekuensi pesan setiap 3 hari terbukti paling optimal karena tidak terjadi kehabisan stok sama sekali dan kerugian = Rp 0. Ini mencerminkan tingkat respon pengisian stok yang sangat cepat, sehingga stok selalu tersedia untuk memenuhi permintaan. Frekuensi pesan setiap 5 hari masih dapat diterima karena tidak terjadi kehabisan stok 0 hari, namun terjadi kerugian sebesar Rp 550.000, kemungkinan disebabkan oleh delay awal pengisian di hari ke-1 atau perbedaan waktu antara habisnya stok dan datangnya pesanan. Frekuensi pesan setiap 7 hari tidak direkomendasikan, karena menyebabkan kehabisan stok selama 12 hari, yang berdampak pada kerugian cukup besar Rp 8.800.000. Ini menunjukkan bahwa siklus pengisian terlalu jarang, sehingga stok tidak mampu menutupi fluktuasi permintaan harian.