Reputation: 11
I am trying to make a matrix of all combinations of 5 numbers between 1 and 100 (integers) that sum to 100. If I could set up min and max for each 5 numbers that would be even greater. The easy way I have done it is to do do 5 nested loops.
for (a in min:max )
{
for (b in min:max )
{
for (c in min:max)
{
for(d in min:max)
{
for (e in min:max)
{
for (f in min:max)
{
for (g in min:max)
{
for (h in min:max)
{
port <- c (a,b,c,d,e,f,g,h)
if(a+b+c+d+e+f+g+h==100) {portif <- rbind(port,portif)}
}}}}}}}}
But I am pretty sure there is a better way in R than these prettry slow loops.
Edit : - Yes, the order is important
It would be even greater if I could set a different min and max for each a,b,c ...
Thanks a lot for your help
Upvotes: 1
Views: 125
Reputation: 9686
Dynamic programming might be faster for you, but harder to implement. Here's a recursive solution:
f <- function(min, max, cnt) {
if(max < min) return(NULL)
if(cnt == 1) return(max)
do.call(rbind, lapply(min:max,
function(i){
X <- f(min, max-i, cnt-1)
if(!is.null(X)) cbind(i, X)
})
)
}
To not include permutations of the same set, you can change the recursion to
X <- f(i+1, max-i, cnt-1)
//edit: To have different min and max for each ply, you can make min and max vectors, then change usage to eg min[cnt]
; you may also want to swap the order to cbind(X,i) for sanity.
Upvotes: 1
Reputation: 11
Than you, your both codes are much faster I found another bit of code which seems aloso quite good
library("partitions")
numparts <- 8
sumparts <- 20
weights <- compositions(n=sumparts, m=numparts, include.zero=TRUE)/sumparts
Upvotes: 0
Reputation: 28652
Get all (choose(100, 5)
resulting in 75287520
) combinations:
x <- combn(1L:100L, 5)
Compute the column sums and check which equals to 100
:
x[, colSums(x) == 100]
Resulting in 25337
combinations, e.g.:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 90
[2,] 1 2 3 5 89
[3,] 1 2 3 6 88
[4,] 1 2 3 7 87
[5,] 1 2 3 8 86
...
Upvotes: 4