DEV Community

Cover image for Solving the Digital Root Algorithm using JavaScript
isabel k.
isabel k.

Posted on β€’ Edited on

20 5

Solving the Digital Root Algorithm using JavaScript

One of my favorite algorithms is finding the digital root of any given integer. A digital root is a single-digit sum that is reached when you iteratively add up the digits that make up a number.

For example:

666
=> 6 + 6 + 6
=> 18
=> 1 + 8 
=> 9
Enter fullscreen mode Exit fullscreen mode

The key to solving this algorithm is to use an iterative method. The solution has to be smart enough to keep executing as long as the returned sum is higher than a single-digit number.

The approach

  1. If our given integer is greater than 9, iterate through each digit in the number.
  2. Add up each digit.
  3. Assess if the sum is a single-digit number.
  4. If not, go back to Step 1.

Let's break it down

1) Create a variable for the sum. Set it to equal the given integer. If this integer is a single-digit number, we'll return it at the very end without mutating it.

function digitalRoot(number) {
   let sum = number
}
Enter fullscreen mode Exit fullscreen mode

2) Write a conditional statement to execute something on the sum if it's a multi-digit number.

function digitalRoot(number) {
   let sum = number
   if (sum > 9) {
      // execute something here
   }
}
Enter fullscreen mode Exit fullscreen mode

3) If the number is greater than 9, turn it into an array so that we can loop through it. In JavaScript, we have to turn the integer into a string, and then call the split() method on it to achieve this.

function digitalRoot(number) {
   let sum = number
   let arr = []

   if (sum > 9) {
      arr = sum.toString().split("")
      console.log(arr) 
   }
}

digitalRoot(24)
=> ["2", "4"]
Enter fullscreen mode Exit fullscreen mode

4) Now let's iterate through the array and sum its elements. We can use the reduce() method for this. reduce() requires a reducer method to execute on, so let's write the logic for it and pass it into reduce(). Inside the reducer method, convert the values into an integer by wrapping each value in parseInt. Since this method will return a single value, we can reassign it to our sum variable.

function digitalRoot(number) {
   let sum = number
   let arr = []
   let reducer = (a,b) => parseInt(a) + parseInt(b)

   if (sum > 9) {
      arr = sum.toString().split("")
      sum = arr.reduce(reducer)
      console.log(sum) 
   }
}

digitalRoot(24)
=> 6
Enter fullscreen mode Exit fullscreen mode

Et voilΓ ! We've solved the algorithm!
...Just kidding. It totally breaks if we pass in any larger numbers.

digitalRoot(666)
=> 18
Enter fullscreen mode Exit fullscreen mode

So how can we keep executing our function while the sum is a multi-digit number?

5) Instead of a conditional if statement, let's use a while loop. The while loop will run while a condition is true, whereas an if statement will just execute once. Let's also move our console.log statement to the end of the function, outside of the loop, so that it only returns a single value.

function digitalRoot(number) {
   let sum = number
   let arr = []
   let reducer = (a,b) => parseInt(a) + parseInt(b)

   while (sum > 9) {
      arr = sum.toString().split("")
      sum = arr.reduce(reducer)
   }

   console.log(sum) 
}

digitalRoot(666)
=> 9
Enter fullscreen mode Exit fullscreen mode

Conclusion

This is one of my favorite algorithms because it's not the most difficult to solve, but still poses an interesting problem. Sound off in the comments if you have a different way of solving this!

Edits made after publishing

Changed the wording in this article because I originally talked about using a recursive solution, but ended up writing just an iterative one. Thanks for all the comments! ✨

Image of Stellar post

Check out Episode 1: How a Hackathon Project Became a Web3 Startup πŸš€

Ever wondered what it takes to build a web3 startup from scratch? In the Stellar Dev Diaries series, we follow the journey of a team of developers building on the Stellar Network as they go from hackathon win to getting funded and launching on mainnet.

Read more

Top comments (15)

Collapse
 
kdraypole profile image
Kobe Raypole β€’

Very cool! I'm a Ruby enthusiast so I tried it out in that.

Your Iterative strategy was great but I think using recursion could help reduce some of the complexity and make for some cleaner code.

def d_root(num)
  return num if num < 10

  d_root(num.to_s.split('').reduce(0) {|acc, digit| acc + digit.to_i}) 
end

Ruby gives us some great helpers for integers so we can simplify this even more.

def d_root(num)
  return num if num < 10

  d_root(num.digits.sum) 
end

Nice and simple!

Collapse
 
khuongduybui profile image
Duy K. Bui β€’

Can I cheat?

function d_root(num) {
  return (num % 9) || 9;
}
Enter fullscreen mode Exit fullscreen mode

:D

Collapse
 
pavi2410 profile image
Pavitra Golchha β€’

I am really curious how do you know this?

Collapse
 
khuongduybui profile image
Duy K. Bui β€’

I learnt it first as a math trick for children in Vietnam: to know if something is divisible by 9, you calculate its digitial root and see if the digital root is divisible by 9 (same goes for 3).

When I grew up, I was curious and tried to prove that mathematically, which is how I ended up with digitalRoot(num) = num % 9 (or 9 if divisible by 9) :D

Collapse
 
terkwood profile image
Felix Terkhorn β€’

mathworld.wolfram.com/DigitalRoot....

Looking good in this corner of the thread!

Collapse
 
athul7744 profile image
Athul Anil Kumar β€’

Amazing intuition!

Collapse
 
keltroth profile image
Django Janny β€’

What about d_root(0) ?

Collapse
 
kushal-niroula profile image
Kushal Niroula β€’

Are we sure this is a recursive approach? I feel like this is an iterative solution as we just run a block until a condition is met. The function is not called multiple times.

function dRoot(num) {
  const parts = num.toString().split("");
  const sum = parts.reduce((aggr,part) => parseInt(part) + parseInt(aggr));
  if(sum > 9) return dRoot(sum);
  return sum;
}

I think this qualifies as recursive. But the iterative approach in the article is much more performant I think. Nice article.

Collapse
 
ph1p profile image
Phil β€’

Thank you! I like those tiny little programming "snacks" :)


shortest (recursion) solution I could find:

const dr = r => r < 10 ? r : dr([...r+''].reduce((b,c) => +b+(+c)));

dr(129); // 3
Collapse
 
darthbob88 profile image
Raymond Price β€’

Cool demo, but that's not actually recursion, that's just iteration. An actual recursive solution, if you wanted to do that for some strange reason, would look more like

function digitalRoot(number) {
   let arr = number.toString().split("");
   let reducer = (a,b) => parseInt(a) + parseInt(b);
   let sum = arr.reduce(reducer)

   if (sum > 9) {
       return digitalRoot(sum);
   } else {
       return sum;
   }
}

Also, sidenote, this function does break on very large numbers. That's not OP's fault, that's because Javascript can't reasonably represent things like 1234567891234567891234567891 as an integer. digitalRoot("1234567891234567891234567891") works just fine, though

Collapse
 
luigidcapra profile image

function F_iRoot(P_sz0){
var sz0 = "" + P_sz0;
var iLen = sz0.length;
var iNum;
var ch;
var iSum = 0;
for (var i=0; i < iLen; i++) {
ch = sz0.charCodeAt(i);
iNum = ch - 48; // '0' = 0x30 = 48
iSum += iNum;
} /* for /
if (iSum > 9) {
iSum = F_iRoot(iSum);
} /
if /
return(iSum);
} /
F_iRoot */

Collapse
 
sylwiavargas profile image
Sylwia Vargas β€’

I love this post! You explain it all so well! Are you planning on creating an algo series?

Collapse
 
ali_7099ad9b604224fb9c8ac profile image
Ali β€’
function digitalRoot(n) {
  return (n - 1) % 9 + 1;
}

Enter fullscreen mode Exit fullscreen mode
Collapse
 
gudimba profile image
Austin Imbastari β€’

thank you so much omg

Collapse
 
sabyrcpu profile image
sabyr-cpu β€’

The better solution I think:

function digital_root(n) {
return (n - 1) % 9 + 1;
}

Image of Stellar post

Check out Episode 1: How a Hackathon Project Became a Web3 Startup πŸš€

Ever wondered what it takes to build a web3 startup from scratch? In the Stellar Dev Diaries series, we follow the journey of a team of developers building on the Stellar Network as they go from hackathon win to getting funded and launching on mainnet.

Read more

πŸ‘‹ Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay