thzinc

# sumEveryOther - Interview question of the week from rendezvous with cassidoo

This was a fun, light interview question this week.

## Interview question of the week

This week’s question: Given a number, sum every second digit in that number.

Example:

``````> sumEveryOther(548915381)
> 26 // 4+9+5+8

> sumEveryOther(10)
> 0

> sumEveryOther(1010.11)
> 1 // 0+0+1
``````

## My solution

My first pass at answering this question was to just accomplish the thing quickly and see how well it performs.

`#mocha`

```
function sumEveryOther(num) {
const str = num.toString().replace(/\D+/, "");
let acc = 0;
for (let i = 0; i < str.length; i++) {
if (i % 2 === 0) continue;
const c = str[i];
acc += parseInt(c, 10);
}

return acc;
}

mocha.setup("bdd");
const assert = chai.assert;
const expect = chai.expect;
const should = chai.should();

describe("Given the examples from the question", () => {
const expectations = [
{ input: 548915381, output: 26, because: "4, 9, 5, and 8" },
{ input: 10, output: 0, because: "0" },
{ input: 1010.11, output: 1, because: "0, 0, and 1" },
];
expectations.forEach(({ input, output, because }) => {
it(`should return \${output} for the number \${input} because the expected digits are \${because}`, () => {
sumEveryOther(input).should.equal(output);
});
});
});

mocha.run();

```

I figured there might be a faster way than using regular expressions and calling `parseInt()` for each qualifying digit, so I took another pass that made use of the UTF-8/ASCII values of the characters in the number string.

`#mocha`

```
const ZERO_CHAR_CODE = "0".charCodeAt(0);
const NINE_CHAR_CODE = "9".charCodeAt(0);
function sumEveryOther(num) {
const str = num.toString();
let acc = 0;
let skip = true;
for (let i = 0; i < str.length; i++) {
const c = str.charCodeAt(i);
if (c < ZERO_CHAR_CODE || NINE_CHAR_CODE < c) {
continue;
}

if (skip) {
skip = false;
continue;
}

skip = true;
acc += c - ZERO_CHAR_CODE;
}

return acc;
}

mocha.setup("bdd");
const assert = chai.assert;
const expect = chai.expect;
const should = chai.should();

describe("Given the examples from the question", () => {
const expectations = [
{ input: 548915381, output: 26, because: "4, 9, 5, and 8" },
{ input: 10, output: 0, because: "0" },
{ input: 1010.11, output: 1, because: "0, 0, and 1" },
];
expectations.forEach(({ input, output, because }) => {
it(`should return \${output} for the number \${input} because the expected digits are \${because}`, () => {
sumEveryOther(input).should.equal(output);
});
});
});

mocha.run();

```

I tested both implementations and included a rudimentary performance test where the function is called 1,000,000 times with random numbers:

`#mocha`

```
mocha.setup("bdd");
const assert = chai.assert;
const expect = chai.expect;
const should = chai.should();

describe("When comparing an optimized implementation to an unoptimized implementation", () => {
const maxIterations = 1_000_000;
const unoptimized = getUnoptimized();
const optimized = getOptimized();

const results = [];
for (const subject of [unoptimized, optimized]) {
const start = performance.now();
for (let i = 0; i < maxIterations; i++) {
const rand = (Math.random() * 1_000_000_000_000) / 1_000_000;
subject(rand);
}
const end = performance.now();
results.push(end - start);
}
const [unoptimizedElapsedTimeMs, optimizedElapsedTimeMs] = results;

it("should be faster", () => {
optimizedElapsedTimeMs.should.be.below(unoptimizedElapsedTimeMs);
});
});

mocha.run();

// Glue...
function getUnoptimized(){
function sumEveryOther(num) {
const str = num.toString().replace(/\D+/, "");
let acc = 0;
for (let i = 0; i < str.length; i++) {
if (i % 2 === 0) continue;
const c = str[i];
acc += parseInt(c, 10);
}

return acc;
}

return sumEveryOther;}
function getOptimized(){
const ZERO_CHAR_CODE = "0".charCodeAt(0);
const NINE_CHAR_CODE = "9".charCodeAt(0);
function sumEveryOther(num) {
const str = num.toString();
let acc = 0;
let skip = true;
for (let i = 0; i < str.length; i++) {
const c = str.charCodeAt(i);
if (c < ZERO_CHAR_CODE || NINE_CHAR_CODE < c) {
continue;
}

if (skip) {
skip = false;
continue;
}

skip = true;
acc += c - ZERO_CHAR_CODE;
}

return acc;
}

return sumEveryOther;}
```