在 R 中将向量分成两组的所有组合
All combinations to split a vector into two groups in R
我正在尝试找出一种有效的方法来获得所有唯一组合,向量中的元素(向量始终是 1:n 之间的序列)可以分成两个大小相等的组。向量中的每个元素都必须表示一次(在两个组之一中)。例如,当 n = 6 时,向量将为 [1,2,3,4,5,6]。这可以分为十种独特的方式来形成两个大小相等的组:
123 | 456
124 | 356
125 | 346
126 | 345
134 | 256
135 | 246
136 | 245
145 | 236
146 | 235
156 | 234
请注意,值 在 组中的顺序无关紧要,因此:
156 | 234
等同于:
651 | 342
另请注意,对称解决方案也无关紧要,因此:
156 | 234
等同于:
234 | 156
当n=4时,有3个解。当 n = 6 时,有 10 个解。当 n = 8 时,有 35 个解。我相信我想出了一种在 R 中获得这些解决方案的方法。但是,一旦 n 变大,它就会有点慢。在大多数情况下,我对我所拥有的感到满意,但想问问是否有人对提高速度或代码质量等的方法有建议。特别是,我从一个有很多重复的解决方案开始,然后我删除重复。我认为,这会使算法变得相当慢。
library(combinat)
# Number of elements in array
n = 6
# Array
dat <- 1:n
# All possible permutations for array
ans <- permn(dat)
lengthAns <- length(ans)
ansDF <- data.frame()
# Place first permutation in final answer data frame
ansDF <- rbind(ansDF, ans[[1]])
# Look at the rest of the possible permutations. Determine for each one if it is truly unique from all the previously-listed possible permutations. If it is unique from them, then add it to the final answer data frame
for (i in 2:lengthAns){
j = i
k = TRUE
while (k && j > 1){
j = j-1
if(setequal(ans[[i]][1:(n/2)], ans[[j]][1:(n/2)]))
k = FALSE
if(setequal(ans[[i]][1:(n/2)], ans[[j]][(n/2+1):(n)]))
k = FALSE
}
if (k){
ansDF <- rbind(ansDF, ans[[i]])
}
}
# At this point, ansDF contains all unique possible ways to split the array into two-equally sized groups.
N = 6
x = 1:N
x1 = combn(x, N/2) #how many ways can we take half the elements to form the 1st group
NC = NCOL(x1)
x2 = x1[, NC:1] # simplified way to generate the complementary groups that include values not in x1
grp1 = t(x1[,1:(NC/2)]) # We only need half of the rows, the 2nd half containing the same set in reverse order
grp2 = t(x2[,1:(NC/2)])
all.comb = cbind(grp1, grp2)
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 1 2 3 4 5 6
# [2,] 1 2 4 3 5 6
# [3,] 1 2 5 3 4 6
# [4,] 1 2 6 3 4 5
# [5,] 1 3 4 2 5 6
# [6,] 1 3 5 2 4 6
# [7,] 1 3 6 2 4 5
# [8,] 1 4 5 2 3 6
# [9,] 1 4 6 2 3 5
#[10,] 1 5 6 2 3 4
我正在尝试找出一种有效的方法来获得所有唯一组合,向量中的元素(向量始终是 1:n 之间的序列)可以分成两个大小相等的组。向量中的每个元素都必须表示一次(在两个组之一中)。例如,当 n = 6 时,向量将为 [1,2,3,4,5,6]。这可以分为十种独特的方式来形成两个大小相等的组:
123 | 456
124 | 356
125 | 346
126 | 345
134 | 256
135 | 246
136 | 245
145 | 236
146 | 235
156 | 234
请注意,值 在 组中的顺序无关紧要,因此:
156 | 234
等同于:
651 | 342
另请注意,对称解决方案也无关紧要,因此:
156 | 234
等同于:
234 | 156
当n=4时,有3个解。当 n = 6 时,有 10 个解。当 n = 8 时,有 35 个解。我相信我想出了一种在 R 中获得这些解决方案的方法。但是,一旦 n 变大,它就会有点慢。在大多数情况下,我对我所拥有的感到满意,但想问问是否有人对提高速度或代码质量等的方法有建议。特别是,我从一个有很多重复的解决方案开始,然后我删除重复。我认为,这会使算法变得相当慢。
library(combinat)
# Number of elements in array
n = 6
# Array
dat <- 1:n
# All possible permutations for array
ans <- permn(dat)
lengthAns <- length(ans)
ansDF <- data.frame()
# Place first permutation in final answer data frame
ansDF <- rbind(ansDF, ans[[1]])
# Look at the rest of the possible permutations. Determine for each one if it is truly unique from all the previously-listed possible permutations. If it is unique from them, then add it to the final answer data frame
for (i in 2:lengthAns){
j = i
k = TRUE
while (k && j > 1){
j = j-1
if(setequal(ans[[i]][1:(n/2)], ans[[j]][1:(n/2)]))
k = FALSE
if(setequal(ans[[i]][1:(n/2)], ans[[j]][(n/2+1):(n)]))
k = FALSE
}
if (k){
ansDF <- rbind(ansDF, ans[[i]])
}
}
# At this point, ansDF contains all unique possible ways to split the array into two-equally sized groups.
N = 6
x = 1:N
x1 = combn(x, N/2) #how many ways can we take half the elements to form the 1st group
NC = NCOL(x1)
x2 = x1[, NC:1] # simplified way to generate the complementary groups that include values not in x1
grp1 = t(x1[,1:(NC/2)]) # We only need half of the rows, the 2nd half containing the same set in reverse order
grp2 = t(x2[,1:(NC/2)])
all.comb = cbind(grp1, grp2)
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 1 2 3 4 5 6
# [2,] 1 2 4 3 5 6
# [3,] 1 2 5 3 4 6
# [4,] 1 2 6 3 4 5
# [5,] 1 3 4 2 5 6
# [6,] 1 3 5 2 4 6
# [7,] 1 3 6 2 4 5
# [8,] 1 4 5 2 3 6
# [9,] 1 4 6 2 3 5
#[10,] 1 5 6 2 3 4