Doudillo
Doudillo

Reputation: 11

How to make an efficient combination of numbers R?

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

Answers (3)

Neal Fultz
Neal Fultz

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

Doudillo
Doudillo

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

daroczig
daroczig

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

Related Questions