0

Question:

Write a function called sumDigits.

Given a number, sumDigits returns the sum of all its digits.

var output = sumDigits(1148);
console.log(output); // --> 14

If the number is negative, the first digit should count as negative.

var output = sumDigits(-316);
console.log(output); // --> 4

This is what I currently have coded and it works for positive values but I can't wrap my head around how to tackle the problem when given a negative value. When -316 is put into the function, NaN is returned and I understand that when I toString().split('') the number, this is what is returned: ['-', '3', '1', '6']. How do I deal with combining index 0 and 1?

function sumDigits(num) {
  var total = 0;
  var newString = num.toString().split('');
  for (var i = 0; i < newString.length; i ++) {
    var converted = parseInt(newString[i]);
    total += converted;
  }
  return total;
}

sumDigits(1148);

Any hints on what methods I should be using? and is there a smarter way to even look at this?

Community
  • 1
  • 1
jalexyep
  • 89
  • 8
  • Looks good to me. You could make "reduce" the code using the reduce method to add the digits together. – evolutionxbox Mar 18 '17 at 19:51
  • Splitting `'-316'` gives you `['-', '3', '1', '6']` - so you would need to look out for a `'-'` character and negate the following digit. A cleaner approach IMHO would be parsing the whole given string as a number and then use Math.log10 to extract the digits. You will find such approaches already on StackOverflow. – le_m Mar 18 '17 at 19:52
  • 1
    If you're going to use a string representation, then all you'd need to do is check for the `-` before the loop, and if it's there, consume it and the next number, and set `total` to that negative value. –  Mar 18 '17 at 19:52
  • While your question is implementation specific, also note the answers given to a similar task here: http://stackoverflow.com/questions/41926762/retrun-sum-of-a-number-positive-or-negative – le_m Mar 18 '17 at 19:54
  • Thanks for the feedback – jalexyep Mar 18 '17 at 19:57
  • Here's a version that doesn't require any string conversion: https://jsfiddle.net/ngho5d94/ –  Mar 18 '17 at 20:14

5 Answers5

1

This should do it:

    function sumDigits(num) {
      var total = 0;
      var newString = num.toString().split('');
      for (var i = 0; i < newString.length; i ++) {
        if(newString[i]==='-') { //check to see if the first char is -
          i++; //if it is, lets move to the negative number
          var converted =  parseInt(newString[i]); // parse negative number
          total -= converted; // subtract value from total
          continue; // move to the next item in the loop
        }
        var converted = parseInt(newString[i]);
        total += converted;
      }
      return total;
    }

console.log(sumDigits(-316));
OctoCode
  • 382
  • 4
  • 14
  • Could you walk me through this part? `if(newString[i]==='-') { i++; var converted = parseInt(newString[i]); total -= converted; continue;` I am not sure what the `i++` is doing and why `total -= converted` is needed. Thanks for the answer. – jalexyep Mar 18 '17 at 20:04
  • i++ is incrementing the counter, since first character is minus sign. After that we are subtracting negative value instead of adding it to the total. – OctoCode Mar 18 '17 at 20:05
  • OOOH okay everything just clicked. Appreciate the help! – jalexyep Mar 18 '17 at 20:43
1

One way to do this, is to do a split that will keep the minus and the first digit together, not split.

You can do that with a regular expression, and use match instead of split:

var newString = num.toString().match(/-?\d/g);

function sumDigits(num) {
  var total = 0;
  var newString = num.toString().match(/-?\d/g);
  for (var i = 0; i < newString.length; i++) {
    var converted = parseInt(newString[i]);
    total += converted;
  }
  return total;
}

var result = sumDigits(-316);
console.log(result);

In a bit shorter version, you could use map and reduce, like this:

function sumDigits(num) {
  return String(num).match(/-?\d/g).map(Number).reduce( (a, b) => a+b );
}

console.log(sumDigits(-316));
trincot
  • 317,000
  • 35
  • 244
  • 286
1

You could always use String#replace with a function as a parameter:

function sumDigits (n) {
  var total = 0
  n.toFixed().replace(/-?\d/g, function (d) {
    total += +d
  })
  return total
}

console.log(sumDigits(-1148)) //=> 14
gyre
  • 16,369
  • 3
  • 37
  • 47
  • That's a nice, short approach, but you're not handling the negative number as described in the question. If you change your regex to `/-?\d/g`, it'll work. –  Mar 18 '17 at 20:05
  • Sorry, I meant that the requirement in the question is that if the number is negative, then the first digit should be subtracted from the total. Your code does indeed calculate a total, but the result isn't what the OP was after. –  Mar 18 '17 at 20:13
  • 1
    Oh, that is a surprising requirement! I'll update the example. – gyre Mar 18 '17 at 20:14
0

Is there a smarter way to even look at this?

You can avoid the conversion from number to string and back by using the modulo operator to extract the last digit. Repeat this step until you got all digits:

function sumDigits(num) {
  let total = 0, digit = 0;
  while (num != 0) {
    total += digit = num % 10;
    num = (num - digit) * 0.1;
  }
  return total < 0 ? digit + digit - total : total;
}

console.log(sumDigits(-316));                    // 4
console.log(sumDigits(1148));                    // 14
console.log(sumDigits(Number.MAX_SAFE_INTEGER)); // 76
le_m
  • 19,302
  • 9
  • 64
  • 74
0
function sumDigits(num) {
  let string = num.toString();
  let zero = 0;
  let total = 0;
  for (var i = 0; i < string.length; i++) {
    if (Math.sign(num) === 1) {
      total = zero += Number(string[i]);
    } else {
            for (var i = 2; i < string.length; i++) {
            total = (zero += Number(string[i])) - Number(string[1]);
      }
            }
  }
  return total;
}
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 14 '22 at 09:35