在R中将载体穷举地分成对的方法

时间:2017-11-10 00:00:43

标签: r recursion functional-programming combinatorics

(这是受到标记为duplicate的另一个问题的启发。我认为这是一个有趣的问题,尽管组合学可能有一个简单的解决方案,我对此非常无知。)

问题

对于长度为n的向量,其中n mod 2为零,找到所有可能的方法将向量的所有元素分成对,无需替换,顺序无关紧要。

例如,对于向量c(1,2,3,4)

list(c(1,2), c(3,4))
list(c(1,3), c(2,4))
list(c(1,4), c(2,3))

我的方法如下(对于新手代码提前道歉):

# write a function that recursively breaks down a list of unique pairs (generated with combn). The natural ordering produced by combn means that for the first pass through, we take as the starting pair, all pairings with element 1 of the vector with all other elements. After that has been allocated, we iterate through the first p/2 pairs (this avoids duplicating).

pairer2 <- function(kn, pair_list) {

  pair1_partners <- lapply(kn, function(x) {

    # remove any pairs in the 'master list' that contain elements of the starting pair.
    partners <- Filter(function(t) !any(t %in% x), pair_list)

    if(length(partners) > 1) {

    # run the function again
      pairer2(kn = partners[1:(length(partners)/2)], partners)
    } else {return(partners)}
  })

    # accumulate results into a nested list structure
  return(mapply(function(x,y) {list(root = x, partners = y)}, kn, pair1_partners, SIMPLIFY = F))
}

# this function generates all possible unique pairs for a vector of length k as the starting point, then runs the pairing off function above

pair_combn <- function(k, n = 2) {

  p <- combn(k, n, simplify = F)

  pairer2(kn = p[1:(length(k)-1)], p)}


# so far a vector k = 4
pair_combn(1:4)

[[1]]
[[1]]$root
[1] 1 2

[[1]]$partners
[[1]]$partners[[1]]
[1] 3 4



[[2]]
[[2]]$root
[1] 1 3

[[2]]$partners
[[2]]$partners[[1]]
[1] 2 4



[[3]]
[[3]]$root
[1] 1 4

[[3]]$partners
[[3]]$partners[[1]]
[1] 2 3

据我所知,它也适用于较大的k。这不是那么有效,可能是因为Filter对于大型列表来说很慢,我必须承认我不能将嵌套列表(可能的解决方案的树表示)折叠到每个分区的列表中。感觉应该有一个更优雅的解决方案(在R中)?

请注意,有趣的是,这种递归方法会产生一种简约(虽然不方便)的可能解决方案。

2 个答案:

答案 0 :(得分:1)

这是一种方式:

> x <- c(1,2,3,4)
> xc <- combn(as.data.frame(combn(x, 2)), 2, simplify = FALSE)
> Filter(function(x) all(1:4 %in% unlist(x)), xc)
[[1]]
  V1 V6
1  1  3
2  2  4

[[2]]
  V2 V5
1  1  2
2  3  4

[[3]]
  V3 V4
1  1  2
2  4  3

> 

更一般地说:

pair_combn <- function(x) {
    Filter(function(e) all(unique(x) %in% unlist(e)),
           combn(as.data.frame(combn(x, 2)),
                 length(x)/2, simplify = FALSE))
}

答案 1 :(得分:1)

感谢您继续我的问题(出于某种奇怪的原因标记为重复)。我认为没有解决方案适用于k&gt; = 10.对于k = 6,Gatsky的答案对我不起作用(当实际有15时,它会返回5种可能性)。 Ista的解决方案在k = 12时失败。