Вот решение, которое дает желаемый результат без дублирования и без дополнительных вызовов для очистки дублированных результатов.Мы используем std::next_permutation
из библиотеки алгоритмов в C++
, которая принимает вектор в качестве входных данных и генерирует лексикографические перестановки, пока не будет достигнута первая перестановка.Это означает, что мы генерируем только 3 перестановки для 001
, 1 перестановку для 999
и 6 перестановок для 123
.
Мы начинаем с генерации всех комбинаций as.character(0:9)
длины 3 с повторением поиспользование gtools::combinations
.
## install.packages("gtools")
myCombs <- gtools::combinations(10, 3, as.character(0:9), repeats.allowed = TRUE)
nrow(myCombs)
[1] 220
Вот версия Rcpp
, которая предоставляет std::next_permutation
для R
:
## install.packages("Rcpp")
Rcpp::cppFunction(
"CharacterVector permuteDigits(CharacterVector v) {
std::string myStr;
std::vector<std::string> result;
for (std::size_t i = 0; i < v.size(); ++i)
myStr += v[i];
do {
result.push_back(myStr);
} while(std::next_permutation(myStr.begin(), myStr.end()));
return wrap(result);
}"
)
И, наконец, мы приводим ее вместе с lapply
:
permutedCombs <- lapply(1:nrow(myCombs), function(x) {
permuteDigits(myCombs[x, ])
})
Вот пример выходных данных:
permutedCombs[1:5]
[[1]]
[1] "000"
[[2]]
[1] "001" "010" "100"
[[3]]
[1] "002" "020" "200"
[[4]]
[1] "003" "030" "300"
[[5]]
[1] "004" "040" "400"
permutedCombs[151:155]
[[1]]
[1] "356" "365" "536" "563" "635" "653"
[[2]]
[1] "357" "375" "537" "573" "735" "753"
[[3]]
[1] "358" "385" "538" "583" "835" "853"
[[4]]
[1] "359" "395" "539" "593" "935" "953"
[[5]]
[1] "366" "636" "663"
И вот доказательство того, что у нас есть все 1000 результатов без дублирования:
sum(lengths(permutedCombs))
[1] 1000
identical(sort(as.integer(do.call(c, permutedCombs))), 0:999)
[1] TRUE