I have a vector of characters 'A', 'B', 'C', 'D' and would like to loop n times to get all possible combinations (4^n) of the characters. How do I write a function that will perform this given input n?
For example, if n=2, my loop will look something like this:
string <- c('A','B','C','D')
combination = c()
count = 1
for (j in string) {
for (k in string) {
combination[count] <- paste0(j,k)
count = count 1
}
}
which will yield:
> combination
[1] "AA" "AB" "AC" "AD" "BA" "BB" "BC" "BD" "CA" "CB" "CC" "CD" "DA" "DB" "DC" "DD"
and if n=3, the code will be like this:
combination = c()
count = 1
for (j in string) {
for (k in string) {
for (l in string) {
combination[count] <- paste0(j,k,l)
count = count 1
}
}
}
which yields
> combination
[1] "AAA" "AAB" "AAC" "AAD" "ABA" "ABB" "ABC" "ABD" "ACA" "ACB" "ACC" "ACD" "ADA" "ADB" "ADC" "ADD" "BAA" "BAB" "BAC"
[20] "BAD" "BBA" "BBB" "BBC" "BBD" "BCA" "BCB" "BCC" "BCD" "BDA" "BDB" "BDC" "BDD" "CAA" "CAB" "CAC" "CAD" "CBA" "CBB"
[39] "CBC" "CBD" "CCA" "CCB" "CCC" "CCD" "CDA" "CDB" "CDC" "CDD" "DAA" "DAB" "DAC" "DAD" "DBA" "DBB" "DBC" "DBD" "DCA"
[58] "DCB" "DCC" "DCD" "DDA" "DDB" "DDC" "DDD"
CodePudding user response:
In a word, recursion:
#' n: length of each combination string
#' basis: the starting vector of characters to combine
#' extras: the vector of characters to be combined with basis. Defaults to basis
#' i: The current depth of recursion. Users should generally not need to access
#' this parameter.
combine <- function(n, basis=c('A','B','C','D'), extras=basis, i=1) {
x <- expand.grid(basis, extras)
y <- paste0(x$Var1, x$Var2)
if (i == n-1) {
return(y)
} else {
return(combine(n, y, extras, i 1))
}
}
Giving, for example,
> combine(2)
[1] "AA" "BA" "CA" "DA" "AB" "BB" "CB" "DB" "AC" "BC" "CC" "DC" "AD" "BD" "CD" "DD"
and
> combine(3)
[1] "AAA" "BAA" "CAA" "DAA" "ABA" "BBA" "CBA" "DBA" "ACA" "BCA" "CCA" "DCA" "ADA" "BDA" "CDA" "DDA" "AAB" "BAB" "CAB" "DAB" "ABB" "BBB" "CBB" "DBB" "ACB" "BCB" "CCB"
[28] "DCB" "ADB" "BDB" "CDB" "DDB" "AAC" "BAC" "CAC" "DAC" "ABC" "BBC" "CBC" "DBC" "ACC" "BCC" "CCC" "DCC" "ADC" "BDC" "CDC" "DDC" "AAD" "BAD" "CAD" "DAD" "ABD" "BBD"
[55] "CBD" "DBD" "ACD" "BCD" "CCD" "DCD" "ADD" "BDD" "CDD" "DDD"
etc.
Feel free to sort the output if another order is more desirable.