7

Before you mark duplicate note that it isn't. Others didn't look for the exact same thing as me.

What is the most compact possible way to sum up a number in javascript until there is only one digit left. For example: You input 5678 then the script adds it together (5+6+7+8) and gets 26, but since its more than 1 digit it adds it again and gets 2+6=8.

Is there anyway to do this with a number of any size? And how compact can the script get?

VinceKaj
  • 335
  • 4
  • 13

16 Answers16

27

If you're looking for short, it's hard to beat:

var n = 5678;
sum  = n % 9 || 9;

console.log(sum)

If you're curious about how that works, see: casting out nines.

Mark
  • 90,562
  • 7
  • 108
  • 148
8

You can do this using recursion, here is an example:

function getOneDigit(nr){
    let asStr = nr.toString();
    let sum = asStr.split("").reduce((a, c) => {
         a+=parseInt(c);
         return a;
    }, 0);
    return sum >= 10 ? getOneDigit(sum) : sum;
}

[234235, 235346, 657234, 1, 2, 5423].forEach(nr => console.log(getOneDigit(nr)));
Titus
  • 22,031
  • 1
  • 23
  • 33
2

This line of code does this.

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

When you take the modulo of a number with 9, it becomes a 1 less than 9. So, when you have 10%9, you will get 1, which is equal to 1+0.

Similarly, 123%9 = 6.

Why (n-1)%9 and added 1: Because when you input 9, it became 0 so input will be invalid.

For n=9, this method will return (9-1)%9 = 8 and 8+1 = 9.

So it does not break.

You can also write

return n%9 || 9
fonZ
  • 2,428
  • 4
  • 21
  • 40
  • 2
    Please describe, what was the problem and how will this code solve it, to help others understand this answer – FZs Oct 21 '19 at 17:13
2
function createCheckDigit(membershipId) {
     var total = membershipId;
   while (total.length > 1) {
       t = 0;
       for (let i = 0; i < total.length; i++) {
               t = Number(t) + Number(total[i]);
       }
       total = t.toString(); 
   }
   return total;
  }
console.log(createCheckDigit("55555"));
  • When answering an old question, your answer would be much more useful to other StackOverflow users if you included some context to explain how your answer helps, particularly for a question that already has an accepted answer. See: [How do I write a good answer](https://stackoverflow.com/help/how-to-answer). – David Buck Nov 28 '19 at 18:24
1

For a compact way, you could use an iterative and recursive approach.

const d = n => n > 9 ? d([...n.toString()].reduce((a, b) => +a + +b)) : n;

console.log(d(5678));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

You need to check if the length of value (after converting sum to a String) is 1 or not.

var fnSum = (arr) => arr.reduce((a, c) => a + (+c), 0); //function to get sum of values

var fnGetSingleDigit = (arr) => {
  while (arr.length != 1) {
    var sum = fnSum(arr);
    arr = String(sum).split("");
  }
  return arr[0];
};

console.log(fnGetSingleDigit([5, 6, 7, 8]));

console.log(fnGetSingleDigit([41,34,3,54,63,46]));

Demo

var fnSum = (arr) => arr.reduce((a, c) => a + (+c), 0); //function to get sum of values

var fnGetSingleDigit = (arr) => {
  while (arr.length != 1) {
    var sum = fnSum(arr);
    arr = String(sum).split("");
  }
  return arr[0];
};

console.log(fnGetSingleDigit([5, 6, 7, 8]));

console.log(fnGetSingleDigit([41,34,3,54,63,46]));
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
0
function fun(n) {
sum = 0;
while(n > 0 || sum > 9)
    {
        if(n == 0)
        {
            n = sum;
            sum = 0;
        }
        sum = sum+n % 10;
        n = Math.floor(n/10);
    }
    console.log(sum);
}

You can use the above snippet.

Harikesh
  • 152
  • 2
  • 12
0

I did it like this:

function sumOfID(__id){
  var arr_str = Array.from(__id)
  var arr = arr_str.map((t)=>{return parseInt(t)})
  function digSum(__arr){
   return __arr.reduce((a,b)=>{return a + b})
  }
   return digSum(arr)%9 || 9    
 }

Note : The trick here is to use mod9 because the modulo 9 of any multiple digit number is its total sum until it becomes a single digit number.

0
// recursive
    function digitSum(n) {
      return (n % 10 === n) ? n : (digitSum(n.toString().split('').reduce((acc, curr) => acc + parseInt(curr), 0)));
    }

    
        
   function digitSum(n) {
       while(!(n % 10 === n)) {
         n = n.toString().split('').reduce((acc, curr) => acc + parseInt(curr), 0);
       }
      
       return n;
    
    console.log(digitSum(467)); // -> 17 -> 8

basically check if the nums length (digit count length) < 2 (achieved this with n % 10 === n (9 % 10 === 9) or n.toString().length < 2 if NOT then call the function again with calculated digit sum take example 467:

  1. 4 + 6 + 7 = 17 (digit length is not 1) call with 17
  2. 1 + 7 = 8 (digit length is 1) -> return. 2nd version is the same as recursive one, hope this helps!
emre-ozgun
  • 676
  • 1
  • 7
  • 17
  • 1
    While this code may answer the question, providing additional context regarding *how* and/or *why* it solves the problem would improve the answer's long-term value. – Sven Eberth Jul 07 '21 at 22:24
0

const a = [1,2,4,4,5,6,7,7].join('')

function add(i){
  let x = i.toString().split('').reduce((p,c)=>parseInt(p)+parseInt(c))
  x = x.toString().length > 1 ? add(x) : x
  return parseInt(x)
}


console.log(add(a))
-1

Here you go

var number = 56785;
var total = number + '';
    
while(total.length > 1) {
   var temp = 0;
   for(var i = 0; i < total.length; i++) {
       temp += +total[i];
   }
   total = temp + '';
}
    
console.log(total);
Bunyamin Coskuner
  • 8,719
  • 1
  • 28
  • 48
-1

You can also opt to use the forEach loop and a while condition to loop over the stringify number and get the sum until the length is 1.

var num = 5678;
var strNum = num.toString().split('');
while(strNum.length !== 1){
  var strNum = calculateSum(strNum);
  strNum = strNum.split('');
}
var result = parseInt(strNum);
console.log(result);

function calculateSum(strNum){
  var sum = 0;
  strNum.forEach((digit)=>{
    sum += parseInt(digit);
  });
  return sum.toString();
}
Ankit Agarwal
  • 30,378
  • 5
  • 37
  • 62
-1

This is my solution for the same problem on CodeWars

const sumup = (num) => {
   let a = String(num).split('').map((k) => {
     return Number(k);
   }).reduce((p, c) => {
     return p + c;
   }, 0);

   return a > 9 ? sumup(a) : a;
}
Dong Nguyen
  • 1,239
  • 9
  • 17
-1

Here is a recursive solution without using any library!

function getSumOfDigits(num){
  var result = 0;
  while(~~(num/10) > 0){
    result += (num % 10);
    num = ~~(num/10);
  }
  return result + num;
}

function getSingleDigit(num) {
  if(~~(num/10) === 0) {
    return num
  } else {
    num = getSumOfDigits(num);
    return getSingleDigit(num);
  }
}

console.log(getSingleDigit(393));
user3505838
  • 351
  • 3
  • 8
-1

You can combine some utility methods with recursion and do it in two lines that are still pretty readable:

function sumDigits(digits) {
  let sum = Array.from(digits.toString()).map(Number).reduce((res, val) => res + val, 0);
  return sum < 10 ? sum : sumDigits(sum);
}

console.log(sumDigits(55555)) // 5+5+5+5+5 = 25 -> 2+5 = 7
Josh Broadhurst
  • 407
  • 3
  • 14
-1

function doSum(n){
 var temp = n, total= 0;
  for(var i = 0; i < n.toString().length; i++ ){
        total = total + (Math.floor(temp) % 10)
    temp = (temp / 10)
  }
 if(total > 9 ) { return doSum(total) }
return total
}
doSum(999999)
Mohammed Jafar
  • 493
  • 6
  • 4