As mentioned in one of the answers by @ThomasIsCoding, it would become TERRIBLY slow when we have higher order of n
or many terms in ...
(due to expand.grid
and apply
).
As always (due to my preference, I think it would be super fun if we don't load any external packages to make it), if you want to stay with base R but boost the performance significantly, I think the following base R function might help a lot.
Basic Idea
Assuming what we would like to expand is in the format (x1 + x2 + x3 + ... + xm)^n
, where m
is any positive integer, and n
is a positive integer as the exponent, we can:
Create a helper
function to produces all possible exponent combinations of (k1, k2, ..., km)
for terms x1^k1 * x2^k2 * ... * xm^km
, where the helper
function can be defined in a recursion way.
On top of obtained tuple (k1, k2, ..., km)
, we should generate the corresponding multinomial coefficients, i.e., n!/(k1! * k2! * ... * km!)
, and then multiply them with the term x1^k1 * x2^k2 * ... * xm^km
Code
f <- function(m, n = m) {
helper <- function(m, n) {
if (m == 1) {
return(n)
}
unlist(
lapply(
0:n,
\(i) Map(c, i, helper(m - 1, max(n - i, 0)))
),
recursive = FALSE
)
}
sapply(
helper(m, n),
\(x) {
term <- gsub(
"\\^1((?=\\D)|$)",
"",
paste0(
paste0("x", seq_along(x), "^", x)[x > 0],
collapse = "*"
),
perl = TRUE
)
coeff <- factorial(n) / prod(factorial(x))
ifelse(coeff == 1, term, paste0(coeff, "*", term))
}
)
}
Output Examples
> f(2)
[1] "x2^2" "2*x1*x2" "x1^2"
> f(3, 2)
[1] "x3^2" "2*x2*x3" "x2^2" "2*x1*x3" "2*x1*x2" "x1^2"
> f(2, 4)
[1] "x2^4" "4*x1*x2^3" "6*x1^2*x2^2" "4*x1^3*x2" "x1^4"
> f(4, 2)
[1] "x4^2" "2*x3*x4" "x3^2" "2*x2*x4" "2*x2*x3" "x2^2" "2*x1*x4"
[8] "2*x1*x3" "2*x1*x2" "x1^2"
and a crazy one
> f(7, 5)
[1] "x7^5" "5*x6*x7^4" "10*x6^2*x7^3"
[4] "10*x6^3*x7^2" "5*x6^4*x7" "x6^5"
[7] "5*x5*x7^4" "20*x5*x6*x7^3" "30*x5*x6^2*x7^2"
[10] "20*x5*x6^3*x7" "5*x5*x6^4" "10*x5^2*x7^3"
[13] "30*x5^2*x6*x7^2" "30*x5^2*x6^2*x7" "10*x5^2*x6^3"
[16] "10*x5^3*x7^2" "20*x5^3*x6*x7" "10*x5^3*x6^2"
[19] "5*x5^4*x7" "5*x5^4*x6" "x5^5"
[22] "5*x4*x7^4" "20*x4*x6*x7^3" "30*x4*x6^2*x7^2"
[25] "20*x4*x6^3*x7" "5*x4*x6^4" "20*x4*x5*x7^3"
[28] "60*x4*x5*x6*x7^2" "60*x4*x5*x6^2*x7" "20*x4*x5*x6^3"
[31] "30*x4*x5^2*x7^2" "60*x4*x5^2*x6*x7" "30*x4*x5^2*x6^2"
[34] "20*x4*x5^3*x7" "20*x4*x5^3*x6" "5*x4*x5^4"
[37] "10*x4^2*x7^3" "30*x4^2*x6*x7^2" "30*x4^2*x6^2*x7"
[40] "10*x4^2*x6^3" "30*x4^2*x5*x7^2" "60*x4^2*x5*x6*x7"
[43] "30*x4^2*x5*x6^2" "30*x4^2*x5^2*x7" "30*x4^2*x5^2*x6"
[46] "10*x4^2*x5^3" "10*x4^3*x7^2" "20*x4^3*x6*x7"
[49] "10*x4^3*x6^2" "20*x4^3*x5*x7" "20*x4^3*x5*x6"
[52] "10*x4^3*x5^2" "5*x4^4*x7" "5*x4^4*x6"
[55] "5*x4^4*x5" "x4^5" "5*x3*x7^4"
[58] "20*x3*x6*x7^3" "30*x3*x6^2*x7^2" "20*x3*x6^3*x7"
[61] "5*x3*x6^4" "20*x3*x5*x7^3" "60*x3*x5*x6*x7^2"
[64] "60*x3*x5*x6^2*x7" "20*x3*x5*x6^3" "30*x3*x5^2*x7^2"
[67] "60*x3*x5^2*x6*x7" "30*x3*x5^2*x6^2" "20*x3*x5^3*x7"
[70] "20*x3*x5^3*x6" "5*x3*x5^4" "20*x3*x4*x7^3"
[73] "60*x3*x4*x6*x7^2" "60*x3*x4*x6^2*x7" "20*x3*x4*x6^3"
[76] "60*x3*x4*x5*x7^2" "120*x3*x4*x5*x6*x7" "60*x3*x4*x5*x6^2"
[79] "60*x3*x4*x5^2*x7" "60*x3*x4*x5^2*x6" "20*x3*x4*x5^3"
[82] "30*x3*x4^2*x7^2" "60*x3*x4^2*x6*x7" "30*x3*x4^2*x6^2"
[85] "60*x3*x4^2*x5*x7" "60*x3*x4^2*x5*x6" "30*x3*x4^2*x5^2"
[88] "20*x3*x4^3*x7" "20*x3*x4^3*x6" "20*x3*x4^3*x5"
[91] "5*x3*x4^4" "10*x3^2*x7^3" "30*x3^2*x6*x7^2"
[94] "30*x3^2*x6^2*x7" "10*x3^2*x6^3" "30*x3^2*x5*x7^2"
[97] "60*x3^2*x5*x6*x7" "30*x3^2*x5*x6^2" "30*x3^2*x5^2*x7"
[100] "30*x3^2*x5^2*x6" "10*x3^2*x5^3" "30*x3^2*x4*x7^2"
[103] "60*x3^2*x4*x6*x7" "30*x3^2*x4*x6^2" "60*x3^2*x4*x5*x7"
[106] "60*x3^2*x4*x5*x6" "30*x3^2*x4*x5^2" "30*x3^2*x4^2*x7"
[109] "30*x3^2*x4^2*x6" "30*x3^2*x4^2*x5" "10*x3^2*x4^3"
[112] "10*x3^3*x7^2" "20*x3^3*x6*x7" "10*x3^3*x6^2"
[115] "20*x3^3*x5*x7" "20*x3^3*x5*x6" "10*x3^3*x5^2"
[118] "20*x3^3*x4*x7" "20*x3^3*x4*x6" "20*x3^3*x4*x5"
[121] "10*x3^3*x4^2" "5*x3^4*x7" "5*x3^4*x6"
[124] "5*x3^4*x5" "5*x3^4*x4" "x3^5"
[127] "5*x2*x7^4" "20*x2*x6*x7^3" "30*x2*x6^2*x7^2"
[130] "20*x2*x6^3*x7" "5*x2*x6^4" "20*x2*x5*x7^3"
[133] "60*x2*x5*x6*x7^2" "60*x2*x5*x6^2*x7" "20*x2*x5*x6^3"
[136] "30*x2*x5^2*x7^2" "60*x2*x5^2*x6*x7" "30*x2*x5^2*x6^2"
[139] "20*x2*x5^3*x7" "20*x2*x5^3*x6" "5*x2*x5^4"
[142] "20*x2*x4*x7^3" "60*x2*x4*x6*x7^2" "60*x2*x4*x6^2*x7"
[145] "20*x2*x4*x6^3" "60*x2*x4*x5*x7^2" "120*x2*x4*x5*x6*x7"
[148] "60*x2*x4*x5*x6^2" "60*x2*x4*x5^2*x7" "60*x2*x4*x5^2*x6"
[151] "20*x2*x4*x5^3" "30*x2*x4^2*x7^2" "60*x2*x4^2*x6*x7"
[154] "30*x2*x4^2*x6^2" "60*x2*x4^2*x5*x7" "60*x2*x4^2*x5*x6"
[157] "30*x2*x4^2*x5^2" "20*x2*x4^3*x7" "20*x2*x4^3*x6"
[160] "20*x2*x4^3*x5" "5*x2*x4^4" "20*x2*x3*x7^3"
[163] "60*x2*x3*x6*x7^2" "60*x2*x3*x6^2*x7" "20*x2*x3*x6^3"
[166] "60*x2*x3*x5*x7^2" "120*x2*x3*x5*x6*x7" "60*x2*x3*x5*x6^2"
[169] "60*x2*x3*x5^2*x7" "60*x2*x3*x5^2*x6" "20*x2*x3*x5^3"
[172] "60*x2*x3*x4*x7^2" "120*x2*x3*x4*x6*x7" "60*x2*x3*x4*x6^2"
[175] "120*x2*x3*x4*x5*x7" "120*x2*x3*x4*x5*x6" "60*x2*x3*x4*x5^2"
[178] "60*x2*x3*x4^2*x7" "60*x2*x3*x4^2*x6" "60*x2*x3*x4^2*x5"
[181] "20*x2*x3*x4^3" "30*x2*x3^2*x7^2" "60*x2*x3^2*x6*x7"
[184] "30*x2*x3^2*x6^2" "60*x2*x3^2*x5*x7" "60*x2*x3^2*x5*x6"
[187] "30*x2*x3^2*x5^2" "60*x2*x3^2*x4*x7" "60*x2*x3^2*x4*x6"
[190] "60*x2*x3^2*x4*x5" "30*x2*x3^2*x4^2" "20*x2*x3^3*x7"
[193] "20*x2*x3^3*x6" "20*x2*x3^3*x5" "20*x2*x3^3*x4"
[196] "5*x2*x3^4" "10*x2^2*x7^3" "30*x2^2*x6*x7^2"
[199] "30*x2^2*x6^2*x7" "10*x2^2*x6^3" "30*x2^2*x5*x7^2"
[202] "60*x2^2*x5*x6*x7" "30*x2^2*x5*x6^2" "30*x2^2*x5^2*x7"
[205] "30*x2^2*x5^2*x6" "10*x2^2*x5^3" "30*x2^2*x4*x7^2"
[208] "60*x2^2*x4*x6*x7" "30*x2^2*x4*x6^2" "60*x2^2*x4*x5*x7"
[211] "60*x2^2*x4*x5*x6" "30*x2^2*x4*x5^2" "30*x2^2*x4^2*x7"
[214] "30*x2^2*x4^2*x6" "30*x2^2*x4^2*x5" "10*x2^2*x4^3"
[217] "30*x2^2*x3*x7^2" "60*x2^2*x3*x6*x7" "30*x2^2*x3*x6^2"
[220] "60*x2^2*x3*x5*x7" "60*x2^2*x3*x5*x6" "30*x2^2*x3*x5^2"
[223] "60*x2^2*x3*x4*x7" "60*x2^2*x3*x4*x6" "60*x2^2*x3*x4*x5"
[226] "30*x2^2*x3*x4^2" "30*x2^2*x3^2*x7" "30*x2^2*x3^2*x6"
[229] "30*x2^2*x3^2*x5" "30*x2^2*x3^2*x4" "10*x2^2*x3^3"
[232] "10*x2^3*x7^2" "20*x2^3*x6*x7" "10*x2^3*x6^2"
[235] "20*x2^3*x5*x7" "20*x2^3*x5*x6" "10*x2^3*x5^2"
[238] "20*x2^3*x4*x7" "20*x2^3*x4*x6" "20*x2^3*x4*x5"
[241] "10*x2^3*x4^2" "20*x2^3*x3*x7" "20*x2^3*x3*x6"
[244] "20*x2^3*x3*x5" "20*x2^3*x3*x4" "10*x2^3*x3^2"
[247] "5*x2^4*x7" "5*x2^4*x6" "5*x2^4*x5"
[250] "5*x2^4*x4" "5*x2^4*x3" "x2^5"
[253] "5*x1*x7^4" "20*x1*x6*x7^3" "30*x1*x6^2*x7^2"
[256] "20*x1*x6^3*x7" "5*x1*x6^4" "20*x1*x5*x7^3"
[259] "60*x1*x5*x6*x7^2" "60*x1*x5*x6^2*x7" "20*x1*x5*x6^3"
[262] "30*x1*x5^2*x7^2" "60*x1*x5^2*x6*x7" "30*x1*x5^2*x6^2"
[265] "20*x1*x5^3*x7" "20*x1*x5^3*x6" "5*x1*x5^4"
[268] "20*x1*x4*x7^3" "60*x1*x4*x6*x7^2" "60*x1*x4*x6^2*x7"
[271] "20*x1*x4*x6^3" "60*x1*x4*x5*x7^2" "120*x1*x4*x5*x6*x7"
[274] "60*x1*x4*x5*x6^2" "60*x1*x4*x5^2*x7" "60*x1*x4*x5^2*x6"
[277] "20*x1*x4*x5^3" "30*x1*x4^2*x7^2" "60*x1*x4^2*x6*x7"
[280] "30*x1*x4^2*x6^2" "60*x1*x4^2*x5*x7" "60*x1*x4^2*x5*x6"
[283] "30*x1*x4^2*x5^2" "20*x1*x4^3*x7" "20*x1*x4^3*x6"
[286] "20*x1*x4^3*x5" "5*x1*x4^4" "20*x1*x3*x7^3"
[289] "60*x1*x3*x6*x7^2" "60*x1*x3*x6^2*x7" "20*x1*x3*x6^3"
[292] "60*x1*x3*x5*x7^2" "120*x1*x3*x5*x6*x7" "60*x1*x3*x5*x6^2"
[295] "60*x1*x3*x5^2*x7" "60*x1*x3*x5^2*x6" "20*x1*x3*x5^3"
[298] "60*x1*x3*x4*x7^2" "120*x1*x3*x4*x6*x7" "60*x1*x3*x4*x6^2"
[301] "120*x1*x3*x4*x5*x7" "120*x1*x3*x4*x5*x6" "60*x1*x3*x4*x5^2"
[304] "60*x1*x3*x4^2*x7" "60*x1*x3*x4^2*x6" "60*x1*x3*x4^2*x5"
[307] "20*x1*x3*x4^3" "30*x1*x3^2*x7^2" "60*x1*x3^2*x6*x7"
[310] "30*x1*x3^2*x6^2" "60*x1*x3^2*x5*x7" "60*x1*x3^2*x5*x6"
[313] "30*x1*x3^2*x5^2" "60*x1*x3^2*x4*x7" "60*x1*x3^2*x4*x6"
[316] "60*x1*x3^2*x4*x5" "30*x1*x3^2*x4^2" "20*x1*x3^3*x7"
[319] "20*x1*x3^3*x6" "20*x1*x3^3*x5" "20*x1*x3^3*x4"
[322] "5*x1*x3^4" "20*x1*x2*x7^3" "60*x1*x2*x6*x7^2"
[325] "60*x1*x2*x6^2*x7" "20*x1*x2*x6^3" "60*x1*x2*x5*x7^2"
[328] "120*x1*x2*x5*x6*x7" "60*x1*x2*x5*x6^2" "60*x1*x2*x5^2*x7"
[331] "60*x1*x2*x5^2*x6" "20*x1*x2*x5^3" "60*x1*x2*x4*x7^2"
[334] "120*x1*x2*x4*x6*x7" "60*x1*x2*x4*x6^2" "120*x1*x2*x4*x5*x7"
[337] "120*x1*x2*x4*x5*x6" "60*x1*x2*x4*x5^2" "60*x1*x2*x4^2*x7"
[340] "60*x1*x2*x4^2*x6" "60*x1*x2*x4^2*x5" "20*x1*x2*x4^3"
[343] "60*x1*x2*x3*x7^2" "120*x1*x2*x3*x6*x7" "60*x1*x2*x3*x6^2"
[346] "120*x1*x2*x3*x5*x7" "120*x1*x2*x3*x5*x6" "60*x1*x2*x3*x5^2"
[349] "120*x1*x2*x3*x4*x7" "120*x1*x2*x3*x4*x6" "120*x1*x2*x3*x4*x5"
[352] "60*x1*x2*x3*x4^2" "60*x1*x2*x3^2*x7" "60*x1*x2*x3^2*x6"
[355] "60*x1*x2*x3^2*x5" "60*x1*x2*x3^2*x4" "20*x1*x2*x3^3"
[358] "30*x1*x2^2*x7^2" "60*x1*x2^2*x6*x7" "30*x1*x2^2*x6^2"
[361] "60*x1*x2^2*x5*x7" "60*x1*x2^2*x5*x6" "30*x1*x2^2*x5^2"
[364] "60*x1*x2^2*x4*x7" "60*x1*x2^2*x4*x6" "60*x1*x2^2*x4*x5"
[367] "30*x1*x2^2*x4^2" "60*x1*x2^2*x3*x7" "60*x1*x2^2*x3*x6"
[370] "60*x1*x2^2*x3*x5" "60*x1*x2^2*x3*x4" "30*x1*x2^2*x3^2"
[373] "20*x1*x2^3*x7" "20*x1*x2^3*x6" "20*x1*x2^3*x5"
[376] "20*x1*x2^3*x4" "20*x1*x2^3*x3" "5*x1*x2^4"
[379] "10*x1^2*x7^3" "30*x1^2*x6*x7^2" "30*x1^2*x6^2*x7"
[382] "10*x1^2*x6^3" "30*x1^2*x5*x7^2" "60*x1^2*x5*x6*x7"
[385] "30*x1^2*x5*x6^2" "30*x1^2*x5^2*x7" "30*x1^2*x5^2*x6"
[388] "10*x1^2*x5^3" "30*x1^2*x4*x7^2" "60*x1^2*x4*x6*x7"
[391] "30*x1^2*x4*x6^2" "60*x1^2*x4*x5*x7" "60*x1^2*x4*x5*x6"
[394] "30*x1^2*x4*x5^2" "30*x1^2*x4^2*x7" "30*x1^2*x4^2*x6"
[397] "30*x1^2*x4^2*x5" "10*x1^2*x4^3" "30*x1^2*x3*x7^2"
[400] "60*x1^2*x3*x6*x7" "30*x1^2*x3*x6^2" "60*x1^2*x3*x5*x7"
[403] "60*x1^2*x3*x5*x6" "30*x1^2*x3*x5^2" "60*x1^2*x3*x4*x7"
[406] "60*x1^2*x3*x4*x6" "60*x1^2*x3*x4*x5" "30*x1^2*x3*x4^2"
[409] "30*x1^2*x3^2*x7" "30*x1^2*x3^2*x6" "30*x1^2*x3^2*x5"
[412] "30*x1^2*x3^2*x4" "10*x1^2*x3^3" "30*x1^2*x2*x7^2"
[415] "60*x1^2*x2*x6*x7" "30*x1^2*x2*x6^2" "60*x1^2*x2*x5*x7"
[418] "60*x1^2*x2*x5*x6" "30*x1^2*x2*x5^2" "60*x1^2*x2*x4*x7"
[421] "60*x1^2*x2*x4*x6" "60*x1^2*x2*x4*x5" "30*x1^2*x2*x4^2"
[424] "60*x1^2*x2*x3*x7" "60*x1^2*x2*x3*x6" "60*x1^2*x2*x3*x5"
[427] "60*x1^2*x2*x3*x4" "30*x1^2*x2*x3^2" "30*x1^2*x2^2*x7"
[430] "30*x1^2*x2^2*x6" "30*x1^2*x2^2*x5" "30*x1^2*x2^2*x4"
[433] "30*x1^2*x2^2*x3" "10*x1^2*x2^3" "10*x1^3*x7^2"
[436] "20*x1^3*x6*x7" "10*x1^3*x6^2" "20*x1^3*x5*x7"
[439] "20*x1^3*x5*x6" "10*x1^3*x5^2" "20*x1^3*x4*x7"
[442] "20*x1^3*x4*x6" "20*x1^3*x4*x5" "10*x1^3*x4^2"
[445] "20*x1^3*x3*x7" "20*x1^3*x3*x6" "20*x1^3*x3*x5"
[448] "20*x1^3*x3*x4" "10*x1^3*x3^2" "20*x1^3*x2*x7"
[451] "20*x1^3*x2*x6" "20*x1^3*x2*x5" "20*x1^3*x2*x4"
[454] "20*x1^3*x2*x3" "10*x1^3*x2^2" "5*x1^4*x7"
[457] "5*x1^4*x6" "5*x1^4*x5" "5*x1^4*x4"
[460] "5*x1^4*x3" "5*x1^4*x2" "x1^5"