I see 3 approaches:
- List all combinations of length N with
utils::combn() or gtools::combinations(), and only keep the one(s) that sum to X. That can be done changing a bit my code above.
- List all partitions using
partitions::parts(), and only keep the one(s) with no repetition.
- The above solutions are inefficient in that they compute more than needed. For big X, that's a lot of partitions/combinations that you're not interested in. You can instead rewrite an algorithm yourself taking inspiration from nirgrahamuk's link, so that you stop computations as soon as you find a satisfying partition, thus saving a lot of computations.
So, for 1:
X <- 15
N <- 5
# find all combinations
all_combns <- combn(X,N,simplify = FALSE)
# compute sums
all_sums <- sapply(all_combns, sum)
# is it a partition?
is_partition <- all_sums == X
# extract the satisfying partition(s)
all_combns[is_partition]
And for 2:
# find all partitions that have the right number of elements
all_partitions <- partitions::restrictedparts(X,N,
include.zero = FALSE)
# find partitions with no duplicate
nb_duplicates <- apply(all_partitions, 2, anyDuplicated)
has_no_duplicate <- nb_duplicates == 0
# extract values
all_partitions[,has_no_duplicate]
The first code gives all these partitions as a list, the second one as a matrix with one column per partition, for example for X=15, N=4:
> all_combns[is_partition]
[[1]]
[1] 1 2 3 9
[[2]]
[1] 1 2 4 8
[[3]]
[1] 1 2 5 7
[[4]]
[1] 1 3 4 7
[[5]]
[1] 1 3 5 6
[[6]]
[1] 2 3 4 6
> all_partitions[,has_no_duplicate]
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 9 8 7 7 6 6
[2,] 3 4 5 4 5 4
[3,] 2 2 2 3 3 3
[4,] 1 1 1 1 1 2