Reputation: 73
I am stuck in a mathematical problem. I would like to make a function that outputs all the ways an integer "n" can be divide into "k" groups in such a way that in each group "k" is at least 1 (k >= 1).
The function could look something like:
n_ways <- function(n,k) {...}
I would like a dataFrame as an output. So for: n_ways(5,3)
A B C
1 3 1 1
2 1 3 1
3 1 1 3
4 2 2 1
5 2 1 2
6 1 2 2
The order in which the solutions are presented in the dataFrame is not important.
I looked for solutions like here and in other languages like here and here. Unfortunately I am not that good to make a function that suits my problem based on this, but hopefully you are.
Thanks a lot in advance!
Upvotes: 4
Views: 786
Reputation: 4474
You can use the partitions
package:
library(partitions)
t(compositions(5, 3, FALSE))
#[1,] 3 1 1
#[2,] 2 2 1
#[3,] 1 3 1
#[4,] 2 1 2
#[5,] 1 2 2
#[6,] 1 1 3
From the respective help file
Function compositions() returns all 2^(n-1) ways of partitioning an integer; thus 4 + 1 + 1 is distinct from 1 + 4 + 1 or 1 + 1 + 4.
Upvotes: 6
Reputation: 10372
Here is my solution, it is not very fast, but it could be a starting point for you to improve the speed.
n_ways <- function(n, k){
addend <- rep(seq(1,n),k)
combinations <- combn(x = addend, m = k)
combinations <- t(combinations[,which(colSums(combinations) == n)])
return(unique(combinations))
}
n_ways(5,3)
# [,1] [,2] [,3]
#[1,] 1 2 2
#[2,] 1 3 1
#[3,] 1 1 3
#[4,] 2 1 2
#[5,] 2 2 1
#[6,] 3 1 1
If you are interested in, I can write some comments to the function, but it consists of R base functions as colSums
or combn
.
Upvotes: 4
Reputation: 60492
Two possibilities:
eg <- expand.grid(rep(list(1:5), 3))
unique(eg[which(rowSums(eg)==5),])
which results in:
Var1 Var2 Var3
3 3 1 1
7 2 2 1
11 1 3 1
27 2 1 2
31 1 2 2
51 1 1 3
Or use the combinat (but this samples without replacement)
library(combinat)
combn(5, 3)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 1 1 1 1 1 1 2 2 2 3
# [2,] 2 2 2 3 3 4 3 3 4 4
# [3,] 3 4 5 4 5 5 4 5 5 5
Upvotes: 4