Get all possible combinations within a given product sum

Viewed 812

I am looking to write an R script that will generate all possible combinations of a collection numbers for which their product sum is under a certain total.

For example, I have these two vectors, x representing the elements I want to generate combinations for, y representing the elements to find the product sum.

x <- c(2,4,6) #elements to find combinations

y <- c(24,48,72) #elements to find product sum

My main constraint here is that the total product sum of any combination of x must be less than or equal to 1244.

Example of Desired Result

|--------------|--------------|--------------|---------------------|
|  Total of 2  |  Total of 4  |  Total of 6  |  Total Product Sum  |
|--------------|--------------|--------------|---------------------|
|       1      |      1       |       1      |         144         |
|--------------|--------------|--------------|---------------------|
|       2      |      2       |       2      |         288         |    
|--------------|--------------|--------------|---------------------|
|       3      |      3       |       3      |         432         |    
|--------------|--------------|--------------|---------------------|
|       4      |      4       |       4      |         576         |    
|--------------|--------------|--------------|---------------------|
|       5      |      5       |       5      |         720         |    
|--------------|--------------|--------------|---------------------|
|      ...     |      ...     |      ...     |         ...         |    
|--------------|--------------|--------------|---------------------|

Sample Code in R

I have tried using the following code, but it only works linearly instead of generating all possible combinations that are less than or equal to 1244.

n_trials <- 30
# data frame to store all possible combinations and their product sum
combo_data <- data.frame(total_of_2 = rep(0,n_trials)
                             , total_of_4 = rep(0,n_trials)
                             , total_of_6 = rep(0,n_trials)
                             , total_product_sum = rep(0,n_trials))

 for (i in 1:n_trials) {
 # check that combination is at most 1244 sqft
   if (i*24 + i*48 + i*72 <= 1244) {
     # track number of each element in x
     combo_data$total_of_2[i] <- i
     combo_data$total_of_4[i] <- i
     combo_data$total_of_6[i] <- i

     # add total product sum
     combo_data$total_product_sum[i] <- i*24 + i*48 + i*72
   }
 }

 view(combo_data)
3 Answers

The number of valid combinations under 1244 will increase as you increase n, so I'm not entirely clear on the goal here. That said, here's a version that uses base R:

y <- c(24,48,72) #elements to find product sum
n <- 30
instances <- expand.grid(1:n, 1:n, 1:n)
instances$product_sum = rowSums(data.frame(Map('*', instances, y)))
instances <- subset(instances, product_sum <= 1244 )

First few rows of the result:

  Var1 Var2 Var3 product_sum
1    1    1    1         144
2    2    1    1         168
3    3    1    1         192
4    4    1    1         216
5    5    1    1         240
6    6    1    1         264

If instead of 1:n you use only your original x values of 2, 4, and 6, you should get 27 valid combinations.

Start with expand.grid to have all possible combinations and then use matrix multiplication.

x <- c(24, 48, 72)
e <- expand.grid(X = seq_len(30), Y = seq_len(30), Z = seq_len(30))

y <- as.vector(x %*% t(e))
z <- cbind(e[y < 1244, ], Prod = y[y < 1244])

head(z)
#  X Y Z Prod
#1 1 1 1  144
#2 2 1 1  168
#3 3 1 1  192
#4 4 1 1  216
#5 5 1 1  240
#6 6 1 1  264

If I understand you correctly:

tibble(X=1:30, Y=1:30, Z=1:30) %>% 
  expand(X, Y, Z) %>% 
  mutate(Total=X*24 + Y*48 + Z*72) %>% 
  filter(Total <= 1244)
# A tibble: 2,990 x 4
       X     Y     Z Total
   <int> <int> <int> <dbl>
 1     1     1     1   144
 2     1     1     2   216
 3     1     1     3   288
 4     1     1     4   360
 5     1     1     5   432
 6     1     1     6   504
 7     1     1     7   576
 8     1     1     8   648
 9     1     1     9   720
10     1     1    10   792
# … with 2,980 more rows

Your soliution fails because you don't loop over the total_of_<x> separately. You need three nested loops to do that. My solution hides the looping under the hood, but is still a brute force solution.

Related