I want to be able to generate a (pseudo)random binary sequence (for example, a sequence of Rs and Ls like RLLRRLR) which is counterbalanced such that the same item does not occur more than twice in a row in the sequence and if I, for example, have a sequence of 20, I get 10 of each. Is there a function in R that can do something like this?
I tried to write a function like this myself. Here is the attempt:
RL_seq <- function(n_L = 10, n_R = 10, max_consec = 2, initial_seq = NULL) {
while(n_L > 0 | n_R > 0){
side <- sample(c("R", "L"), 1)
if (side == "R" & n_R > 0 & length(grep("R", tail(initial_seq, max_consec))) != max_consec) {
initial_seq <- append(initial_seq, side)
n_R <- n_R - 1
} else if (side == "L" & n_L > 0 & length(grep("L", tail(initial_seq, max_consec))) != max_consec) {
initial_seq <- append(initial_seq, side)
n_L <- n_L - 1
}
}
print(initial_seq)
}
# The function does not stop with the following seed
set.seed(1)
RL_seq()
However, it's up to chance whether the code gets stuck or not. I was also hoping that I could change the rules for the sequence (for example, allowing for 3 consecutive Rs), but the code tends to breaks if I touch the arguments. At this point I would be happy if I could run it with the default arguments and not have it get stuck.
I have searched around but I cannot find an answer.
Here, I first determine the mix of elements, then repeatedly shuffle until there's a draw without too many consecutive picks. I'm sure there's a more computationally efficient approach (e.g. where we don't overwrite
seqevery iteration), but this might suffice. For example, it takes ~0.002 sec formax_consec = 2, or a few seconds to find a draw with no repeats (max_consec = 1), even if that takes 100k+ draws to find.Any approach (like the two suggested so far) which relies on random draws will perform poorly for larger sequences, since it will become vanishingly unlikely to happen upon a sequence with few enough repeated strings by chance.