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?
r combinations
add a comment |
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?
r combinations
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
add a comment |
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?
r combinations
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
r combinations
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
add a comment |
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
add a comment |
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).
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
add a comment |
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.
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 thereturn
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
add a comment |
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
Can duplicates be a problem? I thinkcombn
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 callsvec
, you were callingx
. Make sure you have the names of the variables correct.
– mickey
Nov 10 at 14:45
The issue seems to be when thatcombn(vec, i)
returns a list, not a matrix, wheni
is equal to the length of elements invec
. It has an easy workaround, but I'm not sure why that wasn't happening here.
– Kira Tebbe
Nov 10 at 18:35
|
show 1 more comment
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.
add a comment |
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
#
add a comment |
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).
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
add a comment |
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).
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
add a comment |
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).
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).
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
add a comment |
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
add a comment |
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.
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 thereturn
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
add a comment |
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.
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 thereturn
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
add a comment |
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.
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.
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 thereturn
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
add a comment |
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 thereturn
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
add a comment |
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
Can duplicates be a problem? I thinkcombn
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 callsvec
, you were callingx
. Make sure you have the names of the variables correct.
– mickey
Nov 10 at 14:45
The issue seems to be when thatcombn(vec, i)
returns a list, not a matrix, wheni
is equal to the length of elements invec
. It has an easy workaround, but I'm not sure why that wasn't happening here.
– Kira Tebbe
Nov 10 at 18:35
|
show 1 more comment
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
Can duplicates be a problem? I thinkcombn
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 callsvec
, you were callingx
. Make sure you have the names of the variables correct.
– mickey
Nov 10 at 14:45
The issue seems to be when thatcombn(vec, i)
returns a list, not a matrix, wheni
is equal to the length of elements invec
. It has an easy workaround, but I'm not sure why that wasn't happening here.
– Kira Tebbe
Nov 10 at 18:35
|
show 1 more comment
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
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
answered Nov 9 at 23:45
r2evans
24.4k32856
24.4k32856
Can duplicates be a problem? I thinkcombn
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 callsvec
, you were callingx
. Make sure you have the names of the variables correct.
– mickey
Nov 10 at 14:45
The issue seems to be when thatcombn(vec, i)
returns a list, not a matrix, wheni
is equal to the length of elements invec
. It has an easy workaround, but I'm not sure why that wasn't happening here.
– Kira Tebbe
Nov 10 at 18:35
|
show 1 more comment
Can duplicates be a problem? I thinkcombn
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 callsvec
, you were callingx
. Make sure you have the names of the variables correct.
– mickey
Nov 10 at 14:45
The issue seems to be when thatcombn(vec, i)
returns a list, not a matrix, wheni
is equal to the length of elements invec
. 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
|
show 1 more comment
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 10 at 0:25
nate.edwinton
901314
901314
add a comment |
add a comment |
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
#
add a comment |
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
#
add a comment |
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
#
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
#
answered Nov 10 at 9:49
Moody_Mudskipper
20.5k32460
20.5k32460
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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