Turning 38 into 2: How to Solve the Add Digits Problem
Tags: leetcode, javascript, algorithms, codenewbie
Published: 2020-06-23 17:35:31

Today's algorithm is the [Add Digits Problem](https://leetcode.com/problems/add-digits/):
> Given a non-negative integer num, repeatedly add all its digits until the result has only one digit.

For example, if you were given the number 38, you'd add its digits 3 + 8, getting 11. Because 11 is not a single-digit number, we'd add the digits again, so we'd do 1 + 1, getting 2, which is our result.

In math, this is called the ['Digital Root'](https://en.wikipedia.org/wiki/Digital_root), and there is a specific algorithm you can use to solve the problem. However, since memorizing algorithms is not a great way to understand problems and build on concepts, I'll instead approach this problem using while loops and modulo.

## Approaching the Add Digits Problem
I want to approach this problem by using modulo. Modulo (%) is an operator which returns the remainder after dividing one number by another. For example, `10 % 3` would give us the result of 1, because 10/3 is 3, remainder 1. I like using modulo in these kinds of problems because combining modulo 10 (`%10`) with division enables us to separate the digits in a number.

To illustrate what I mean, we can use an example. Let's say we're given the number 15, and we wanted to separate the 1 and 5.
```
  let number = 15
  number % 10    // this gives us 5
  Math.floor(num / 10)    // this gives us 1
```

In this problem, we want to separate the digits and add them, and keep doing that as long as the sum is more than 1 digit. There are two main processes that are repeated in this approach: summing the digits, and separating the digits. We want to repeat both of these processes a number of times, and therefore we'll want to have nested while loops. The outer while loop will keep executing as long as the result we're working with is greater than or equal to 10 (a.k.a., it's not a single digit). The inner while loop will keep executing as long as the numbers still can be separated, which means as long as the number we're working with is greater than 0.

## Coding the Solution to the Add Digits Problem
We'll start by setting up the nested for loops that we discussed in the approach above.

```javascript
function addDigits(num) {
  while (num >= 10) {
    //...
    while (num > 0) {
      //...
    }
  }
  //...
}
```

Inside the first while loop, we'll initialize a variable called `sum`, setting it equal to 0. Each time we start this while loop, we'll want to reset the sum equal to 0.

```javascript
function addDigits(num) {
  while (num >= 10) {
    let sum = 0;
    while (num > 0) {
      //...
    }
    //...
  }
  //...
}
```

Now, inside the inner while loop is where we split `num` into its separate digits using modulo and division. We'll add the last digit of `num` to `sum` using `num % 10`, and then we'll modify `num` using division to effectively remove the last digit.

```javascript
function addDigits(num) {
  while (num >= 10) {
    let sum = 0;
    while (num > 0) {
      sum += num % 10;
      num = Math.floor(num / 10);
    }
    //...
  }
  //...
}
```

When the inner while loop is done executing for the first time, we have the sum of the digits the first time we split them. However, it's very possible that this sum will be a number greater than or equal to 10, in which case we'll need to go through the loop again. Therefore, we'll set `num` equal to `sum`, and the loop may execute again.

Finally, outside of of the larger while loop, we'll return `num`.

```javascript
function addDigits(num) {
  while (num >= 10) {
    let sum = 0;
    while (num > 0) {
      sum += num % 10;
      num = Math.floor(num / 10);
    }
    num = sum;
  }
  return num;
}
```

## Going Through an Example

Let's say we're given the number 38. First, we'll ask: is `num` greater than or equal to 10? It is, so  we'll enter the larger while loop, where we will immediately set `sum` equal to 0.

![In blue, `num = 38`. In green, `38 >= 0`. In orange, `sum = 0`.](https://dev-to-uploads.s3.amazonaws.com/i/586n6d260qppk8k6vww4.png)

Now we're met with the second while loop. Is 38 greater than 0? It is, so we'll enter the while loop. We'll do `38%10`, which gives us 8, and add it to `sum`, so `sum` equals 8. We'll also set `num` equal to `Math.floor(38/10)`, which is 3.

![In purple, `38 > 0`. In orange, `sum += 38 % 10 = 8`. In blue, `num = Math.floor(38 / 10) = 3`.](https://dev-to-uploads.s3.amazonaws.com/i/hqpwtfj28sctt614xrqg.png)

Now we've executed the inner while loop for the first time. Num is 3, which is greater than 0, so we'll execute the inner while loop again. We'll do `3%10`, which gives us 3, and add that to `sum`, making `sum` equal 11. We'll also set `num` equal to `Math.floor(3/10)`, which is 0.

![In purple, `3 > 0`. In orange, `sum += 3 % 10 = 11`. In blue, `num = Math.floor(3 / 10) = 0`.](https://dev-to-uploads.s3.amazonaws.com/i/f8jimuoyhofyus1umr9v.png)

We've executed the inner while loop a second time. This time, num = 0, so we won't execute it again. We can now set `num` equal to `sum`, so `num = 11`.

![In blue, `num = sum = 11`.](https://dev-to-uploads.s3.amazonaws.com/i/ihzq8g5qamzfmtvkm6fy.png)

Now we can look at the outer while loop again. Is `num` greater than or equal to 10? Yes, so we'll enter the outer while loop again. We'll set `sum` equal to 0 again.

![In green `11 >= 10`. In orange, `sum = 0`.](https://dev-to-uploads.s3.amazonaws.com/i/xw2wnqo85kqg0xwpgvkg.png)

Is `num`, which is 11, greater than 0? Yes, so we'll enter the inner while loop again. We'll do `num%10`, which is 1, and add that to `sum`, making `sum = 1`. We'll also modify `num`, and set it equal to `Math.floor(11/10)`, which is 1.

![In purple, `11 > 0`. In orange, `sum += 11 % 10 = 1`. In blue, `num = Math.floor(11 / 10) = 1`.](https://dev-to-uploads.s3.amazonaws.com/i/jx0o6bhqa4gg1fdffdai.png)

We've executed the inner while loop once, so now we can check: is `num`, which is 1, greater than 0? Yes, so we'll enter the inner while loop again. Again, we'll do `num%10`, which is `1%10`, which is 1, and add it to `sum`, giving us `sum = 2`. We'll then set `num` equal to `Math.floor(1/10)`, which is 0.

![In purple, `1 > 0`. In orange, `sum += 1 % 10 = 2`. In blue, `num = Math.floor(1 / 10) = 0`.](https://dev-to-uploads.s3.amazonaws.com/i/8fj3lp7izkricgvywmd2.png)

We've executed the inner while loop, but this time `num = 0`, so we won't execute it again. So, we can set `num = sum`, which means `num = 2`.

![In blue `num = sum = 2`.](https://dev-to-uploads.s3.amazonaws.com/i/le8sjp91mjwh7esrbm5h.png)

We'll check if we should go through the outer while loop again by asking, is `num >=10`? Since `num` is 2, that's not true, so we won't enter the while loop again. Therefore, we'll just return `num`, which is 2.

--
Let me know if you have any questions or alternative solutions!