R:有效计算分区的排列

时间:2016-06-30 13:46:47

标签: r algorithm permutation partitioning

给出包含n个唯一元素的向量:

x <- c('a','b','c')

我想找到任意x n的所有分区的所有排列。对于n=3,这意味着13个订单:

('a', 'b', 'c')
('a') ('b','c')
('b','c') ('a')
('a','b') ('c')
('a','c') ('b')
('b') ('a','c')
('c') ('b','a')
('a') ('b') ('c')
('a') ('c') ('b')
('b') ('a') ('c')
('b') ('c') ('a')
('c') ('a') ('b')
('c') ('b') ('a')

可以使用listParts库中的partitions找到分区(setparts,但遗憾的是,它似乎与R的最新版本不兼容),以及{{1}的排列来自permn包:

combinat

但是,我很难找到一种有效的方法来置换分区并存储结果。我的目标是将结果映射到像

这样的结构
library(partitions)
library(combinat)
parts <- listParts(length(x))

p1 <- permn(parts[[1]])
p2 <- permn(parts[[2]])
...

其中整数表示排列中元素的顺序。由于分区在内部是无序的,因此分区中的任何元素都将接收相同的整数等级。似乎应该有一些方法通过引用分区的列表索引来有效地做到这一点,但我无法找到一种方法来做到这一点。

1 个答案:

答案 0 :(得分:0)

以下是简短的代码段,可以达到预期的效果:

x <- c('a','b','c')

## Probably not a good idea to name this parts as there
## is a function in the partitions package called parts
myParts <- partitions::listParts(length(x))

permParts <- unlist(lapply(seq_along(x), function(j) {
    tempParts <- myParts[lengths(myParts) == j]
    perms <- combinat::permn(j)

    unlist(lapply(tempParts, function(p) {
        lapply(perms, function(q) {
            t <- lapply(p[q], function(i) x[i])
            class(t) <- c("list", "equivalence")
            t
        })
    }), recursive = F)
}), recursive = F)

这是给定示例的输出:

permParts
[[1]]
[1] (a,b,c)

[[2]]
[1] (a,c)(b)

[[3]]
[1] (b)(a,c)

[[4]]
[1] (a,b)(c)

[[5]]
[1] (c)(a,b)

[[6]]
[1] (b,c)(a)

[[7]]
[1] (a)(b,c)

[[8]]
[1] (a)(b)(c)

[[9]]
[1] (a)(c)(b)

[[10]]
[1] (c)(a)(b)

[[11]]
[1] (c)(b)(a)

[[12]]
[1] (b)(c)(a)

[[13]]
[1] (b)(a)(c)

我不会说上述内容必然是最有效的解决方案,但是如果不滚动算法,我无法想到更有效的攻击方式。