3

Im solving a codewars problem and im pretty sure i've got it working:

function digital_root(n) {
    // ...
    n = n.toString();
    if (n.length === 1) {
        return parseInt(n);
    } else {
        let count = 0;
        for (let i = 0; i < n.length; i++) {
            //console.log(parseInt(n[i]))
            count += parseInt(n[i]);
        }
        //console.log(count);
        digital_root(count);
    }
}

console.log(digital_root(942));

Essentially it's supposed to find a "digital root":

A digital root is the recursive sum of all the digits in a number. Given n, take the sum of the digits of n. If that value has two digits, continue reducing in this way until a single-digit number is produced. This is only applicable to the natural numbers.

So im actually getting the correct answer at the end but for whatever reason on the if statement (which im watching the debugger run and it does enter that statement it will say the return value is the correct value.

But then it jumps out of the if statement and tries to return from the main digital_root function?

Why is this? shouldn't it break out of this when it hits the if statement? Im confused why it attempt to jump out of the if statement and then try to return nothing from digital_root so the return value ends up being undefined?

0

3 Answers 3

10

You're not returning anything inside else. It should be:

return digital_root(count);
^^^^^^^

Why?

digital_root is supposed to return something. If we call it with a one digit number, then the if section is executed, and since we return from that if, everything works fine. But if we provide a number composed of more than one digit then the else section get executed. Now, in the else section we calculate the digital_root of the count but we don't use that value (the value that should be returned). The line above could be split into two lines of code that makes it easy to understand:

var result = digital_root(count); // get the digital root of count (may or may not call digital_root while calculating it, it's not owr concern)
return result;                    // return the result of that so it can be used from the caller of digital_root
Sign up to request clarification or add additional context in comments.

2 Comments

Crap, im not super used to using recursion. I guess....can you explain why we return this? Is it because your returning the value from the "future" to itself "now" i guess?
@msmith1114 Check the explanation! I hope it's useful.
2

Code review

My remarks is code comments below

// javascript generally uses camelCase for function names
// so this should be digitalRoot, not digital_root
function digital_root(n) {
    // variable reassignment is generally frowned upon
    // it's somewhat silly to convert a number to a string if you're just going to parse it again
    n = n.toString();
    if (n.length === 1) {
        // you should always specify a radix when using parseInt
        return parseInt(n);
    } else {
        let count = 0;
        for (let i = 0; i < n.length; i++) {
            //console.log(parseInt(n[i]))
            count += parseInt(n[i]);
        }
        // why are you looping above but then using recursion here?
        // missing return keyword below
        digital_root(count);
    }
}

console.log(digital_root(942));

Simple recursive solution

With some of those things in mind, let's simplify our approach to digitalRoot...

const digitalRoot = n =>
  n < 10 ? n : digitalRoot(n % 10 + digitalRoot((n - n % 10) / 10))
  
console.log(digitalRoot(123))         //          => 6
console.log(digitalRoot(1234))        //       10 => 1
console.log(digitalRoot(12345))       //       15 => 6
console.log(digitalRoot(123456))      //       21 => 3
console.log(digitalRoot(99999999999)) // 99 => 18 => 9


Using reduce

A digital root is the recursive sum of all the digits in a number. Given n, take the sum of the digits of n. If that value has two digits, continue reducing in this way until a single-digit number is produced. This is only applicable to the natural numbers.

If you are meant to use an actual reducing function, I'll show you how to do that here. First, we'll make a toDigits function which takes an integer, and returns an Array of its digits. Then, we'll implement digitalRoot by reducing those those digits using an add reducer initialized with the empty sum, 0

// toDigits :: Int -> [Int]
const toDigits = n =>
  n === 0 ? [] :  [...toDigits((n - n % 10) / 10), n % 10]

// add :: (Number, Number) -> Number
const add = (x,y) => x + y

// digitalRoot :: Int -> Int
const digitalRoot = n =>
  n < 10 ? n : digitalRoot(toDigits(n).reduce(add, 0))
      
console.log(digitalRoot(123))         //          => 6
console.log(digitalRoot(1234))        //       10 => 1
console.log(digitalRoot(12345))       //       15 => 6
console.log(digitalRoot(123456))      //       21 => 3
console.log(digitalRoot(99999999999)) // 99 => 18 => 9

Comments

0

its a recursive function the code should be somewhat like this

function digital_root(n) {
    // ...
    n=n.toString();
    if(n.length === 1){
         return parseInt(n);
    }
    else
    {
    let count = 0;
    for(let i = 0; i<n.length;i++)
    {
    //console.log(parseInt(n[i]))
    count+=parseInt(n[i]);
    }
   //console.log(count);
   return digital_root(count);
   }
}

you should return the same function instead of just calling it to get the correct call stack

4 Comments

why are you using a loop and recursion? in this case, it's pretty much one or the other – that's beside the point anyway; your function returns 9 for digital_root(123123123) but should return 18
well the question was why its returning undefined instead of a value , i just corrected recursive part portion of the code
and for your next question please see this link for what is digital root thonky.com/nine-hours-nine-persons-nine-doors/digital-root digital_root(123123123) = 9 and not 18 if i got the digital root concept right.if i am wrong i apologies ,please share your view on digital roots
you are correct. I have mistaken digital root as the simple sum of the digits. thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.