R 以6种不同的方式列出3个数字的组合?

R 以6种不同的方式列出3个数字的组合?,r,permutation,R,Permutation,从001到999的一系列数字中,我希望能够建立一个函数,其中从001到199,数字的组合将以多达6种不同的方式列出。例192为192、129、291、219、912、921。清单显然应该以001开头,它将显示为:001、010、100。我不确定您想要结果的格式 如前所述,这些是排列:combinat::permn可能是实现这一点最方便的方法 使用零填充(“%03d”)格式化数字,并将其拆分为字符(strsplit(,,“”)): 应用于每个整数 result <- lapply(0:999

从001到999的一系列数字中,我希望能够建立一个函数,其中从001到199,数字的组合将以多达6种不同的方式列出。例192为192、129、291、219、912、921。清单显然应该以001开头,它将显示为:001、010、100。

我不确定您想要结果的格式

如前所述,这些是排列:
combinat::permn
可能是实现这一点最方便的方法

使用零填充(
“%03d”
)格式化数字,并将其拆分为字符(
strsplit(,,“”)
):

应用于每个整数

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"

result您可以使用
tidyr::crossing
展开索引向量。网格

库(tidyverse)
指数%
过滤器(x!=y,x!=z,y!=z)%>%
pmap(~unname(c(…))
索引%>%str
#>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%
唯一的()
})
perms[500:510]]>%str(vec.len=6)
#>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次迭代,但矢量化方法的扩展性会更好。

这里有一个解决方案,它可以提供所需的输出,而无需重复,也无需额外调用来清除重复的结果。我们利用了
C++
中算法库中的
std::next_permutation
,它以向量作为输入,生成字典排列,直到达到第一个排列。这意味着,我们只为
001
生成3个排列,为
999
生成1个排列,为
123
生成6个排列

我们首先使用
gtools::compositions
生成长度为3的
as.character(0:9)
的所有组合,并进行重复

## install.packages("gtools")
myCombs <- gtools::combinations(10, 3, as.character(0:9), repeats.allowed = TRUE)

nrow(myCombs)
[1] 220
最后,我们将它与
lappy
一起带来:

permutedCombs <- lapply(1:nrow(myCombs), function(x) {
    permuteDigits(myCombs[x, ])
})
这里有证据证明我们有1000个结果,没有重复:

sum(lengths(permutedCombs))
[1] 1000

identical(sort(as.integer(do.call(c, permutedCombs))), 0:999)
[1] TRUE

你问的是排列。你可能想看看
## 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);
    }"
)
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