Hi. The following code from stackoverflow enumerates all permutations of a vector x. Please explain why this works. What the rbind statement is doing? Thanks.
getPerms <- function(x) {
if (length(x) == 1) {
return(x)
}
else {
res <- matrix(nrow = 0, ncol = length(x))
for (i in seq_along(x)) {
res <- rbind(res, cbind(x[i], Recall(x[-i])))
}
return(res)
}
}
perm <- function(v) {
n <- length(v)
if (n == 1) v
else {
X <- NULL
for (i in 1:n) X <- rbind(X, cbind(v[i], perm(v[-i])))
X
}
}
perm(letters[1:3])
#> [,1] [,2] [,3]
#> [1,] "a" "b" "c"
#> [2,] "a" "c" "b"
#> [3,] "b" "a" "c"
#> [4,] "b" "c" "a"
#> [5,] "c" "a" "b"
#> [6,] "c" "b" "a"
Created on 2020-10-18 by the reprex package (v0.3.0.9001)
if traps for a single element vector
for (i in 1:n) X <- rbind(X, cbind(v[i], perm(v[-i])))
populates a matrix by iterating over the length of the vector and taking its element at each step and creating a row in X (initially NULL) with the value of that element and, the elegant part, recursively calling itself to create the columns with the remaining possibilities with the elements less that that which starts the row.
# use global X as an argument
X <- NULL
perm <- function(v,X=X) {
n <- length(v)
if (n == 1) v
else {
X <- NULL
for (i in 1:n) X <- rbind(X, cbind(v[i], perm(v[-i])))
X
}
}
perm(letters[1:3],X)
Because X is merely a placeholder object it can be initialized within either the global environment or the function; within the globql environment is an extra step. Generally, functions should return a value rather than manipulate a global object in situ/
Were you asking just to understand the code? If you're looking for an efficient way to generate permutations, you could use permn from the combinat package:
library(combinat)
v = letters[1:3]
# Returns a list
permn(v)
# If you want a matrix
do.call("rbind", permn(v))