Find all combinations of a set of numbers that add up to a certain total









up vote
6
down vote

favorite












I've seen a few solutions to similar problems, but they all require iteration over the number of items to be added together.



Here's my goal: from a list of numbers, find all of the combinations (without replacement) that add up to a certain total. For example, if I have numbers 1,1,2,3,5 and total 5, it should return 5,2,3, and 1,1,3.



I was trying to use combn but it required you to specify the number of items in each combination. Is there a way to do it that allows for solution sets of any size?










share|improve this question























  • Possible duplicate of Finding all possible combinations of numbers to reach a given sum
    – 989
    Nov 10 at 0:07






  • 3




    @989, perhaps, but the only R solution there returns nothing (which is, in this context and my opinion, a waste of a function) and operates in side-effect by printing compactly formatted "formulas" to the console. It might be useful to some, but it defies functional programming and actually doing something with the findings.
    – r2evans
    Nov 10 at 2:52














up vote
6
down vote

favorite












I've seen a few solutions to similar problems, but they all require iteration over the number of items to be added together.



Here's my goal: from a list of numbers, find all of the combinations (without replacement) that add up to a certain total. For example, if I have numbers 1,1,2,3,5 and total 5, it should return 5,2,3, and 1,1,3.



I was trying to use combn but it required you to specify the number of items in each combination. Is there a way to do it that allows for solution sets of any size?










share|improve this question























  • Possible duplicate of Finding all possible combinations of numbers to reach a given sum
    – 989
    Nov 10 at 0:07






  • 3




    @989, perhaps, but the only R solution there returns nothing (which is, in this context and my opinion, a waste of a function) and operates in side-effect by printing compactly formatted "formulas" to the console. It might be useful to some, but it defies functional programming and actually doing something with the findings.
    – r2evans
    Nov 10 at 2:52












up vote
6
down vote

favorite









up vote
6
down vote

favorite











I've seen a few solutions to similar problems, but they all require iteration over the number of items to be added together.



Here's my goal: from a list of numbers, find all of the combinations (without replacement) that add up to a certain total. For example, if I have numbers 1,1,2,3,5 and total 5, it should return 5,2,3, and 1,1,3.



I was trying to use combn but it required you to specify the number of items in each combination. Is there a way to do it that allows for solution sets of any size?










share|improve this question















I've seen a few solutions to similar problems, but they all require iteration over the number of items to be added together.



Here's my goal: from a list of numbers, find all of the combinations (without replacement) that add up to a certain total. For example, if I have numbers 1,1,2,3,5 and total 5, it should return 5,2,3, and 1,1,3.



I was trying to use combn but it required you to specify the number of items in each combination. Is there a way to do it that allows for solution sets of any size?







r combinations






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 11 at 12:46









Jaap

53.9k20116127




53.9k20116127










asked Nov 9 at 23:26









Kira Tebbe

176215




176215











  • Possible duplicate of Finding all possible combinations of numbers to reach a given sum
    – 989
    Nov 10 at 0:07






  • 3




    @989, perhaps, but the only R solution there returns nothing (which is, in this context and my opinion, a waste of a function) and operates in side-effect by printing compactly formatted "formulas" to the console. It might be useful to some, but it defies functional programming and actually doing something with the findings.
    – r2evans
    Nov 10 at 2:52
















  • Possible duplicate of Finding all possible combinations of numbers to reach a given sum
    – 989
    Nov 10 at 0:07






  • 3




    @989, perhaps, but the only R solution there returns nothing (which is, in this context and my opinion, a waste of a function) and operates in side-effect by printing compactly formatted "formulas" to the console. It might be useful to some, but it defies functional programming and actually doing something with the findings.
    – r2evans
    Nov 10 at 2:52















Possible duplicate of Finding all possible combinations of numbers to reach a given sum
– 989
Nov 10 at 0:07




Possible duplicate of Finding all possible combinations of numbers to reach a given sum
– 989
Nov 10 at 0:07




3




3




@989, perhaps, but the only R solution there returns nothing (which is, in this context and my opinion, a waste of a function) and operates in side-effect by printing compactly formatted "formulas" to the console. It might be useful to some, but it defies functional programming and actually doing something with the findings.
– r2evans
Nov 10 at 2:52




@989, perhaps, but the only R solution there returns nothing (which is, in this context and my opinion, a waste of a function) and operates in side-effect by printing compactly formatted "formulas" to the console. It might be useful to some, but it defies functional programming and actually doing something with the findings.
– r2evans
Nov 10 at 2:52












5 Answers
5






active

oldest

votes

















up vote
7
down vote



accepted










This is precisely what combo/permuteGeneral from RcppAlgos (I am the author) were built for. Since we have repetition of specific elements in our sample vector, we will be finding combinations of multisets that meet our criteria. Note that this is different than the more common case of generating combinations with repetition where each element is allowed to be repeated m times. For many combination generating functions, multisets pose problems as duplicates are introduced and must be dealt with. This can become a bottleneck in your code if the size of your data is decently large. The functions in RcppAlgos handle these cases efficiently without creating any duplicate results. I should mention that there are a couple of other great libraries that handle multisets quite well: multicool and arrangements.



Moving on to the task at hand, we can utilize the constraint arguments of comboGeneral to find all combinations of our vector that meet a specific criteria:



vec <- c(1,1,2,3,5) ## using variables from @r2evans
uni <- unique(vec)
myRep <- rle(vec)$lengths
ans <- 5

library(RcppAlgos)
lapply(seq_along(uni), function(x)
comboGeneral(uni, x, freqs = myRep,
constraintFun = "sum",
comparisonFun = "==",
limitConstraints = ans)
)

[[1]]
[,1]
[1,] 5

[[2]]
[,1] [,2]
[1,] 2 3

[[3]]
[,1] [,2] [,3]
[1,] 1 1 3

[[4]]
[,1] [,2] [,3] [,4] ## no solutions of length 4


These functions are highly optimized and extend well to larger cases. For example, consider the following example that would produce over 30 million combinations:



set.seed(42)
bigVec <- sort(sample(1:30, 40, TRUE))

rle(bigVec)
Run Length Encoding
lengths: int [1:22] 2 1 1 2 1 1 1 2 3 1 ...
values : int [1:22] 1 3 4 5 7 8 9 12 14 15 ...

bigUni <- unique(bigVec)
bigRep <- rle(bigVec)$lengths
bigAns <- 199
len <- 12

comboCount(bigUni, len, freqs = bigRep)
[1] 30904021


All 300000+ results are returned very quickly:



system.time(bigTest <- comboGeneral(bigUni, len, freqs = bigRep,
constraintFun = "sum",
comparisonFun = "==",
limitConstraints = bigAns))
user system elapsed
0.383 0.008 0.390

head(bigTest)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
[1,] 1 1 3 4 5 9 29 29 29 29 30 30
[2,] 1 1 3 4 5 12 26 29 29 29 30 30
[3,] 1 1 3 4 5 12 28 28 28 29 30 30
[4,] 1 1 3 4 5 12 28 28 29 29 29 30
[5,] 1 1 3 4 5 14 25 28 29 29 30 30
[6,] 1 1 3 4 5 14 25 29 29 29 29 30

nrow(bigTest)
[1] 370646

all(rowSums(bigTest) == bigAns)
[1] TRUE


Addendum



I must mention that generally when I see a problem like: "finding all combinations that sum to a particular number" my first thought is integer partitions. For example, in the related problem Getting all combinations which sum up to 100 in R, we can easily solve with the partitions library. However, this approach does not extend to the general case (as we have here) where the vector contains specific repetition or we have a vector that contains values that don't easily convert to an integer equivalent (E.g. the vector (0.1, 0.2, 0.3, 0.4) can easily be treated as 1:4, however treating c(3.98486 7.84692 0.0038937 7.4879) as integers and subsequently applying an integer partitions approach would require an extravagant amount of computing power rendering this method useless).






share|improve this answer


















  • 2




    Really impressed by the large cases.
    – nate.edwinton
    Nov 10 at 8:57






  • 1




    This is the fastest approach given so far.
    – mickey
    Nov 10 at 14:56

















up vote
6
down vote













I took your combn idea and looped over the possible sizes of the sets.



func = function(x, total)
M = length(x)
y = NULL
total = 15
for (m in 1:M)
tmp = combn(x, m)
ind = which(colSums(tmp) == total)
if (length(ind) > 0)
for (j in 1:length(ind))
y = c(y, list(tmp[,ind[j]]))


return (unique(lapply(y, sort)))


x = c(1,1,2,3,5,8,13)

> func(x, 15)
[[1]]
[1] 2 13

[[2]]
[1] 1 1 13

[[3]]
[1] 2 5 8

[[4]]
[1] 1 1 5 8

[[5]]
[1] 1 1 2 3 8


Obviously, this will have problems as M grows since tmp will get big pretty quickly and the length of y can't be (maybe?) pre-determined.






share|improve this answer






















  • I like this method; the only issue is it'll return duplicates in a different order (like both [1,4] and [4,1]).
    – Kira Tebbe
    Nov 10 at 18:42






  • 1




    Modified so no duplicates
    – mickey
    Nov 10 at 18:47










  • Great edit! Missing right parenthesis at the end of the return statement, but a great solution. Thank you!
    – Kira Tebbe
    Nov 10 at 18:50






  • 1




    Thanks, I would still recommend Joseph Wood's answer especially if you're working with large data.
    – mickey
    Nov 10 at 18:58

















up vote
5
down vote













Similar to mickey's answer, we can use combn inside another looping mechanism. I'll use lapply:



vec <- c(1,1,2,3,5)
ans <- 5

Filter(length, lapply(seq_len(length(vec)),
function(i)
v <- combn(vec, i)
v[, colSums(v) == ans, drop = FALSE]
))
# [[1]]
# [,1]
# [1,] 5
# [[2]]
# [,1]
# [1,] 2
# [2,] 3
# [[3]]
# [,1]
# [1,] 1
# [2,] 1
# [3,] 3


You can omit the Filter(length, portion, though it may return a number of empty matrices. They're easy enough to deal with and ignore, I just thought removing them would be aesthetically preferred.



This method gives you a matrix with multiple candidates in each column, so



ans <- 4
Filter(length, lapply(seq_len(length(vec)),
function(i)
v <- combn(vec, i)
v[, colSums(v) == ans, drop = FALSE]
))
# [[1]]
# [,1] [,2]
# [1,] 1 1
# [2,] 3 3
# [[2]]
# [,1]
# [1,] 1
# [2,] 1
# [3,] 2


If duplicates are a problem, you can always do:



Filter(length, lapply(seq_len(length(vec)),
function(i)
v <- combn(vec, i)
v <- v[, colSums(v) == ans, drop = FALSE]
v[,!duplicated(t(v)),drop = FALSE]
))
# [[1]]
# [,1]
# [1,] 1
# [2,] 3
# [[2]]
# [,1]
# [1,] 1
# [2,] 1
# [3,] 2





share|improve this answer




















  • Can duplicates be a problem? I think combn gives unique columns.
    – mickey
    Nov 9 at 23:53






  • 1




    Duplicates are a problem when the input vector has duplicates (1 is listed twice in the input vector). A duplicate is demonstrated in the second example. combn works in the elements themselves, not just unique elements.
    – r2evans
    Nov 9 at 23:55











  • This looks good, but I copied your code and got an error (Error in colSums(v) : 'x' must be an array of at least two dimensions). Trying to figure out why.
    – Kira Tebbe
    Nov 10 at 4:53










  • What r2evans calls vec, you were calling x. Make sure you have the names of the variables correct.
    – mickey
    Nov 10 at 14:45










  • The issue seems to be when that combn(vec, i) returns a list, not a matrix, when i is equal to the length of elements in vec. It has an easy workaround, but I'm not sure why that wasn't happening here.
    – Kira Tebbe
    Nov 10 at 18:35

















up vote
4
down vote













Now here is a solution involving gtools (gtools::permutations):



# Creating lists of all permutations of the vector x
df1 <- permutations(n=length(x),r=length(x),v=1:length(x),repeats.allowed=F)
ls1 <- list()
for(j in 1:nrow(df1)) ls1[[j]] <- x[df1[j,1:ncol(df1)]]

# Taking all cumulative sums and filtering entries equaling our magic number
sumsCum <- t(vapply(1:length(ls1), function(j) cumsum(ls1[[j]]), numeric(length(x))))
indexMN <- which(sumsCum == magicNumber, arr.ind = T)
finalList <- list()
for(j in 1:nrow(indexMN))
magicRow <- indexMN[j,1]
magicCol <- 1:indexMN[j,2]
finalList[[j]] <- ls1[[magicRow]][magicCol]

finalList <- unique(finalList)


where x = c(1,1,2,3,5) and magicNumber = 5. This is a first draft, I am sure it can be improved here and there.






share|improve this answer



























    up vote
    2
    down vote













    Not the most efficient but the most compact so far:



    x <- c(1,1,2,3,5)
    n <- length(x)
    res <- 5
    unique(combn(c(x,rep(0,n-1)), n, function(x) x[x!=0][sum(x)==res], FALSE))[-1]
    # [[1]]
    # [1] 1 1 3
    #
    # [[2]]
    # [1] 2 3
    #
    # [[3]]
    # [1] 5
    #





    share|improve this answer




















      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234525%2ffind-all-combinations-of-a-set-of-numbers-that-add-up-to-a-certain-total%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      7
      down vote



      accepted










      This is precisely what combo/permuteGeneral from RcppAlgos (I am the author) were built for. Since we have repetition of specific elements in our sample vector, we will be finding combinations of multisets that meet our criteria. Note that this is different than the more common case of generating combinations with repetition where each element is allowed to be repeated m times. For many combination generating functions, multisets pose problems as duplicates are introduced and must be dealt with. This can become a bottleneck in your code if the size of your data is decently large. The functions in RcppAlgos handle these cases efficiently without creating any duplicate results. I should mention that there are a couple of other great libraries that handle multisets quite well: multicool and arrangements.



      Moving on to the task at hand, we can utilize the constraint arguments of comboGeneral to find all combinations of our vector that meet a specific criteria:



      vec <- c(1,1,2,3,5) ## using variables from @r2evans
      uni <- unique(vec)
      myRep <- rle(vec)$lengths
      ans <- 5

      library(RcppAlgos)
      lapply(seq_along(uni), function(x)
      comboGeneral(uni, x, freqs = myRep,
      constraintFun = "sum",
      comparisonFun = "==",
      limitConstraints = ans)
      )

      [[1]]
      [,1]
      [1,] 5

      [[2]]
      [,1] [,2]
      [1,] 2 3

      [[3]]
      [,1] [,2] [,3]
      [1,] 1 1 3

      [[4]]
      [,1] [,2] [,3] [,4] ## no solutions of length 4


      These functions are highly optimized and extend well to larger cases. For example, consider the following example that would produce over 30 million combinations:



      set.seed(42)
      bigVec <- sort(sample(1:30, 40, TRUE))

      rle(bigVec)
      Run Length Encoding
      lengths: int [1:22] 2 1 1 2 1 1 1 2 3 1 ...
      values : int [1:22] 1 3 4 5 7 8 9 12 14 15 ...

      bigUni <- unique(bigVec)
      bigRep <- rle(bigVec)$lengths
      bigAns <- 199
      len <- 12

      comboCount(bigUni, len, freqs = bigRep)
      [1] 30904021


      All 300000+ results are returned very quickly:



      system.time(bigTest <- comboGeneral(bigUni, len, freqs = bigRep,
      constraintFun = "sum",
      comparisonFun = "==",
      limitConstraints = bigAns))
      user system elapsed
      0.383 0.008 0.390

      head(bigTest)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
      [1,] 1 1 3 4 5 9 29 29 29 29 30 30
      [2,] 1 1 3 4 5 12 26 29 29 29 30 30
      [3,] 1 1 3 4 5 12 28 28 28 29 30 30
      [4,] 1 1 3 4 5 12 28 28 29 29 29 30
      [5,] 1 1 3 4 5 14 25 28 29 29 30 30
      [6,] 1 1 3 4 5 14 25 29 29 29 29 30

      nrow(bigTest)
      [1] 370646

      all(rowSums(bigTest) == bigAns)
      [1] TRUE


      Addendum



      I must mention that generally when I see a problem like: "finding all combinations that sum to a particular number" my first thought is integer partitions. For example, in the related problem Getting all combinations which sum up to 100 in R, we can easily solve with the partitions library. However, this approach does not extend to the general case (as we have here) where the vector contains specific repetition or we have a vector that contains values that don't easily convert to an integer equivalent (E.g. the vector (0.1, 0.2, 0.3, 0.4) can easily be treated as 1:4, however treating c(3.98486 7.84692 0.0038937 7.4879) as integers and subsequently applying an integer partitions approach would require an extravagant amount of computing power rendering this method useless).






      share|improve this answer


















      • 2




        Really impressed by the large cases.
        – nate.edwinton
        Nov 10 at 8:57






      • 1




        This is the fastest approach given so far.
        – mickey
        Nov 10 at 14:56














      up vote
      7
      down vote



      accepted










      This is precisely what combo/permuteGeneral from RcppAlgos (I am the author) were built for. Since we have repetition of specific elements in our sample vector, we will be finding combinations of multisets that meet our criteria. Note that this is different than the more common case of generating combinations with repetition where each element is allowed to be repeated m times. For many combination generating functions, multisets pose problems as duplicates are introduced and must be dealt with. This can become a bottleneck in your code if the size of your data is decently large. The functions in RcppAlgos handle these cases efficiently without creating any duplicate results. I should mention that there are a couple of other great libraries that handle multisets quite well: multicool and arrangements.



      Moving on to the task at hand, we can utilize the constraint arguments of comboGeneral to find all combinations of our vector that meet a specific criteria:



      vec <- c(1,1,2,3,5) ## using variables from @r2evans
      uni <- unique(vec)
      myRep <- rle(vec)$lengths
      ans <- 5

      library(RcppAlgos)
      lapply(seq_along(uni), function(x)
      comboGeneral(uni, x, freqs = myRep,
      constraintFun = "sum",
      comparisonFun = "==",
      limitConstraints = ans)
      )

      [[1]]
      [,1]
      [1,] 5

      [[2]]
      [,1] [,2]
      [1,] 2 3

      [[3]]
      [,1] [,2] [,3]
      [1,] 1 1 3

      [[4]]
      [,1] [,2] [,3] [,4] ## no solutions of length 4


      These functions are highly optimized and extend well to larger cases. For example, consider the following example that would produce over 30 million combinations:



      set.seed(42)
      bigVec <- sort(sample(1:30, 40, TRUE))

      rle(bigVec)
      Run Length Encoding
      lengths: int [1:22] 2 1 1 2 1 1 1 2 3 1 ...
      values : int [1:22] 1 3 4 5 7 8 9 12 14 15 ...

      bigUni <- unique(bigVec)
      bigRep <- rle(bigVec)$lengths
      bigAns <- 199
      len <- 12

      comboCount(bigUni, len, freqs = bigRep)
      [1] 30904021


      All 300000+ results are returned very quickly:



      system.time(bigTest <- comboGeneral(bigUni, len, freqs = bigRep,
      constraintFun = "sum",
      comparisonFun = "==",
      limitConstraints = bigAns))
      user system elapsed
      0.383 0.008 0.390

      head(bigTest)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
      [1,] 1 1 3 4 5 9 29 29 29 29 30 30
      [2,] 1 1 3 4 5 12 26 29 29 29 30 30
      [3,] 1 1 3 4 5 12 28 28 28 29 30 30
      [4,] 1 1 3 4 5 12 28 28 29 29 29 30
      [5,] 1 1 3 4 5 14 25 28 29 29 30 30
      [6,] 1 1 3 4 5 14 25 29 29 29 29 30

      nrow(bigTest)
      [1] 370646

      all(rowSums(bigTest) == bigAns)
      [1] TRUE


      Addendum



      I must mention that generally when I see a problem like: "finding all combinations that sum to a particular number" my first thought is integer partitions. For example, in the related problem Getting all combinations which sum up to 100 in R, we can easily solve with the partitions library. However, this approach does not extend to the general case (as we have here) where the vector contains specific repetition or we have a vector that contains values that don't easily convert to an integer equivalent (E.g. the vector (0.1, 0.2, 0.3, 0.4) can easily be treated as 1:4, however treating c(3.98486 7.84692 0.0038937 7.4879) as integers and subsequently applying an integer partitions approach would require an extravagant amount of computing power rendering this method useless).






      share|improve this answer


















      • 2




        Really impressed by the large cases.
        – nate.edwinton
        Nov 10 at 8:57






      • 1




        This is the fastest approach given so far.
        – mickey
        Nov 10 at 14:56












      up vote
      7
      down vote



      accepted







      up vote
      7
      down vote



      accepted






      This is precisely what combo/permuteGeneral from RcppAlgos (I am the author) were built for. Since we have repetition of specific elements in our sample vector, we will be finding combinations of multisets that meet our criteria. Note that this is different than the more common case of generating combinations with repetition where each element is allowed to be repeated m times. For many combination generating functions, multisets pose problems as duplicates are introduced and must be dealt with. This can become a bottleneck in your code if the size of your data is decently large. The functions in RcppAlgos handle these cases efficiently without creating any duplicate results. I should mention that there are a couple of other great libraries that handle multisets quite well: multicool and arrangements.



      Moving on to the task at hand, we can utilize the constraint arguments of comboGeneral to find all combinations of our vector that meet a specific criteria:



      vec <- c(1,1,2,3,5) ## using variables from @r2evans
      uni <- unique(vec)
      myRep <- rle(vec)$lengths
      ans <- 5

      library(RcppAlgos)
      lapply(seq_along(uni), function(x)
      comboGeneral(uni, x, freqs = myRep,
      constraintFun = "sum",
      comparisonFun = "==",
      limitConstraints = ans)
      )

      [[1]]
      [,1]
      [1,] 5

      [[2]]
      [,1] [,2]
      [1,] 2 3

      [[3]]
      [,1] [,2] [,3]
      [1,] 1 1 3

      [[4]]
      [,1] [,2] [,3] [,4] ## no solutions of length 4


      These functions are highly optimized and extend well to larger cases. For example, consider the following example that would produce over 30 million combinations:



      set.seed(42)
      bigVec <- sort(sample(1:30, 40, TRUE))

      rle(bigVec)
      Run Length Encoding
      lengths: int [1:22] 2 1 1 2 1 1 1 2 3 1 ...
      values : int [1:22] 1 3 4 5 7 8 9 12 14 15 ...

      bigUni <- unique(bigVec)
      bigRep <- rle(bigVec)$lengths
      bigAns <- 199
      len <- 12

      comboCount(bigUni, len, freqs = bigRep)
      [1] 30904021


      All 300000+ results are returned very quickly:



      system.time(bigTest <- comboGeneral(bigUni, len, freqs = bigRep,
      constraintFun = "sum",
      comparisonFun = "==",
      limitConstraints = bigAns))
      user system elapsed
      0.383 0.008 0.390

      head(bigTest)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
      [1,] 1 1 3 4 5 9 29 29 29 29 30 30
      [2,] 1 1 3 4 5 12 26 29 29 29 30 30
      [3,] 1 1 3 4 5 12 28 28 28 29 30 30
      [4,] 1 1 3 4 5 12 28 28 29 29 29 30
      [5,] 1 1 3 4 5 14 25 28 29 29 30 30
      [6,] 1 1 3 4 5 14 25 29 29 29 29 30

      nrow(bigTest)
      [1] 370646

      all(rowSums(bigTest) == bigAns)
      [1] TRUE


      Addendum



      I must mention that generally when I see a problem like: "finding all combinations that sum to a particular number" my first thought is integer partitions. For example, in the related problem Getting all combinations which sum up to 100 in R, we can easily solve with the partitions library. However, this approach does not extend to the general case (as we have here) where the vector contains specific repetition or we have a vector that contains values that don't easily convert to an integer equivalent (E.g. the vector (0.1, 0.2, 0.3, 0.4) can easily be treated as 1:4, however treating c(3.98486 7.84692 0.0038937 7.4879) as integers and subsequently applying an integer partitions approach would require an extravagant amount of computing power rendering this method useless).






      share|improve this answer














      This is precisely what combo/permuteGeneral from RcppAlgos (I am the author) were built for. Since we have repetition of specific elements in our sample vector, we will be finding combinations of multisets that meet our criteria. Note that this is different than the more common case of generating combinations with repetition where each element is allowed to be repeated m times. For many combination generating functions, multisets pose problems as duplicates are introduced and must be dealt with. This can become a bottleneck in your code if the size of your data is decently large. The functions in RcppAlgos handle these cases efficiently without creating any duplicate results. I should mention that there are a couple of other great libraries that handle multisets quite well: multicool and arrangements.



      Moving on to the task at hand, we can utilize the constraint arguments of comboGeneral to find all combinations of our vector that meet a specific criteria:



      vec <- c(1,1,2,3,5) ## using variables from @r2evans
      uni <- unique(vec)
      myRep <- rle(vec)$lengths
      ans <- 5

      library(RcppAlgos)
      lapply(seq_along(uni), function(x)
      comboGeneral(uni, x, freqs = myRep,
      constraintFun = "sum",
      comparisonFun = "==",
      limitConstraints = ans)
      )

      [[1]]
      [,1]
      [1,] 5

      [[2]]
      [,1] [,2]
      [1,] 2 3

      [[3]]
      [,1] [,2] [,3]
      [1,] 1 1 3

      [[4]]
      [,1] [,2] [,3] [,4] ## no solutions of length 4


      These functions are highly optimized and extend well to larger cases. For example, consider the following example that would produce over 30 million combinations:



      set.seed(42)
      bigVec <- sort(sample(1:30, 40, TRUE))

      rle(bigVec)
      Run Length Encoding
      lengths: int [1:22] 2 1 1 2 1 1 1 2 3 1 ...
      values : int [1:22] 1 3 4 5 7 8 9 12 14 15 ...

      bigUni <- unique(bigVec)
      bigRep <- rle(bigVec)$lengths
      bigAns <- 199
      len <- 12

      comboCount(bigUni, len, freqs = bigRep)
      [1] 30904021


      All 300000+ results are returned very quickly:



      system.time(bigTest <- comboGeneral(bigUni, len, freqs = bigRep,
      constraintFun = "sum",
      comparisonFun = "==",
      limitConstraints = bigAns))
      user system elapsed
      0.383 0.008 0.390

      head(bigTest)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
      [1,] 1 1 3 4 5 9 29 29 29 29 30 30
      [2,] 1 1 3 4 5 12 26 29 29 29 30 30
      [3,] 1 1 3 4 5 12 28 28 28 29 30 30
      [4,] 1 1 3 4 5 12 28 28 29 29 29 30
      [5,] 1 1 3 4 5 14 25 28 29 29 30 30
      [6,] 1 1 3 4 5 14 25 29 29 29 29 30

      nrow(bigTest)
      [1] 370646

      all(rowSums(bigTest) == bigAns)
      [1] TRUE


      Addendum



      I must mention that generally when I see a problem like: "finding all combinations that sum to a particular number" my first thought is integer partitions. For example, in the related problem Getting all combinations which sum up to 100 in R, we can easily solve with the partitions library. However, this approach does not extend to the general case (as we have here) where the vector contains specific repetition or we have a vector that contains values that don't easily convert to an integer equivalent (E.g. the vector (0.1, 0.2, 0.3, 0.4) can easily be treated as 1:4, however treating c(3.98486 7.84692 0.0038937 7.4879) as integers and subsequently applying an integer partitions approach would require an extravagant amount of computing power rendering this method useless).







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 10 at 16:18

























      answered Nov 10 at 7:31









      Joseph Wood

      3,20421634




      3,20421634







      • 2




        Really impressed by the large cases.
        – nate.edwinton
        Nov 10 at 8:57






      • 1




        This is the fastest approach given so far.
        – mickey
        Nov 10 at 14:56












      • 2




        Really impressed by the large cases.
        – nate.edwinton
        Nov 10 at 8:57






      • 1




        This is the fastest approach given so far.
        – mickey
        Nov 10 at 14:56







      2




      2




      Really impressed by the large cases.
      – nate.edwinton
      Nov 10 at 8:57




      Really impressed by the large cases.
      – nate.edwinton
      Nov 10 at 8:57




      1




      1




      This is the fastest approach given so far.
      – mickey
      Nov 10 at 14:56




      This is the fastest approach given so far.
      – mickey
      Nov 10 at 14:56












      up vote
      6
      down vote













      I took your combn idea and looped over the possible sizes of the sets.



      func = function(x, total)
      M = length(x)
      y = NULL
      total = 15
      for (m in 1:M)
      tmp = combn(x, m)
      ind = which(colSums(tmp) == total)
      if (length(ind) > 0)
      for (j in 1:length(ind))
      y = c(y, list(tmp[,ind[j]]))


      return (unique(lapply(y, sort)))


      x = c(1,1,2,3,5,8,13)

      > func(x, 15)
      [[1]]
      [1] 2 13

      [[2]]
      [1] 1 1 13

      [[3]]
      [1] 2 5 8

      [[4]]
      [1] 1 1 5 8

      [[5]]
      [1] 1 1 2 3 8


      Obviously, this will have problems as M grows since tmp will get big pretty quickly and the length of y can't be (maybe?) pre-determined.






      share|improve this answer






















      • I like this method; the only issue is it'll return duplicates in a different order (like both [1,4] and [4,1]).
        – Kira Tebbe
        Nov 10 at 18:42






      • 1




        Modified so no duplicates
        – mickey
        Nov 10 at 18:47










      • Great edit! Missing right parenthesis at the end of the return statement, but a great solution. Thank you!
        – Kira Tebbe
        Nov 10 at 18:50






      • 1




        Thanks, I would still recommend Joseph Wood's answer especially if you're working with large data.
        – mickey
        Nov 10 at 18:58














      up vote
      6
      down vote













      I took your combn idea and looped over the possible sizes of the sets.



      func = function(x, total)
      M = length(x)
      y = NULL
      total = 15
      for (m in 1:M)
      tmp = combn(x, m)
      ind = which(colSums(tmp) == total)
      if (length(ind) > 0)
      for (j in 1:length(ind))
      y = c(y, list(tmp[,ind[j]]))


      return (unique(lapply(y, sort)))


      x = c(1,1,2,3,5,8,13)

      > func(x, 15)
      [[1]]
      [1] 2 13

      [[2]]
      [1] 1 1 13

      [[3]]
      [1] 2 5 8

      [[4]]
      [1] 1 1 5 8

      [[5]]
      [1] 1 1 2 3 8


      Obviously, this will have problems as M grows since tmp will get big pretty quickly and the length of y can't be (maybe?) pre-determined.






      share|improve this answer






















      • I like this method; the only issue is it'll return duplicates in a different order (like both [1,4] and [4,1]).
        – Kira Tebbe
        Nov 10 at 18:42






      • 1




        Modified so no duplicates
        – mickey
        Nov 10 at 18:47










      • Great edit! Missing right parenthesis at the end of the return statement, but a great solution. Thank you!
        – Kira Tebbe
        Nov 10 at 18:50






      • 1




        Thanks, I would still recommend Joseph Wood's answer especially if you're working with large data.
        – mickey
        Nov 10 at 18:58












      up vote
      6
      down vote










      up vote
      6
      down vote









      I took your combn idea and looped over the possible sizes of the sets.



      func = function(x, total)
      M = length(x)
      y = NULL
      total = 15
      for (m in 1:M)
      tmp = combn(x, m)
      ind = which(colSums(tmp) == total)
      if (length(ind) > 0)
      for (j in 1:length(ind))
      y = c(y, list(tmp[,ind[j]]))


      return (unique(lapply(y, sort)))


      x = c(1,1,2,3,5,8,13)

      > func(x, 15)
      [[1]]
      [1] 2 13

      [[2]]
      [1] 1 1 13

      [[3]]
      [1] 2 5 8

      [[4]]
      [1] 1 1 5 8

      [[5]]
      [1] 1 1 2 3 8


      Obviously, this will have problems as M grows since tmp will get big pretty quickly and the length of y can't be (maybe?) pre-determined.






      share|improve this answer














      I took your combn idea and looped over the possible sizes of the sets.



      func = function(x, total)
      M = length(x)
      y = NULL
      total = 15
      for (m in 1:M)
      tmp = combn(x, m)
      ind = which(colSums(tmp) == total)
      if (length(ind) > 0)
      for (j in 1:length(ind))
      y = c(y, list(tmp[,ind[j]]))


      return (unique(lapply(y, sort)))


      x = c(1,1,2,3,5,8,13)

      > func(x, 15)
      [[1]]
      [1] 2 13

      [[2]]
      [1] 1 1 13

      [[3]]
      [1] 2 5 8

      [[4]]
      [1] 1 1 5 8

      [[5]]
      [1] 1 1 2 3 8


      Obviously, this will have problems as M grows since tmp will get big pretty quickly and the length of y can't be (maybe?) pre-determined.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 10 at 18:56

























      answered Nov 9 at 23:36









      mickey

      59013




      59013











      • I like this method; the only issue is it'll return duplicates in a different order (like both [1,4] and [4,1]).
        – Kira Tebbe
        Nov 10 at 18:42






      • 1




        Modified so no duplicates
        – mickey
        Nov 10 at 18:47










      • Great edit! Missing right parenthesis at the end of the return statement, but a great solution. Thank you!
        – Kira Tebbe
        Nov 10 at 18:50






      • 1




        Thanks, I would still recommend Joseph Wood's answer especially if you're working with large data.
        – mickey
        Nov 10 at 18:58
















      • I like this method; the only issue is it'll return duplicates in a different order (like both [1,4] and [4,1]).
        – Kira Tebbe
        Nov 10 at 18:42






      • 1




        Modified so no duplicates
        – mickey
        Nov 10 at 18:47










      • Great edit! Missing right parenthesis at the end of the return statement, but a great solution. Thank you!
        – Kira Tebbe
        Nov 10 at 18:50






      • 1




        Thanks, I would still recommend Joseph Wood's answer especially if you're working with large data.
        – mickey
        Nov 10 at 18:58















      I like this method; the only issue is it'll return duplicates in a different order (like both [1,4] and [4,1]).
      – Kira Tebbe
      Nov 10 at 18:42




      I like this method; the only issue is it'll return duplicates in a different order (like both [1,4] and [4,1]).
      – Kira Tebbe
      Nov 10 at 18:42




      1




      1




      Modified so no duplicates
      – mickey
      Nov 10 at 18:47




      Modified so no duplicates
      – mickey
      Nov 10 at 18:47












      Great edit! Missing right parenthesis at the end of the return statement, but a great solution. Thank you!
      – Kira Tebbe
      Nov 10 at 18:50




      Great edit! Missing right parenthesis at the end of the return statement, but a great solution. Thank you!
      – Kira Tebbe
      Nov 10 at 18:50




      1




      1




      Thanks, I would still recommend Joseph Wood's answer especially if you're working with large data.
      – mickey
      Nov 10 at 18:58




      Thanks, I would still recommend Joseph Wood's answer especially if you're working with large data.
      – mickey
      Nov 10 at 18:58










      up vote
      5
      down vote













      Similar to mickey's answer, we can use combn inside another looping mechanism. I'll use lapply:



      vec <- c(1,1,2,3,5)
      ans <- 5

      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v[, colSums(v) == ans, drop = FALSE]
      ))
      # [[1]]
      # [,1]
      # [1,] 5
      # [[2]]
      # [,1]
      # [1,] 2
      # [2,] 3
      # [[3]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 3


      You can omit the Filter(length, portion, though it may return a number of empty matrices. They're easy enough to deal with and ignore, I just thought removing them would be aesthetically preferred.



      This method gives you a matrix with multiple candidates in each column, so



      ans <- 4
      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v[, colSums(v) == ans, drop = FALSE]
      ))
      # [[1]]
      # [,1] [,2]
      # [1,] 1 1
      # [2,] 3 3
      # [[2]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 2


      If duplicates are a problem, you can always do:



      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v <- v[, colSums(v) == ans, drop = FALSE]
      v[,!duplicated(t(v)),drop = FALSE]
      ))
      # [[1]]
      # [,1]
      # [1,] 1
      # [2,] 3
      # [[2]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 2





      share|improve this answer




















      • Can duplicates be a problem? I think combn gives unique columns.
        – mickey
        Nov 9 at 23:53






      • 1




        Duplicates are a problem when the input vector has duplicates (1 is listed twice in the input vector). A duplicate is demonstrated in the second example. combn works in the elements themselves, not just unique elements.
        – r2evans
        Nov 9 at 23:55











      • This looks good, but I copied your code and got an error (Error in colSums(v) : 'x' must be an array of at least two dimensions). Trying to figure out why.
        – Kira Tebbe
        Nov 10 at 4:53










      • What r2evans calls vec, you were calling x. Make sure you have the names of the variables correct.
        – mickey
        Nov 10 at 14:45










      • The issue seems to be when that combn(vec, i) returns a list, not a matrix, when i is equal to the length of elements in vec. It has an easy workaround, but I'm not sure why that wasn't happening here.
        – Kira Tebbe
        Nov 10 at 18:35














      up vote
      5
      down vote













      Similar to mickey's answer, we can use combn inside another looping mechanism. I'll use lapply:



      vec <- c(1,1,2,3,5)
      ans <- 5

      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v[, colSums(v) == ans, drop = FALSE]
      ))
      # [[1]]
      # [,1]
      # [1,] 5
      # [[2]]
      # [,1]
      # [1,] 2
      # [2,] 3
      # [[3]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 3


      You can omit the Filter(length, portion, though it may return a number of empty matrices. They're easy enough to deal with and ignore, I just thought removing them would be aesthetically preferred.



      This method gives you a matrix with multiple candidates in each column, so



      ans <- 4
      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v[, colSums(v) == ans, drop = FALSE]
      ))
      # [[1]]
      # [,1] [,2]
      # [1,] 1 1
      # [2,] 3 3
      # [[2]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 2


      If duplicates are a problem, you can always do:



      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v <- v[, colSums(v) == ans, drop = FALSE]
      v[,!duplicated(t(v)),drop = FALSE]
      ))
      # [[1]]
      # [,1]
      # [1,] 1
      # [2,] 3
      # [[2]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 2





      share|improve this answer




















      • Can duplicates be a problem? I think combn gives unique columns.
        – mickey
        Nov 9 at 23:53






      • 1




        Duplicates are a problem when the input vector has duplicates (1 is listed twice in the input vector). A duplicate is demonstrated in the second example. combn works in the elements themselves, not just unique elements.
        – r2evans
        Nov 9 at 23:55











      • This looks good, but I copied your code and got an error (Error in colSums(v) : 'x' must be an array of at least two dimensions). Trying to figure out why.
        – Kira Tebbe
        Nov 10 at 4:53










      • What r2evans calls vec, you were calling x. Make sure you have the names of the variables correct.
        – mickey
        Nov 10 at 14:45










      • The issue seems to be when that combn(vec, i) returns a list, not a matrix, when i is equal to the length of elements in vec. It has an easy workaround, but I'm not sure why that wasn't happening here.
        – Kira Tebbe
        Nov 10 at 18:35












      up vote
      5
      down vote










      up vote
      5
      down vote









      Similar to mickey's answer, we can use combn inside another looping mechanism. I'll use lapply:



      vec <- c(1,1,2,3,5)
      ans <- 5

      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v[, colSums(v) == ans, drop = FALSE]
      ))
      # [[1]]
      # [,1]
      # [1,] 5
      # [[2]]
      # [,1]
      # [1,] 2
      # [2,] 3
      # [[3]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 3


      You can omit the Filter(length, portion, though it may return a number of empty matrices. They're easy enough to deal with and ignore, I just thought removing them would be aesthetically preferred.



      This method gives you a matrix with multiple candidates in each column, so



      ans <- 4
      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v[, colSums(v) == ans, drop = FALSE]
      ))
      # [[1]]
      # [,1] [,2]
      # [1,] 1 1
      # [2,] 3 3
      # [[2]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 2


      If duplicates are a problem, you can always do:



      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v <- v[, colSums(v) == ans, drop = FALSE]
      v[,!duplicated(t(v)),drop = FALSE]
      ))
      # [[1]]
      # [,1]
      # [1,] 1
      # [2,] 3
      # [[2]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 2





      share|improve this answer












      Similar to mickey's answer, we can use combn inside another looping mechanism. I'll use lapply:



      vec <- c(1,1,2,3,5)
      ans <- 5

      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v[, colSums(v) == ans, drop = FALSE]
      ))
      # [[1]]
      # [,1]
      # [1,] 5
      # [[2]]
      # [,1]
      # [1,] 2
      # [2,] 3
      # [[3]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 3


      You can omit the Filter(length, portion, though it may return a number of empty matrices. They're easy enough to deal with and ignore, I just thought removing them would be aesthetically preferred.



      This method gives you a matrix with multiple candidates in each column, so



      ans <- 4
      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v[, colSums(v) == ans, drop = FALSE]
      ))
      # [[1]]
      # [,1] [,2]
      # [1,] 1 1
      # [2,] 3 3
      # [[2]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 2


      If duplicates are a problem, you can always do:



      Filter(length, lapply(seq_len(length(vec)),
      function(i)
      v <- combn(vec, i)
      v <- v[, colSums(v) == ans, drop = FALSE]
      v[,!duplicated(t(v)),drop = FALSE]
      ))
      # [[1]]
      # [,1]
      # [1,] 1
      # [2,] 3
      # [[2]]
      # [,1]
      # [1,] 1
      # [2,] 1
      # [3,] 2






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Nov 9 at 23:45









      r2evans

      24.4k32856




      24.4k32856











      • Can duplicates be a problem? I think combn gives unique columns.
        – mickey
        Nov 9 at 23:53






      • 1




        Duplicates are a problem when the input vector has duplicates (1 is listed twice in the input vector). A duplicate is demonstrated in the second example. combn works in the elements themselves, not just unique elements.
        – r2evans
        Nov 9 at 23:55











      • This looks good, but I copied your code and got an error (Error in colSums(v) : 'x' must be an array of at least two dimensions). Trying to figure out why.
        – Kira Tebbe
        Nov 10 at 4:53










      • What r2evans calls vec, you were calling x. Make sure you have the names of the variables correct.
        – mickey
        Nov 10 at 14:45










      • The issue seems to be when that combn(vec, i) returns a list, not a matrix, when i is equal to the length of elements in vec. It has an easy workaround, but I'm not sure why that wasn't happening here.
        – Kira Tebbe
        Nov 10 at 18:35
















      • Can duplicates be a problem? I think combn gives unique columns.
        – mickey
        Nov 9 at 23:53






      • 1




        Duplicates are a problem when the input vector has duplicates (1 is listed twice in the input vector). A duplicate is demonstrated in the second example. combn works in the elements themselves, not just unique elements.
        – r2evans
        Nov 9 at 23:55











      • This looks good, but I copied your code and got an error (Error in colSums(v) : 'x' must be an array of at least two dimensions). Trying to figure out why.
        – Kira Tebbe
        Nov 10 at 4:53










      • What r2evans calls vec, you were calling x. Make sure you have the names of the variables correct.
        – mickey
        Nov 10 at 14:45










      • The issue seems to be when that combn(vec, i) returns a list, not a matrix, when i is equal to the length of elements in vec. It has an easy workaround, but I'm not sure why that wasn't happening here.
        – Kira Tebbe
        Nov 10 at 18:35















      Can duplicates be a problem? I think combn gives unique columns.
      – mickey
      Nov 9 at 23:53




      Can duplicates be a problem? I think combn gives unique columns.
      – mickey
      Nov 9 at 23:53




      1




      1




      Duplicates are a problem when the input vector has duplicates (1 is listed twice in the input vector). A duplicate is demonstrated in the second example. combn works in the elements themselves, not just unique elements.
      – r2evans
      Nov 9 at 23:55





      Duplicates are a problem when the input vector has duplicates (1 is listed twice in the input vector). A duplicate is demonstrated in the second example. combn works in the elements themselves, not just unique elements.
      – r2evans
      Nov 9 at 23:55













      This looks good, but I copied your code and got an error (Error in colSums(v) : 'x' must be an array of at least two dimensions). Trying to figure out why.
      – Kira Tebbe
      Nov 10 at 4:53




      This looks good, but I copied your code and got an error (Error in colSums(v) : 'x' must be an array of at least two dimensions). Trying to figure out why.
      – Kira Tebbe
      Nov 10 at 4:53












      What r2evans calls vec, you were calling x. Make sure you have the names of the variables correct.
      – mickey
      Nov 10 at 14:45




      What r2evans calls vec, you were calling x. Make sure you have the names of the variables correct.
      – mickey
      Nov 10 at 14:45












      The issue seems to be when that combn(vec, i) returns a list, not a matrix, when i is equal to the length of elements in vec. It has an easy workaround, but I'm not sure why that wasn't happening here.
      – Kira Tebbe
      Nov 10 at 18:35




      The issue seems to be when that combn(vec, i) returns a list, not a matrix, when i is equal to the length of elements in vec. It has an easy workaround, but I'm not sure why that wasn't happening here.
      – Kira Tebbe
      Nov 10 at 18:35










      up vote
      4
      down vote













      Now here is a solution involving gtools (gtools::permutations):



      # Creating lists of all permutations of the vector x
      df1 <- permutations(n=length(x),r=length(x),v=1:length(x),repeats.allowed=F)
      ls1 <- list()
      for(j in 1:nrow(df1)) ls1[[j]] <- x[df1[j,1:ncol(df1)]]

      # Taking all cumulative sums and filtering entries equaling our magic number
      sumsCum <- t(vapply(1:length(ls1), function(j) cumsum(ls1[[j]]), numeric(length(x))))
      indexMN <- which(sumsCum == magicNumber, arr.ind = T)
      finalList <- list()
      for(j in 1:nrow(indexMN))
      magicRow <- indexMN[j,1]
      magicCol <- 1:indexMN[j,2]
      finalList[[j]] <- ls1[[magicRow]][magicCol]

      finalList <- unique(finalList)


      where x = c(1,1,2,3,5) and magicNumber = 5. This is a first draft, I am sure it can be improved here and there.






      share|improve this answer
























        up vote
        4
        down vote













        Now here is a solution involving gtools (gtools::permutations):



        # Creating lists of all permutations of the vector x
        df1 <- permutations(n=length(x),r=length(x),v=1:length(x),repeats.allowed=F)
        ls1 <- list()
        for(j in 1:nrow(df1)) ls1[[j]] <- x[df1[j,1:ncol(df1)]]

        # Taking all cumulative sums and filtering entries equaling our magic number
        sumsCum <- t(vapply(1:length(ls1), function(j) cumsum(ls1[[j]]), numeric(length(x))))
        indexMN <- which(sumsCum == magicNumber, arr.ind = T)
        finalList <- list()
        for(j in 1:nrow(indexMN))
        magicRow <- indexMN[j,1]
        magicCol <- 1:indexMN[j,2]
        finalList[[j]] <- ls1[[magicRow]][magicCol]

        finalList <- unique(finalList)


        where x = c(1,1,2,3,5) and magicNumber = 5. This is a first draft, I am sure it can be improved here and there.






        share|improve this answer






















          up vote
          4
          down vote










          up vote
          4
          down vote









          Now here is a solution involving gtools (gtools::permutations):



          # Creating lists of all permutations of the vector x
          df1 <- permutations(n=length(x),r=length(x),v=1:length(x),repeats.allowed=F)
          ls1 <- list()
          for(j in 1:nrow(df1)) ls1[[j]] <- x[df1[j,1:ncol(df1)]]

          # Taking all cumulative sums and filtering entries equaling our magic number
          sumsCum <- t(vapply(1:length(ls1), function(j) cumsum(ls1[[j]]), numeric(length(x))))
          indexMN <- which(sumsCum == magicNumber, arr.ind = T)
          finalList <- list()
          for(j in 1:nrow(indexMN))
          magicRow <- indexMN[j,1]
          magicCol <- 1:indexMN[j,2]
          finalList[[j]] <- ls1[[magicRow]][magicCol]

          finalList <- unique(finalList)


          where x = c(1,1,2,3,5) and magicNumber = 5. This is a first draft, I am sure it can be improved here and there.






          share|improve this answer












          Now here is a solution involving gtools (gtools::permutations):



          # Creating lists of all permutations of the vector x
          df1 <- permutations(n=length(x),r=length(x),v=1:length(x),repeats.allowed=F)
          ls1 <- list()
          for(j in 1:nrow(df1)) ls1[[j]] <- x[df1[j,1:ncol(df1)]]

          # Taking all cumulative sums and filtering entries equaling our magic number
          sumsCum <- t(vapply(1:length(ls1), function(j) cumsum(ls1[[j]]), numeric(length(x))))
          indexMN <- which(sumsCum == magicNumber, arr.ind = T)
          finalList <- list()
          for(j in 1:nrow(indexMN))
          magicRow <- indexMN[j,1]
          magicCol <- 1:indexMN[j,2]
          finalList[[j]] <- ls1[[magicRow]][magicCol]

          finalList <- unique(finalList)


          where x = c(1,1,2,3,5) and magicNumber = 5. This is a first draft, I am sure it can be improved here and there.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 10 at 0:25









          nate.edwinton

          901314




          901314




















              up vote
              2
              down vote













              Not the most efficient but the most compact so far:



              x <- c(1,1,2,3,5)
              n <- length(x)
              res <- 5
              unique(combn(c(x,rep(0,n-1)), n, function(x) x[x!=0][sum(x)==res], FALSE))[-1]
              # [[1]]
              # [1] 1 1 3
              #
              # [[2]]
              # [1] 2 3
              #
              # [[3]]
              # [1] 5
              #





              share|improve this answer
























                up vote
                2
                down vote













                Not the most efficient but the most compact so far:



                x <- c(1,1,2,3,5)
                n <- length(x)
                res <- 5
                unique(combn(c(x,rep(0,n-1)), n, function(x) x[x!=0][sum(x)==res], FALSE))[-1]
                # [[1]]
                # [1] 1 1 3
                #
                # [[2]]
                # [1] 2 3
                #
                # [[3]]
                # [1] 5
                #





                share|improve this answer






















                  up vote
                  2
                  down vote










                  up vote
                  2
                  down vote









                  Not the most efficient but the most compact so far:



                  x <- c(1,1,2,3,5)
                  n <- length(x)
                  res <- 5
                  unique(combn(c(x,rep(0,n-1)), n, function(x) x[x!=0][sum(x)==res], FALSE))[-1]
                  # [[1]]
                  # [1] 1 1 3
                  #
                  # [[2]]
                  # [1] 2 3
                  #
                  # [[3]]
                  # [1] 5
                  #





                  share|improve this answer












                  Not the most efficient but the most compact so far:



                  x <- c(1,1,2,3,5)
                  n <- length(x)
                  res <- 5
                  unique(combn(c(x,rep(0,n-1)), n, function(x) x[x!=0][sum(x)==res], FALSE))[-1]
                  # [[1]]
                  # [1] 1 1 3
                  #
                  # [[2]]
                  # [1] 2 3
                  #
                  # [[3]]
                  # [1] 5
                  #






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 10 at 9:49









                  Moody_Mudskipper

                  20.5k32460




                  20.5k32460



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234525%2ffind-all-combinations-of-a-set-of-numbers-that-add-up-to-a-certain-total%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      Barbados

                      How to read a connectionString WITH PROVIDER in .NET Core?

                      Node.js Script on GitHub Pages or Amazon S3