我希望能够构造一个从001到999的数字范围,其中从001到199的函数将以多达6种不同的方式列出数字的组合。示例192为192、129、291、219、912、921。列表显然应该以001开头,它将显示为:001、010、100。
答案 0 :(得分:1)
我不确定您想要哪种格式的结果。
如前所述,这些是排列:combinat::permn
可能是实现此目的的最方便的方法。
使用零填充("%03d"
)格式化数字,并分割成字符(strsplit(.,"")
):
f0 <- function(x) strsplit(sprintf("%03d",x),"")[[1]]
创建所有排列,将它们压回字符串(paste/collapse
),然后选择唯一值(例如000
仅具有一个唯一值)
f1 <- function(x) unique(sapply(combinat::permn(f0(x)),paste,collapse=""))
适用于每个整数
result <- lapply(0:999,f1)
head(result)
[[1]]
[1] "000"
[[2]]
[1] "001" "010" "100"
[[3]]
[1] "002" "020" "200"
[[4]]
[1] "003" "030" "300"
[[5]]
[1] "004" "040" "400"
[[6]]
[1] "005" "050" "500"
后来的值确实有多达六个条目。
答案 1 :(得分:1)
您可以使用tidyr::crossing
或expand.grid
来创建索引向量:
library(tidyverse)
indices <- crossing(x = 1:3, y = 1:3, z = 1:3) %>%
filter(x != y, x != z, y != z) %>%
pmap(~unname(c(...)))
indices %>% str
#> List of 6
#> $ : int [1:3] 1 2 3
#> $ : int [1:3] 1 3 2
#> $ : int [1:3] 2 1 3
#> $ : int [1:3] 2 3 1
#> $ : int [1:3] 3 1 2
#> $ : int [1:3] 3 2 1
...,然后在遍历所有输入向量时可以用来对它们进行子集化:
perms <- pmap(crossing(x = 0:9, y = 0:9, z = 0:9), function(...){
map_chr(indices, function(x) paste(c(...)[x], collapse = "")) %>%
unique()
})
perms[500:510] %>% str(vec.len = 6)
#> List of 11
#> $ : chr [1:3] "499" "949" "994"
#> $ : chr [1:3] "500" "050" "005"
#> $ : chr [1:6] "501" "510" "051" "015" "150" "105"
#> $ : chr [1:6] "502" "520" "052" "025" "250" "205"
#> $ : chr [1:6] "503" "530" "053" "035" "350" "305"
#> $ : chr [1:6] "504" "540" "054" "045" "450" "405"
#> $ : chr [1:3] "505" "550" "055"
#> $ : chr [1:6] "506" "560" "056" "065" "650" "605"
#> $ : chr [1:6] "507" "570" "057" "075" "750" "705"
#> $ : chr [1:6] "508" "580" "058" "085" "850" "805"
#> $ : chr [1:6] "509" "590" "059" "095" "950" "905"
这最终仍然是很多迭代,因此尽管它可以进行6000次迭代足够快,但矢量化方法会更好地扩展。
答案 2 :(得分:0)
这里是一种解决方案,可以在不重复的情况下提供所需的输出,并且无需其他调用即可清除重复的结果。我们利用std::next_permutation
中算法库中的C++
来利用001
,该算法库将向量作为输入并生成字典编排,直到达到第一个排列。这意味着,我们仅为999
生成3个排列,为123
生成1个排列,为as.character(0:9)
生成6个排列。
我们首先利用gtools::combinations
生成长度为3的## 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"
以下是一些示例输出:
sum(lengths(permutedCombs))
[1] 1000
identical(sort(as.integer(do.call(c, permutedCombs))), 0:999)
[1] TRUE
这证明我们有1000个结果,没有重复:
{{1}}