= Solution
{c}
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 $j$ when $u$ falls in the interval between the previous cumulative sum and the $j$th one. That interval has length $p_j$, 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.
Back to article page