Каждое упорядоченное спаривание n элементов (где n равномерно) эквивалентно случайной перестановке (1:n) %% (n/2)
. Кроме того, поскольку порядок пар не имеет значения, перестановки, равные значению, фактически эквивалентны. Например, c(1,1,0,0)
эквивалентно c(0,0,1,1)
- оба из них соединяют первые два элемента вместе и последние два элемента вместе. Таким образом, мы можем получить уникальный набор дополнив каждую перестановку, а затем повторно маркируя элементы каждой перестановки в том порядке, что они появляются, а затем принимать только уникальные одни из результата:
library(magrittr)
library(combinat)
all_pairings <- function(n) {
if (n %% 2 != 0)
stop("n must be even")
allperms <- permn((1:n) %% (n/2))
allperms %<>% lapply(. %>% factor(levels=unique(.)) %>% as.numeric)
unique(allperms)
}
Это дает нам правильный результат при п = 4:
> all_pairings(4)
[[1]]
[1] 1 2 1 2
[[2]]
[1] 1 2 2 1
[[3]]
[1] 1 1 2 2
Чтобы действительно получить пар, использовать split
функцию:
> lapply(all_pairings(4), split, x=letters[1:n])
[[1]]
[[1]]$`1`
[1] "a" "c"
[[1]]$`2`
[1] "b" "d"
[[2]]
[[2]]$`1`
[1] "a" "d"
[[2]]$`2`
[1] "b" "c"
[[3]]
[[3]]$`1`
[1] "a" "b"
[[3]]$`2`
[1] "c" "d"
Если вам нужно только количество уникальных спариваний и не полный список из них, есть явная формула: http://www.regentsprep.org/regents/math/algebra/apr2/LpermRep.htm
В этом случае формула для уникальных парных элементов из N элементов будет равна factorial(n)/2^(n/2)/factorial(n/2)
. Первый член представляет собой все перестановки, второй термин представляет избыточность из-за эквивалентных переупорядочений внутри пары, а третий член представляет избыточность из-за переупорядочения пар.
num_pairings <- function(n) {
if (any(n %% 2 != 0))
stop("n must be even")
factorial(n)/(2^(n/2))/factorial(n/2)
}
> n <- seq(2,20, by=2); data.frame(n=n, NumPairings=num_pairings(n))
data.frame with 10 rows and 2 columns
n NumPairings
<numeric> <numeric>
1 2 1
2 4 3
3 6 15
4 8 105
5 10 945
6 12 10395
7 14 135135
8 16 2027025
9 18 34459425
10 20 654729075
Для вашего конкретного примера вы можете сделать что-то вроде 'res <- combn (x, 2, simplify = FALSE); indx <- select (length (x), 2); Map (c, res [1: (indx/2)], res [indx: (indx/2 + 1)]) ', хотя я не уверен, как вы хотите обобщить это для более длинных векторов. Например, для 'x <- 1: 5' попарные комбинации не смогут заполнить полный вектор из 5 значений каждый раз. –
Во всяком случае, единственная функциональность, которая имеет для меня смысл, - это что-то вроде' vecfunc <- function (x) { L <- длина (x); indx <- выберите (L, L/2); res <- combn (x, L/2, simplify = FALSE); Карта (c, res [1: (indx/2)], res [indx: (indx/2 + 1)]) } ', которая будет принимать только четные векторы длины. Тогда вы даже можете сделать 'x <-1: 8; vecfunc (x) ' –
Я совершенно смущен относительно того, как 3 набора пар являются« всевозможными попаримыми сопоставлениями »с учетом вашего примера' x' – thelatemail