R - generates all combinations of 2 vectors of given constraints
I would like to generate all combinations of two vectors with two constraints: there can never be more than three characters from the first vector, and there must always be at least one character from the second vector. I would also like to change the final number of characters in the combination.
For example, here are two vectors:
vec1=c("A","B","C","D")
vec2=c("W","X","Y","Z")
Let's say I need 3 characters in combination. Possible permutations: "A" "B" "X"
or "A" "Y" "Z"
. An unacceptable permutation would be: "A" "B" "C"
because at least one character from vec2
.
Now tell me I need 5 characters in combination. Possible valid permutations are: "A" "C" "Z" "Y"
or "A" "Y" "Z" "X"
. An invalid permutation would be: "A" "C" "D" "B" "X"
since vec2
there are> 3 characters from.
I guess I could use expand.grid
to create all the combinations and then somehow subsets, but there should be an easier way. Thanks in advance!
source to share
I'm not sure if it's easier, but you can remove permutations that don't satisfy your conditions with this strategy:
-
create all combinations of
vec1
that are acceptable. -
create all combinations of
vec2
that are acceptable. -
generate all combinations that make one solution out of 1. + one solution out of 2. Here I will filter with condition 3. After that
-
(if you are looking for combinations, you're done, otherwise :) do all the permutations of the letters in each result.
Now let
vec1 <- LETTERS [1:4]
vec2 <- LETTERS [23:26]
## lists can eat up lots of memory, so use character vectors instead.
combine <- function (x, y)
combn (y, x, paste, collapse = "")
res1 <- unlist (lapply (0:3, combine, vec1))
res2 <- unlist (lapply (1:length (vec2), combine, vec2))
now we have:
> res1
[1] "" "A" "B" "C" "D" "AB" "AC" "AD" "BC" "BD" "CD" "ABC"
[13] "ABD" "ACD" "BCD"
> res2
[1] "W" "X" "Y" "Z" "WX" "WY" "WZ" "XY" "XZ" "YZ"
[11] "WXY" "WXZ" "WYZ" "XYZ" "WXYZ"
res3 <- outer (res1, res2, paste0)
res3 <- res3 [nchar (res3) == 5]
So here you are:
> res3
[1] "ABCWX" "ABDWX" "ACDWX" "BCDWX" "ABCWY" "ABDWY" "ACDWY" "BCDWY" "ABCWZ"
[10] "ABDWZ" "ACDWZ" "BCDWZ" "ABCXY" "ABDXY" "ACDXY" "BCDXY" "ABCXZ" "ABDXZ"
[19] "ACDXZ" "BCDXZ" "ABCYZ" "ABDYZ" "ACDYZ" "BCDYZ" "ABWXY" "ACWXY" "ADWXY"
[28] "BCWXY" "BDWXY" "CDWXY" "ABWXZ" "ACWXZ" "ADWXZ" "BCWXZ" "BDWXZ" "CDWXZ"
[37] "ABWYZ" "ACWYZ" "ADWYZ" "BCWYZ" "BDWYZ" "CDWYZ" "ABXYZ" "ACXYZ" "ADXYZ"
[46] "BCXYZ" "BDXYZ" "CDXYZ" "AWXYZ" "BWXYZ" "CWXYZ" "DWXYZ"
If you prefer the results to be broken down into individual letters:
res <- matrix (unlist (strsplit (res3, "")), nrow = length (res3), byrow = TRUE)
> res
[,1] [,2] [,3] [,4] [,5]
[1,] "A" "B" "C" "W" "X"
[2,] "A" "B" "D" "W" "X"
[3,] "A" "C" "D" "W" "X"
[4,] "B" "C" "D" "W" "X"
(snip)
[51,] "C" "W" "X" "Y" "Z"
[52,] "D" "W" "X" "Y" "Z"
What are your combinations.
source to share