Ratnabh Kumar Rai
Ratnabh Kumar Rai

Reputation: 584

Recursion running through infinite loop

I just started out with recursion so I was solving a question which is like

Create a function that takes numbers as arguments, adds them together, and returns the product of digits until the answer is only 1 digit long.

sumDigProd(16, 28) ➞ 6
// 16 + 28 = 44
// 4 * 4 =  16
// 1 * 6 = 6

sumDigProd(0) ➞ 0

sumDigProd(1, 2, 3, 4, 5, 6) ➞ 2

so i did it with recursion as

function sumDigProd(...digits) {
  let ans = digits.reduce((a, b) => a + b, 0);
  console.log(ans);
  const result=calc(ans);
 function calc(ans) {
    ans = ans.toString();
    let pro = 1;
    for (let i = 0; i < ans.length; i++) {
      pro = pro * ans[i];
    }
    console.log(pro);
    while (pro > 10) {
      calc(pro);
    }
    return pro
   
  }
  return result
}
console.log(sumDigProd(16,28));

so I am running it in infinite loop

Upvotes: 2

Views: 163

Answers (5)

Mike
Mike

Reputation: 1327

Editorial: I found some of the answers here clever, but harder to follow, below is another example of adding the values, and then multiplying digits if there are multiple


Recursive: Product of Sum's Digits

const sumDigitProduct = (num,...rest)=>{

  if(rest.length)
    num = sumDigitProduct( rest.reduce((agg,cv)=>agg+parseFloat(cv), num) )
  
  const digits = (''+num).split('')
  if( digits.length > 1)
    num = sumDigitProduct( digits.reduce((agg,cv)=>agg*parseFloat(cv)) )
  
  return num;
};


// Tests
console.log('expect: 3; got:', sumDigitProduct(1,2))
console.log('expect: 5; got:', sumDigitProduct(15))
console.log('expect: 6; got:', sumDigitProduct(16,28))
console.log('expect: 0; got:', sumDigitProduct(0))
console.log('expect: 2; got:', sumDigitProduct(1,2,3,4,5,6))

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386550

You could return the result of calling calc for getting a recursive result.

function sumDigProd(...digits) {
    function calc(ans) {
        let pro = [...ans.toString()].reduce((a, b) => a * b);
        return pro > 9 
            ? calc(pro)
            : pro;
    }

    return calc(digits.reduce((a, b) => a + b, 0));
}

console.log(sumDigProd(16, 28)); // 6
console.log(sumDigProd(1, 2, 3, 4, 5, 6)); // 2

Upvotes: 2

trincot
trincot

Reputation: 350137

You did not assign the return value from the recursive call.

Also, you are mixing an iterative solution (with while) with a recursive one. You need one of the two, not both.

For the recursive solution you can just use an if. And in that case you can even immediately return the return value from the recursive call.

Also, the condition should be pro >= 10, as 10 is not OK as a final value:

function sumDigProd(...digits) {
  let ans = digits.reduce((a, b) => a + b, 0);
  console.log(ans);

  function calc(ans) {
    ans = ans.toString();
    let pro = 1;
    for (let i = 0; i < ans.length; i++) {
      pro = pro * ans[i];
    }
    console.log(pro);
    if (pro >= 10) {
      return calc(pro); // recursive case
    }
    return pro; // base case
  }

  return calc(ans);
}
console.log(sumDigProd(16,28));

An iterative solution could be achieved with little change:

function sumDigProd(...digits) {
  let pro = digits.reduce((a, b) => a + b, 0);
  console.log(pro);

  while (pro >= 10) {
    ans = pro.toString();
    pro = 1;
    for (let i = 0; i < ans.length; i++) {
      pro = pro * ans[i];
    }
    console.log(pro);
  }

  return pro;
}
console.log(sumDigProd(16,28));

And crunching the code to a smaller footprint, it could become:

function sumDigProd(...digits) {
  let pro = digits.reduce((a, b) => a + b, 0);
  while (pro >= 10) {
    pro = Array.from(pro.toString()).reduce((a, b) => a * b, 1);
  }
  return pro;
}
console.log(sumDigProd(16,28));

Upvotes: 5

prime_hit
prime_hit

Reputation: 326

A bit shorter version:

function sumDigProd(a, b){

  let rec = function(a) {
    if (String(a).length == 1) return a;
        return rec(String(a).split('').map(Number).reduce((a,b)=>a*b));
  }
   return rec(a+b);
}

Upvotes: 1

Ed Lucas
Ed Lucas

Reputation: 7305

You just need to assign pro and change your while to an if:

function sumDigProd(...digits) {
  let ans = digits.reduce((a, b) => a + b, 0);
  console.log(ans);
  const result=calc(ans);
 function calc(ans) {
    ans = ans.toString();
    let pro = 1;
    for (let i = 0; i < ans.length; i++) {
      pro = pro * ans[i];
    }
    console.log(pro);
    if (pro >= 10) {
      pro = calc(pro);
    }
    return pro

  }
  return result
}
console.log(sumDigProd(16,28,12));

Upvotes: 1

Related Questions