1

For base $b = 10$, I want to list all numbers with $d$ digits (no leading zeros) and digit sum $x$, in increasing order.

For example for $d = 6$ and $x = 40$ we would get:

139999, 148999, 149899, 149989, 149998, 157999, 158899, 158989, 158998, 159799, 159889, 159898, 159979, 159988, 159997, 166999, 167899, 167989, 167998, 168799, 168889, 168898, 168979, 168988, 168997, 169699, 169789, 169798, 169879, 169888, 169897, 169969, 169978, 169987, 169996, 175999, 176899, 176989, 176998, 177799, 177889, 177898, 177979, 177988, 177997, 178699, 178789, 178798, 178879, 178888, 178897, 178969, 178978, 178987, 178996, 179599, 179689, 179698, 179779, 179788, 179797, 179869, 179878, 179887, 179896, 179959, 179968, 179977, 179986, 179995, 184999, 185899, 185989, 185998, 186799, 186889, 186898, 186979, 186988, 186997, 187699, 187789, 187798, 187879, 187888, 187897, 187969, 187978, 187987, 187996, 188599, 188689, 188698, 188779, 188788, 188797, 188869, 188878, 188887, 188896, 188959, 188968, 188977, 188986, 188995, 189499, 189589, 189598, 189679, 189688, ...

Now, using the generalized stars-bars problem creating a program, which produces an unordered list is easy. But for large $d$ and $x \rightarrow d \cdot b/2$, the list gets huge, so sorting it needs lots of RAM and it gets pretty slow.

I suspect (hope) there exists a ready-made algorithm, that for a number $n$ gives the nearest number $n'$, so that $n'$ has the same digit sum as $n$. Could you give me a hint?


EDIT: This is my solution in Python so far. The function returns the next integer with the same digit sum. I tested it for quite a huge range of numbers. But I don't know if it is correct. If you find an error, please let me know.
def next_same_xsum(x):
    BASE = 10
    t = 1
    u = 1
    while x % (u * BASE) == 0:
        u *= BASE
    if u > 1:
        y = next_same_xsum(x // u)
        w = 1

        while x // u // (w * BASE) < y // (w * BASE):
            w *= BASE
        s = y % w
        return s + (y - s) * u
    while x // (t * BASE * BASE) < (x + BASE - 1) // (t * BASE * BASE):
        t *= BASE

    if t > 1:
        z = next_same_xsum(x // t)
        r = BASE - x % BASE - 1
        return t - 1 + (z - r) * t

    return x + BASE - 1
viuser
  • 261
  • how about using a recursive function. split the number as a digit (b) followed by a (d - 1) digit number whose sum of digits must be (x - b) allowing 0 – Lozenges Jul 07 '16 at 10:30

1 Answers1

1

Here is an algorithm to find the next number up. We need the following notation: use (d,x) for a d-digit number with digit sum = x (d,x,M) is the largest (d,x) and (d,x,m) is the smallest (d,x)

e.g. 187987 is a (6,40), (2,15,M)=96 and (2,15,m)=69

Suppose we want the next number after 187987. We start with the last two digits:87 it is not maximal so we add 9 to 87 to get the next number: 187996 now the last three digit number 996 is a (3,24,M) in this case add 1 to the previous digit so the 7 becomes an 8. The next number is 188 followed by (3,23,m) that is 188599

Lozenges
  • 1,742
  • an additional problem are the numbers with trailing zeros. – viuser Jul 10 '16 at 04:09
  • 3700 is a (4,10) in which 700 is (3,7,M) so the next step would be to add 1 to the 3 and fill in the remaining with (3,6,m) (here 0 is allowed) to get the next number: 4006 – Lozenges Jul 10 '16 at 07:35