Я хочу переставить вектор так, чтобы элемент не мог находиться в одном месте после перестановки, как это было в оригинале. Скажем, у меня есть список таких элементов: AABBCCADEF
Существенным перетасовкой будет: BBAADEFCCA
Но это было бы неверно: B A ACFEDCAB или BCA B FEDCAB
Самый близкий ответ, который я мог найти, это следующее: python shuffle, чтобы позиция никогда не повторялась. Но это не совсем то, что я хочу, потому что в этом примере нет повторяющихся элементов.
Я хочу быстрый алгоритм, который обобщает этот ответ в случае повторений.
MWE:
library(microbenchmark)
set.seed(1)
x <- sample(letters, size=295, replace=T)
terrible_implementation <- function(x) {
xnew <- sample(x)
while(any(x == xnew)) {
xnew <- sample(x)
}
return(xnew)
}
microbenchmark(terrible_implementation(x), times=10)
Unit: milliseconds
expr min lq mean median uq max neval
terrible_implementation(x) 479.5338 2346.002 4738.49 2993.29 4858.254 17005.05 10
Также, как определить, можно ли переставить последовательность таким образом?
РЕДАКТИРОВАТЬ: для того, чтобы сделать это совершенно ясно, что я хочу, новый вектор должен удовлетворять следующим условиям:
1) all(table(newx) == table(x))
2) all(x != newx)
например:.
newx <- terrible_implementation(x)
all(table(newx) == table(x))
[1] TRUE
all(x != newx)
[1] TRUE