Skip to content

Instantly share code, notes, and snippets.

@ha0ye
Last active August 31, 2021 21:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ha0ye/7cba5e0fc1dde39ef0116b15b05b432f to your computer and use it in GitHub Desktop.
Save ha0ye/7cba5e0fc1dde39ef0116b15b05b432f to your computer and use it in GitHub Desktop.
generate random sequences without consecutive repeats
f <- function(x)
{
n <- sum(x)
v <- numeric(n)
prev <- NULL
for (i in 1:n)
{
idx <- x > floor(sum(x)/2) # how many counts are > n/2
if (sum(idx) >= 2) # error if more than 2 (impossible?)
{
stop("multiple counts > floor(n/2); x = (", paste(x, collapse = ","), ")")
} else if (any(idx)) {
j <- which(idx)
if (!is.null(prev) && prev == j) # error if one count is > n/2, but was prev
{
stop("j == prev; prev = ", prev, ", x = (", paste(x, collapse = ","), ")")
} else { # if one count is > n/2, it must be chosen
v[i] <- j
x[j] <- x[j] - 1
}
} else {
p <- x # store counts
if (!is.null(prev)) { p[prev] <- 0 } # modify counts to not select prev
j <- sample(seq_along(x), size = 1, prob = p) # sample, weighted by counts
v[i] <- j
x[j] <- x[j] - 1
}
prev <- j # remember last selection
}
v
}
f(c(10, 10))
f(c(4, 4, 5))
f(c(1, 1, 1, 1, 4))
f(c(1, 1, 1, 1, 5))
f(c(1, 1, 1, 1, 6)) # should error out
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment