diff --git a/15_totalIntegers/README.md b/15_totalIntegers/README.md new file mode 100644 index 00000000000..48d09cda822 --- /dev/null +++ b/15_totalIntegers/README.md @@ -0,0 +1,8 @@ +# Exercise 15 - totalIntegers + +Write a function that takes in an arbitrarily deep array or object and returns the total number of integers stored inside this array or object. + +```javascript +totalIntegers([[[5], 3], 0, 2, ['foo'], [], [4, [5, 6]]]); // returns 7 +totalIntegers({ a: 1, b: { a: [5, 10], b: 11 } }); // returns 4 +``` diff --git a/15_totalIntegers/solution/totalIntegers-solution.js b/15_totalIntegers/solution/totalIntegers-solution.js new file mode 100644 index 00000000000..7ba19766cad --- /dev/null +++ b/15_totalIntegers/solution/totalIntegers-solution.js @@ -0,0 +1,24 @@ +// The extra null check is required since typeof null === "object" evaluates to true +const isObject = (value) => typeof value === 'object' && value !== null; + +const totalIntegers = function (obj) { + let count = 0; + + if (!isObject(obj)) { + return; + } + + const elements = Object.values(obj); + + for (const el of elements) { + if (Number.isInteger(el)) { + count++; + } else if (isObject(el)) { + count += totalIntegers(el); + } + } + return count; +}; + +// Do not edit below this line +module.exports = totalIntegers; diff --git a/15_totalIntegers/solution/totalIntegers-solution.spec.js b/15_totalIntegers/solution/totalIntegers-solution.spec.js new file mode 100644 index 00000000000..19676196061 --- /dev/null +++ b/15_totalIntegers/solution/totalIntegers-solution.spec.js @@ -0,0 +1,40 @@ +const totalIntegers = require('./totalIntegers-solution'); + +describe('totalIntegers', () => { + test('Works with a simple array of numbers', () => { + expect(totalIntegers([1, 2, 3])).toBe(3); + }); + test('Ignores non-integer values', () => { + expect(totalIntegers([1, 2, '3', 4])).toBe(3); + }); + test('Works with simple objects', () => { + expect(totalIntegers({ a: 1, b: '2', c: 3 })).toBe(2); + }); + test('Works with an empty nested array', () => { + expect(totalIntegers([[], [], []])).toBe(0); + }); + test('Works with a very nested array', () => { + expect(totalIntegers([[[[[[[[[[[[[[4]]]]]], 246]]]]]]]])).toBe(2); + }); + test('Works with negative numbers', () => { + expect(totalIntegers([5, 7, -7, [45, -1, -0], [4, 7, -4, -4, -4, [777777, -45674]], [-5477654]])).toBe(14); + }); + test('Works with floats', () => { + expect(totalIntegers([5, 7.7, 7, [45, 1, 0], [4.0, 7, [7.77777, 4567.4]], [5477.654]])).toBe(7); + }); + test('Only accepts arrays or objects', () => { + expect(totalIntegers('2')).toBe(undefined); + expect(totalIntegers(() => {})).toBe(undefined); + expect(totalIntegers(42)).toBe(undefined); + expect(totalIntegers(NaN)).toBe(undefined); + }); + test('Works with NaN', () => { + expect(totalIntegers([5, NaN, [NaN, NaN, 64], 4])).toBe(3); + }); + test('Works with a nested array of all kinds of things', () => { + expect(totalIntegers([NaN, [[{}], 555 ], '444', [], 74.0, undefined, [[() => {}], [4], Infinity, [[[], -44.0], [null, '-4'], NaN [[]], 6]], () => {}, [[], [-Infinity, ['4'], [4.7, -46.7], NaN]]])).toBe(5); + }); + test('Works with arrays containing objects containing integers', () => { + expect(totalIntegers([4, 6, { a: 1, b: { a: [5, 10], b: 11 } }, 9])).toBe(7); + }); +}); diff --git a/15_totalIntegers/totalIntegers.js b/15_totalIntegers/totalIntegers.js new file mode 100644 index 00000000000..d4c24861530 --- /dev/null +++ b/15_totalIntegers/totalIntegers.js @@ -0,0 +1,6 @@ +const totalIntegers = function() { + +}; + +// Do not edit below this line +module.exports = totalIntegers; diff --git a/15_totalIntegers/totalIntegers.spec.js b/15_totalIntegers/totalIntegers.spec.js new file mode 100644 index 00000000000..d33d2293d30 --- /dev/null +++ b/15_totalIntegers/totalIntegers.spec.js @@ -0,0 +1,50 @@ +const totalIntegers = require('./totalIntegers'); + +describe('totalIntegers', () => { + test('Works with a simple array of numbers', () => { + expect(totalIntegers([1, 2, 3])).toBe(3); + }); + + test.skip('Ignores non-integer values', () => { + expect(totalIntegers([1, 2, '3', 4])).toBe(3); + }); + + test.skip('Works with simple objects', () => { + expect(totalIntegers({ a: 1, b: '2', c: 3 })).toBe(2); + }); + + test.skip('Works with an empty nested array', () => { + expect(totalIntegers([[], [], []])).toBe(0); + }); + + test.skip('Works with a very nested array', () => { + expect(totalIntegers([[[[[[[[[[[[[[4]]]]]], 246]]]]]]]])).toBe(2); + }); + + test.skip('Works with negative numbers', () => { + expect(totalIntegers([5, 7, -7, [45, -1, -0], [4, 7, -4, -4, -4, [777777, -45674]], [-5477654]])).toBe(14); + }); + + test.skip('Works with floats', () => { + expect(totalIntegers([5, 7.7, 7, [45, 1, 0], [4.0, 7, [7.77777, 4567.4]], [5477.654]])).toBe(7); + }); + + test.skip('Only accepts arrays or objects', () => { + expect(totalIntegers('2')).toBe(undefined); + expect(totalIntegers(() => {})).toBe(undefined); + expect(totalIntegers(42)).toBe(undefined); + expect(totalIntegers(NaN)).toBe(undefined); + }); + + test.skip('Works with NaN', () => { + expect(totalIntegers([5, NaN, [NaN, NaN, 64], 4])).toBe(3); + }); + + test.skip('Works with a nested array of all kinds of things', () => { + expect(totalIntegers([NaN, [[{}], 555 ], '444', [], 74.0, undefined, [[() => {}], [4], Infinity, [[[], -44.0], [null, '-4'], NaN [[]], 6]], () => {}, [[], [-Infinity, ['4'], [4.7, -46.7], NaN]]])).toBe(5); + }); + + test.skip('Works with arrays containing objects containing integers', () => { + expect(totalIntegers([4, 6, { a: 1, b: { a: [5, 10], b: 11 } }, 9])).toBe(7); + }); +});