0

Say I have $5$ non-negative integers $a,b,c,d,e$.
I need $a+b+c+d+e=s$. I'd like to find a way get all possible sets of answers. E.g. $[10,0,0,0,0], [9,1,0,0,0]$, etc. I was thinking of brute forcing it, but that's getting annoying & complicated fast. Is there a better/cleaner way to generate these sets? The only restriction is that I need to get ALL possibilities.

Would also appreciate if you can suggest any more tags if you don't know the answer.

woogie
  • 124

4 Answers4

1

Since you seem to be interested in generating the solutions in the least "brute force" way, here's a different approach to the one I gave earlier that works by iteration rather recursion. This python generator will highly efficiently (and lazily) generate all of the partitions of length $n$ that sum to $s$:

def partitions(n, s):
    a = [s] + [0]*(n-1) # start with a = [s,0,0, ..., 0]
    while True:
        yield list(a)
        # now we find the successor of a
        # find the left-most non-zero element
        k = 0
        while a[k] == 0:
            k += 1
        if k==n-1:
            # we have reached the last iteration [0,0,..., s]
            # so this will trigger a StopIteration exception
            return
        a[k+1] += 1
        a[0] = a[k]-1
        if k>0:
            a[k] = 0

But since this is math.stackexchange, I should formalize the mathematical analysis :).

Let $P$ be the set of all sequences of $n$ non-negative integers that sum to $s$.

Let $>$ be the lexicographic ordering on $P$, going from right to left: if $a_{n-1} > b_{n-1}$ then $a > b$; if $a_{n-1} < b_{n-1}$ then $a<b$; otherwise $a_{n-1} = b_{n-1}$ and we move on to comparing $a_{n-2}$ and $b_{n-2}$; and so on.

This is a linear order; the minimal element being $[s, 0, 0, ..., 0]$ and the maximal element being $[0, 0, ..., 0, s]$.

So given some $a \in P$, we want to find the successor $succ(a) = b$ in the linear order - i.e., the unique element $b$ s.t. $\forall c \in P, c > a \rightarrow c \geq b$.

Let $k$ be the smallest index such that $a_k > 0$.

Consider the set $A = \{ b \in P \mid i>k \rightarrow b_i = a_i\}$. $a$ is maximal in this set, since for $b \in A$, we must have $\sum_{i=0}^{k}b_i = a_k$; and thus if any $b_i>0$ for $i<k$, we must have $b_k<a_k$.

Next define the set $B = \{b \in P \mid b_{k+1} = a_{k+1}+1, i>k+1 \rightarrow b_i = a_i\}$. If $b \in B$, then $b > a$; and if $b \in B, c \notin B$ and $b>a, c>a$, then $c>b$; so $succ(a) \in B$.

Therefore $succ(a)$ is the smallest element of $B$; which is defined by:

$$b_0 = a_k-1$$ $$ 0<i\leq k \rightarrow b_i = 0$$ $$ b_{k+1} = a_{k+1}+1$$ $$ i>k+1 \rightarrow b_i = a_i$$

However, since for all $i<k$, $a_i = 0$ by definition of $k$, in our algorithm we can get away with just changing potentially three elements, in place: $a_{k+1}, a_0$, and (if $k>0$), $a_k$.

Chas Brown
  • 1,660
0

Since you write $a+b+c+d+e = s = 10$,(say),
I take it that 10+0+0+0+0 is different from 0+10+0+0+0

This is like putting 10 identical balls ("stars") in 5 distinct boxes with the +'s acting as dividers ("bars"), a standard "stars and bars" problem which you can look up if you need to.

One solution could be $\huge{\boxed.+\boxed{\circ\circ}+\boxed{\circ\circ\circ} +\boxed. + \boxed{ \circ\circ\circ\circ\circ}}$,

indicating a distribution of $0,2,3,0,5$ in the $5$ boxes

Note that the the # of +'s ("bars") is always $1$ less than the # of boxes

The only thing we need to decide is where to put the four +'s in the string of $10+4$, thus $\binom{14}{4}$

For $s$ balls and $5$ boxes, the formula would be $\dbinom{s+5-1}{5-1}$

0

In general for $n$ you have the complicated problem called partition of a natural integer $n$. You have the generating function of $p(n)$; $n=0,1,2,3....$ given by the formula (due to Euler): $$\sum_{n=0}^{\infty}p(n)x^n=\prod_{k=1}^{\infty}\left(\frac{1}{1-x^k}\right)$$ so you have in the RHS the product $$(1+x+x^2+.....+x^n+...)(1+x^2+...+x^{2n}+...)(1+x^3+...+x^{3n}+...)....$$ and you can calculate for $p(5)=7$ In fact you have the seven possibilities $$5\\4+1\\3+2\\3+1+1\\2+2+1\\2+1+1+1\\1+1+1+1+1$$

You have besides the sequence $A000041$ in $OEIS$ where there are a lot of $p(n)$

Piquito
  • 29,594
0

If order matters, and you want an algorithm to generate all the possible results, you can use a recursion like this:

Let $f(n,s)$ be the set of sequences of length $n$ whose (non-negative) elements sum to $s$.

$$f(1, s) = \{[s]\}$$ $$f(n, s) = \bigcup_{i=0}^{s}\bigcup_{a \in f(n-1, s-i)}[a_0, a_1, ..., a_{n-1}, i]$$

In python:

def f(n,s):
    if n==1:
        return [[s]]
    else:
       parts = []
       for i in range(s+1):
           for a in f(n-1, s-i):
               parts.append(a + [i])
       return parts

Basically: the set of sequences of length $n$ that sum to $s$ and end with $i$ is the set of sequences of length $n-1$ that sum to $s-i$, with $i$ tacked onto the end. Lather, rinse, repeat!

EDIT: Note that if $n$ or $s$ are large, you can 'memoize' the above function; so that once you've calculated $f(a,b)$ once, you don't need to recalculate it (which will save some time at the expense of space).

Chas Brown
  • 1,660