From cf27b9727fe2035ac07147e222056511f8ab765c Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 08:33:23 +0100 Subject: [PATCH 01/13] Update fix/median.js to make tests pass --- Sprint-1/fix/median.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index b22590bc6..71aa3115e 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -6,9 +6,23 @@ // or 'list' has mixed values (the function is expected to sort only numbers). function calculateMedian(list) { - const middleIndex = Math.floor(list.length / 2); - const median = list.splice(middleIndex, 1)[0]; - return median; + // return null if it is not an array + if (!Array.isArray(list)) return null; + + // filter only numbers from array and sort the filtered array. If no numbers return null + const numbers = list + .filter((item) => typeof item === "number") + .sort((a, b) => a - b); + if (numbers.length === 0) return null; + + // get numbers array mid point + const middleIndex = Math.floor(numbers.length / 2); + // check if numbers array length is even + const isEven = numbers.length % 2 === 0; + // calculate median based on whether the numbers array length is even or odd + return isEven + ? (median = (numbers[middleIndex - 1] + numbers[middleIndex]) / 2) + : numbers[middleIndex]; } module.exports = calculateMedian; From fe3b212dea6f16ef5bf429348a71babf3f607607 Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 10:46:09 +0100 Subject: [PATCH 02/13] Write tests for implement/dedupe.test.js --- Sprint-1/implement/dedupe.test.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index d7c8e3d8e..46e918a0f 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -16,13 +16,29 @@ E.g. dedupe([1, 2, 1]) returns [1, 2] // Given an empty array // When passed to the dedupe function // Then it should return an empty array -test.todo("given an empty array, it returns an empty array"); +test("given an empty array, it returns an empty array", () => { + expect(removeDuplicates([])).toEqual([]); +}); // Given an array with no duplicates // When passed to the dedupe function // Then it should return a copy of the original array +test("given an array with no duplicates, it returns the original array", () => { + expect(removeDuplicates([4, 5, 6])).toEqual([4, 5, 6]); +}); // Given an array of strings or numbers // When passed to the dedupe function -// Then it should return a new array with duplicates removed while preserving the +// Then it should return a new array with duplicates removed while preserving the // first occurrence of each element from the original array. +test("given a number array with duplicates, it returns a new array without duplicates", () => { + expect(removeDuplicates([1, 2, 3, 2, 3])).toEqual([1, 2, 3]); +}); + +test("given a string array with duplicates, it returns a new array without duplicates", () => { + expect(removeDuplicates(["a", "a", "b", "c"])).toEqual(["a", "b", "c"]); +}); + +test("given a mixed array with duplicates, it returns a new array without duplicates", () => { + expect(removeDuplicates([1, "a", "a", "b", "c"])).toEqual([1, "a", "b", "c"]); +}); From 8478b484c0997613ca2a91a50ad29ce956be2d34 Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 10:50:15 +0100 Subject: [PATCH 03/13] Complete implement/dedupe.js - all tests pass --- Sprint-1/implement/dedupe.js | 11 ++++++++++- Sprint-1/implement/dedupe.test.js | 10 +++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 781e8718a..8e7cd5116 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1 +1,10 @@ -function dedupe() {} +function dedupe(array) { + // return empty array if empty input + if (array.length === 0) return []; + // check if array has duplicates + const hasDuplicates = new Set(array).size !== array.length; + // if no duplicates return original array else return new array with duplicates removed (string or numbers) + return !hasDuplicates ? array : [...new Set(array)]; +} + +module.exports = dedupe; diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index 46e918a0f..03d21bfe1 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -17,14 +17,14 @@ E.g. dedupe([1, 2, 1]) returns [1, 2] // When passed to the dedupe function // Then it should return an empty array test("given an empty array, it returns an empty array", () => { - expect(removeDuplicates([])).toEqual([]); + expect(dedupe([])).toEqual([]); }); // Given an array with no duplicates // When passed to the dedupe function // Then it should return a copy of the original array test("given an array with no duplicates, it returns the original array", () => { - expect(removeDuplicates([4, 5, 6])).toEqual([4, 5, 6]); + expect(dedupe([4, 5, 6])).toEqual([4, 5, 6]); }); // Given an array of strings or numbers @@ -32,13 +32,13 @@ test("given an array with no duplicates, it returns the original array", () => { // Then it should return a new array with duplicates removed while preserving the // first occurrence of each element from the original array. test("given a number array with duplicates, it returns a new array without duplicates", () => { - expect(removeDuplicates([1, 2, 3, 2, 3])).toEqual([1, 2, 3]); + expect(dedupe([1, 2, 3, 2, 3])).toEqual([1, 2, 3]); }); test("given a string array with duplicates, it returns a new array without duplicates", () => { - expect(removeDuplicates(["a", "a", "b", "c"])).toEqual(["a", "b", "c"]); + expect(dedupe(["a", "a", "b", "c"])).toEqual(["a", "b", "c"]); }); test("given a mixed array with duplicates, it returns a new array without duplicates", () => { - expect(removeDuplicates([1, "a", "a", "b", "c"])).toEqual([1, "a", "b", "c"]); + expect(dedupe([1, "a", "a", "b", "c"])).toEqual([1, "a", "b", "c"]); }); From c8c55994768d71910aece48e1c7fcb127bbb4684 Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 11:04:41 +0100 Subject: [PATCH 04/13] Update numbers filter in fix/median.js --- Sprint-1/fix/median.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index 71aa3115e..aa22d1175 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -11,7 +11,7 @@ function calculateMedian(list) { // filter only numbers from array and sort the filtered array. If no numbers return null const numbers = list - .filter((item) => typeof item === "number") + .filter((item) => typeof item === "number" && Number.isFinite(item)) .sort((a, b) => a - b); if (numbers.length === 0) return null; From d73f09c4009f0aec2ccd8d204a0b1806948d4885 Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 11:17:19 +0100 Subject: [PATCH 05/13] Write tests for implement/max.test.js --- Sprint-1/implement/max.test.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/Sprint-1/implement/max.test.js b/Sprint-1/implement/max.test.js index 82f18fd88..c424243f9 100644 --- a/Sprint-1/implement/max.test.js +++ b/Sprint-1/implement/max.test.js @@ -16,28 +16,45 @@ const findMax = require("./max.js"); // When passed to the max function // Then it should return -Infinity // Delete this test.todo and replace it with a test. -test.todo("given an empty array, returns -Infinity"); +test("given an empty array, returns -Infinity", () => { + expect(findMax([])).toBe(-Infinity); +}); // Given an array with one number // When passed to the max function // Then it should return that number - +test("given an array with one number, returns that number", () => { + expect(findMax([2])).toBe(2); +}); // Given an array with both positive and negative numbers // When passed to the max function // Then it should return the largest number overall - +test("given an array with positive and negative numbers, returns largest overall number", () => { + expect(findMax([5, -3, 15])).toBe(15); +}); // Given an array with just negative numbers // When passed to the max function // Then it should return the closest one to zero +test("given an array with negative numbers, returns number closest to zero", () => { + expect(findMax([-5, -3, -15])).toBe(-3); +}); // Given an array with decimal numbers // When passed to the max function // Then it should return the largest decimal number +test("given an array with decimal numbers, returns largest decimal number", () => { + expect(findMax([10.5, 2.6, 8.1])).toBe(10.5); +}); // Given an array with non-number values // When passed to the max function // Then it should return the max and ignore non-numeric values - +test("given a mixed array with non-number values, returns largest number and ignore non-numbers", () => { + expect(findMax([7, 3, "hello", "#"])).toBe(7); +}); // Given an array with only non-number values // When passed to the max function // Then it should return the least surprising value given how it behaves for all other inputs +test("given an array of non-number values, returns -Infinity", () => { + expect(findMax(["#", "hello", "?"])).toBe(-Infinity); +}); From 752c5304f0944ff691392aa736459d404331964b Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 19:54:11 +0100 Subject: [PATCH 06/13] Complete implement/max.js - all tests pass --- Sprint-1/implement/max.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 6dd76378e..451e00b91 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,4 +1,16 @@ function findMax(elements) { + // return -Infinity for empty array or if array only contains non-numbers + // filter, sort array in ascending order and return last value in the array + // array with one number - return one number + // array with positive and negative numbers, return largest number + // array with negative numbers return the one closest to zero + // array with decimal numbers return the one with the largest decimal + // mixed array - ignore non-numbers and return largest number + + // filter to return only numbers or an empty array + const numbers = elements.filter((item) => Number.isFinite(item)); + // if numbers present in array return largest number or return -Infinity for empty array + return numbers.length ? Math.max(...numbers) : -Infinity; } module.exports = findMax; From 8dad701b4bfa409da7cb6b187ce395bb86a4cb18 Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 20:12:37 +0100 Subject: [PATCH 07/13] Complete implement/sum.js - all tests pass --- Sprint-1/implement/sum.js | 4 ++++ Sprint-1/implement/sum.test.js | 23 +++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 9062aafe3..11ff75dcb 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,4 +1,8 @@ function sum(elements) { + // filter out the numbers and sum them up + return elements + .filter((item) => Number.isFinite(item)) + .reduce((acc, num) => acc + num, 0); } module.exports = sum; diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index dd0a090ca..2cc159e93 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -13,24 +13,39 @@ const sum = require("./sum.js"); // Given an empty array // When passed to the sum function // Then it should return 0 -test.todo("given an empty array, returns 0") +test("given an empty array, returns 0", () => { + expect(sum([])).toBe(0); +}); // Given an array with just one number // When passed to the sum function // Then it should return that number +test("given an array with one number, returns the number", () => { + expect(sum([1])).toBe(1); +}); // Given an array containing negative numbers // When passed to the sum function // Then it should still return the correct total sum - +test("given an array of only negative numbers, returns the sum", () => { + expect(sum([-1, -2])).toBe(-3); +}); // Given an array with decimal/float numbers // When passed to the sum function // Then it should return the correct total sum - +test("given an array with decimal/float numbers, returns the sum", () => { + expect(sum([2, 3.5, 4])).toBe(9.5); +}); // Given an array containing non-number values // When passed to the sum function -// Then it should ignore the non-numerical values and return the sum of the numerical elements +// Then it should ignore the non-numerical values and return the sum of the numerical +test("given an array containing non-number values, returns sum of number values", () => { + expect(sum([5, "#", "hello", 2])).toBe(7); +}); // Given an array with only non-number values // When passed to the sum function // Then it should return the least surprising value given how it behaves for all other inputs +test("given an array of non-number values, returns 0", () => { + expect(sum(["#", "hello"])).toBe(0); +}); From e91162d95ddec05f8a1ab511b3f5cb42ade911ee Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 20:13:53 +0100 Subject: [PATCH 08/13] Update implement/max.js --- Sprint-1/implement/max.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 451e00b91..5d81cb063 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,12 +1,4 @@ function findMax(elements) { - // return -Infinity for empty array or if array only contains non-numbers - // filter, sort array in ascending order and return last value in the array - // array with one number - return one number - // array with positive and negative numbers, return largest number - // array with negative numbers return the one closest to zero - // array with decimal numbers return the one with the largest decimal - // mixed array - ignore non-numbers and return largest number - // filter to return only numbers or an empty array const numbers = elements.filter((item) => Number.isFinite(item)); // if numbers present in array return largest number or return -Infinity for empty array From 40aa890d408b949dfe2eb7d939af7b4c1379b7bf Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 20:21:42 +0100 Subject: [PATCH 09/13] Refactored refactor/includes.js --- Sprint-1/refactor/includes.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 29dad81f0..158c8ac96 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,13 +1,7 @@ // Refactor the implementation of includes to use a for...of loop function includes(list, target) { - for (let index = 0; index < list.length; index++) { - const element = list[index]; - if (element === target) { - return true; - } - } - return false; + return list.includes(target); } module.exports = includes; From be1cf59022e5187eaa8e6ebdd75cc685b471428d Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 20:24:38 +0100 Subject: [PATCH 10/13] Updated refactor/includes.js to use for of loop --- Sprint-1/refactor/includes.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 158c8ac96..9373ad463 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,7 +1,10 @@ // Refactor the implementation of includes to use a for...of loop function includes(list, target) { - return list.includes(target); + for (const number of list) { + if (number === target) return true; + } + return false; } module.exports = includes; From e6bb904411128ce71d8dc6448543d455bbfb19e5 Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Mon, 6 Jul 2026 21:22:14 +0100 Subject: [PATCH 11/13] Complete solution on stretch/aoc-2018-day1/solution.js --- Sprint-1/stretch/aoc-2018-day1/solution.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Sprint-1/stretch/aoc-2018-day1/solution.js b/Sprint-1/stretch/aoc-2018-day1/solution.js index e69de29bb..5e76650dd 100644 --- a/Sprint-1/stretch/aoc-2018-day1/solution.js +++ b/Sprint-1/stretch/aoc-2018-day1/solution.js @@ -0,0 +1,14 @@ +const fs = require("fs"); +const path = require("path"); +const data = fs.readFileSync(path.join(__dirname, "input.txt"), "utf-8"); +const total = data + .split("\n") + .map((line) => line.trim()) + .filter((line) => line !== "") + .map(Number); + +const mapFrequency = (changes) => changes.reduce((acc, num) => acc + num, 0); +console.log(mapFrequency([+1, +1, +1])); // 3 +console.log(mapFrequency([+1, +1, -2])); // 0 +console.log(mapFrequency([-1, -2, -3])); // -6 +console.log(mapFrequency(total)); // 529; From 43561d7133910213fafa8e3889402f8b8d9a9174 Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Thu, 16 Jul 2026 20:31:27 +0100 Subject: [PATCH 12/13] Refactor dedupe.js --- Sprint-1/implement/dedupe.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 8e7cd5116..921c7e6e4 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1,10 +1,7 @@ function dedupe(array) { // return empty array if empty input if (array.length === 0) return []; - // check if array has duplicates - const hasDuplicates = new Set(array).size !== array.length; - // if no duplicates return original array else return new array with duplicates removed (string or numbers) - return !hasDuplicates ? array : [...new Set(array)]; + return Array.from(new Set(array)); } module.exports = dedupe; From b98a26cf426d2bb987a87bbaf3236566169d029b Mon Sep 17 00:00:00 2001 From: Martin Mwaka Date: Thu, 16 Jul 2026 20:39:22 +0100 Subject: [PATCH 13/13] Refactor median.js to remove inFinite --- Sprint-1/fix/median.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index aa22d1175..71aa3115e 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -11,7 +11,7 @@ function calculateMedian(list) { // filter only numbers from array and sort the filtered array. If no numbers return null const numbers = list - .filter((item) => typeof item === "number" && Number.isFinite(item)) + .filter((item) => typeof item === "number") .sort((a, b) => a - b); if (numbers.length === 0) return null;