Solution

ID: past-exam-of-the-probability-statistics-and-options-i-course-of-the-university-of-oxford/2010/u/1/b/solution

Use inverse transform sampling for the categorical draw. Validate a finite nonnegative probability vector, allowing only a small rounding tolerance in its total, then compare a single uniform draw with the cumulative probabilities:
sim1 <- function(p) {
  if (!is.numeric(p) || length(p) == 0L ||
      any(!is.finite(p)) || any(p < 0) ||
      abs(sum(p) - 1) > 1e-12) {
    stop("p must be a nonempty finite probability vector")
  }
  p <- p / sum(p)
  cumulative <- cumsum(p)
  cumulative[length(p)] <- 1
  u <- runif(1)
  as.integer(which(u < cumulative)[1L])
}
The returned value is when falls in the interval between the previous cumulative sum and the th one. That interval has length , so the output has the required probabilities. Strict comparison skips zero-probability categories even if a simulated uniform value equals an interval boundary. Exactly one call to runif(1) is made.

New to topics? Read the docs here!