diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index b22590bc6..ad7aa50ef 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -6,9 +6,29 @@ // 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; + if (!Array.isArray(list)) { + return null; + } + const arrCopy = [...list]; + const filteredNumbers = arrCopy.filter((num) => Number.isFinite(num)); + + if (filteredNumbers.length === 0) { + return null; + } + + const sortedNumbers = filteredNumbers.sort((a, b) => a - b); + let middleIndex; + if (sortedNumbers.length % 2 === 0) { + middleIndex = sortedNumbers.length / 2; + const firstMiddleIndex = sortedNumbers[middleIndex - 1]; + const secondMiddleIndex = sortedNumbers[middleIndex]; + return (firstMiddleIndex + secondMiddleIndex) / 2; + } else { + middleIndex = Math.floor(sortedNumbers.length / 2); + return sortedNumbers[middleIndex]; + } } +// console.log(calculateMedian([100, 2, 3, 'f', 4, 9, 9, 0, "hey", 'g'])) + module.exports = calculateMedian; diff --git a/Sprint-1/fix/median.test.js b/Sprint-1/fix/median.test.js index 21da654d7..43ce21ec6 100644 --- a/Sprint-1/fix/median.test.js +++ b/Sprint-1/fix/median.test.js @@ -1,6 +1,6 @@ // median.test.js -// Someone has implemented calculateMedian but it isn't +// Someone has implemented calculateMedian, but it isn't // passing all the tests... // Fix the implementation of calculateMedian so it passes all tests @@ -13,7 +13,8 @@ describe("calculateMedian", () => { { input: [1, 2, 3, 4], expected: 2.5 }, { input: [1, 2, 3, 4, 5, 6], expected: 3.5 }, ].forEach(({ input, expected }) => - it(`returns the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) + it(`returns the median for [${input}]`, () => + expect(calculateMedian(input)).toEqual(expected)) ); [ @@ -24,7 +25,8 @@ describe("calculateMedian", () => { { input: [110, 20, 0], expected: 20 }, { input: [6, -2, 2, 12, 14], expected: 6 }, ].forEach(({ input, expected }) => - it(`returns the correct median for unsorted array [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) + it(`returns the correct median for unsorted array [${input}]`, () => + expect(calculateMedian(input)).toEqual(expected)) ); it("doesn't modify the input array [3, 1, 2]", () => { @@ -33,8 +35,17 @@ describe("calculateMedian", () => { expect(list).toEqual([3, 1, 2]); }); - [ 'not an array', 123, null, undefined, {}, [], ["apple", null, undefined] ].forEach(val => - it(`returns null for non-numeric array (${val})`, () => expect(calculateMedian(val)).toBe(null)) + [ + "not an array", + 123, + null, + undefined, + {}, + [], + ["apple", null, undefined], + ].forEach((val) => + it(`returns null for non-numeric array (${val})`, () => + expect(calculateMedian(val)).toBe(null)) ); [ @@ -45,6 +56,7 @@ describe("calculateMedian", () => { { input: [3, "apple", 1, null, 2, undefined, 4], expected: 2.5 }, { input: ["banana", 5, 3, "apple", 1, 4, 2], expected: 3 }, ].forEach(({ input, expected }) => - it(`filters out non-numeric values and calculates the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) + it(`filters out non-numeric values and calculates the median for [${input}]`, () => + expect(calculateMedian(input)).toEqual(expected)) ); }); diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 781e8718a..b286e24e2 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1 +1,9 @@ -function dedupe() {} +function dedupe(elements) { + if (elements.length === 0) { + return []; + } + + return elements.filter((item, index) => elements.indexOf(item) === index); +} + +module.exports = dedupe; diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index d7c8e3d8e..9b742930b 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -16,13 +16,46 @@ 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, return an empty array", () => { + 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 +const testCaseNoDuplicates = [ + { + input: ["hey", "buddy", "world", "10", "sister", 1], + expected: ["hey", "buddy", "world", "10", "sister", 1], + }, + { + input: [2, 3, 4, 5, 6, 7], + expected: [2, 3, 4, 5, 6, 7], + }, +]; +testCaseNoDuplicates.forEach(({ input, expected }) => { + test("given an array with no duplicates, return a copy of the array", () => { + expect(dedupe(input)).toEqual(expected); + }); +}); // 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. +const testCaseWithDuplicates = [ + { input: [1, 2, 2, 3, 1], expected: [1, 2, 3] }, + { input: ["a", "b", "a", "c", "b"], expected: ["a", "b", "c"] }, + { input: [5, 5, 1, 1, 2, 3, 2], expected: [5, 1, 2, 3] }, + { + input: ["apple", "banana", "apple", "orange"], + expected: ["apple", "banana", "orange"], + }, + { input: [1, "a", 1, "b", "a", 2], expected: [1, "a", "b", 2] }, + { input: ["hey", "hey", "hey", "hey", "hey", "hey"], expected: ["hey"] }, +]; +testCaseWithDuplicates.forEach(({ input, expected }) => { + test("given an array with duplicates, return a new array with only the first occurrence", () => { + expect(dedupe(input)).toEqual(expected); + }); +}); diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 6dd76378e..1e6383a9f 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,4 +1,23 @@ function findMax(elements) { + if (elements.length === 0) { + return -Infinity; + } + const elementLists = elements.filter((number) => { + return typeof number === "number"; + }); + if (elementLists.length === 0) { + return undefined; + } + if (elementLists.length === 1) { + return elementLists[0]; + } + let max = elementLists[0]; + for (let i = 1; i < elementLists.length; i++) { + if (elementLists[i] > max) { + max = elementLists[i]; + } + } + return max; } - +console.log(findMax([-1, 0, -2])); module.exports = findMax; diff --git a/Sprint-1/implement/max.test.js b/Sprint-1/implement/max.test.js index 82f18fd88..e11ca7ecf 100644 --- a/Sprint-1/implement/max.test.js +++ b/Sprint-1/implement/max.test.js @@ -15,29 +15,93 @@ const findMax = require("./max.js"); // Given an empty array // 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([])).toEqual(-Infinity); +}); // Given an array with one number // When passed to the max function // Then it should return that number +const testCaseArrayWithOneNumber = [ + { input: [4], expected: 4 }, + { input: [5], expected: 5 }, + { input: [10], expected: 10 }, +]; +testCaseArrayWithOneNumber.forEach(({ input, expected }) => { + test("given an array with one number, returns that number", () => { + expect(findMax(input)).toEqual(expected); + }); +}); // Given an array with both positive and negative numbers // When passed to the max function // Then it should return the largest number overall +const testCaseArrayWithPositiveAndNegativeNumbers = [ + { input: [-5, 3, -10, 8, 2, -1], expected: 8 }, + { input: [-20, 15, -3, 7, -100, 4], expected: 15 }, + { input: [-1, -50, 0.5, -2, -10], expected: 0.5 }, +]; +testCaseArrayWithPositiveAndNegativeNumbers.forEach(({ input, expected }) => { + test("given a mix of positive and negative number, returns the largest number overall", () => { + expect(findMax(input)).toEqual(expected); + }); +}); // Given an array with just negative numbers // When passed to the max function // Then it should return the closest one to zero +const testCaseArrayWithOnlyNegativeNumbers = [ + { input: [-5, -3, -10, -8, -2, -1], expected: -1 }, + { input: [-20, -15, -3, -7, -100, -4], expected: -3 }, + { input: [-1, -50, -0.5, -2, -10], expected: -0.5 }, +]; + +testCaseArrayWithOnlyNegativeNumbers.forEach(({ input, expected }) => { + test("given negative numbers, returns the closest number to zero", () => { + expect(findMax(input)).toEqual(expected); + }); +}); // Given an array with decimal numbers // When passed to the max function // Then it should return the largest decimal number +const testCaseArrayWithOnlyDecimalNumbers = [ + { input: [1.5, 3.7, 2.4, 8.9, 4.2], expected: 8.9 }, + { input: [0.2, 0.8, 0.1, 0.6, 0.4], expected: 0.8 }, + { input: [-1.5, -3.2, -0.7, -5.6, -2.1], expected: -0.7 }, +]; +testCaseArrayWithOnlyDecimalNumbers.forEach(({ input, expected }) => { + test("given decimal numbers, returns the largets decimal number", () => { + expect(findMax(input)).toEqual(expected); + }); +}); // Given an array with non-number values // When passed to the max function // Then it should return the max and ignore non-numeric values +const testCaseArrayWithNonNumberValues = [ + { input: [5, "hello", 10, null, 3], expected: 10 }, + { input: ["world", -5, 8, undefined, 2], expected: 8 }, + { input: [true, 4, false, 12, "hey"], expected: 12 }, + { input: [-10, "hello", -2, null, -20], expected: -2 }, + { input: [2.5, {}, 7.8, [], "test"], expected: 7.8 }, +]; +testCaseArrayWithNonNumberValues.forEach(({ input, expected }) => { + test("given an array including non-numerical values, returns the max and ignore non-numeric values", () => { + expect(findMax(input)).toEqual(expected); + }); +}); // 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 +const testCaseArrayWithOnlyNonNumberValues = [ + { input: ["hello", "world"], expected: undefined }, + { input: [null, undefined, true, false], expected: undefined }, + { input: [{}, [], "test"], expected: undefined }, +]; +testCaseArrayWithOnlyNonNumberValues.forEach(({ input, expected }) => { + test("given an array with only non-number values, returns undefined", () => { + expect(findMax(input)).toEqual(expected); + }); +}); diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 9062aafe3..dbd58428e 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,4 +1,17 @@ function sum(elements) { + if (elements.length === 0) { + return 0; + } + const elementsList = elements.filter((element) => { + return typeof element === "number"; + }); + if (elementsList.length === 1) { + return elementsList[0]; + } + let sum = 0; + for (let i = 0; i < elementsList.length; i++) { + sum += elementsList[i]; + } + return sum; } - module.exports = sum; diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index dd0a090ca..e89cd9e63 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -13,24 +13,74 @@ 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 zero", () => { + expect(sum([])).toEqual(0); +}); // Given an array with just one number // When passed to the sum function // Then it should return that number +test("given an array of one number, returns number", () => { + expect(sum([7])).toEqual(7); +}); // Given an array containing negative numbers // When passed to the sum function // Then it should still return the correct total sum +const testCaseNegativeNumbers = [ + { input: [-1, -2, -3], expected: -6 }, + { input: [-5, -10, -15], expected: -30 }, + { input: [-20, -8, -12], expected: -40 }, + { input: [-100, -50, -75], expected: -225 }, +]; +testCaseNegativeNumbers.forEach(({ input, expected }) => { + test("given an array of negative numbers, returns total sum", () => { + expect(sum(input)).toBeCloseTo(expected); + }); +}); // Given an array with decimal/float numbers // When passed to the sum function // Then it should return the correct total sum - +const testCaseDecimalNumbers = [ + { input: [1.5, 2.7, 3.2], expected: 7.4 }, + { input: [4.25, 6.75, 8.5], expected: 19.5 }, + { input: [0.5, 1.25, 2.75], expected: 4.5 }, + { input: [-1.5, -2.25, -3.75], expected: -7.5 }, +]; +testCaseDecimalNumbers.forEach(({ input, expected }) => { + test("given an array of decimal numbers, returns total sum", () => { + expect(sum(input)).toBeCloseTo(expected); + }); +}); // 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 +const testCaseNonNumerical = [ + { input: [1, "hello", 2, 3], expected: 6 }, + { input: [5, null, 10, undefined], expected: 15 }, + { input: ["apple", 4, 6, "banana"], expected: 10 }, + { input: [2, true, 3, {}, 5], expected: 10 }, + { input: ["10", 1, 2, 3], expected: 6 }, +]; +testCaseNonNumerical.forEach(({ input, expected }) => { + test("given an array of non-numerical values, return sum of numerical values", () => { + expect(sum(input)).toEqual(expected); + }); +}); // 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 +const testNonNumberValues = [ + { input: ["hello", "world"], expected: 0 }, + { input: [null, undefined], expected: 0 }, + { input: [true, false, "apple"], expected: 0 }, + { input: [{}, "10", null], expected: 0 }, + { input: ["apple", null, undefined, false], expected: 0 }, +]; +testNonNumberValues.forEach(({ input, expected }) => { + test("given an array of non number values, return zero", () => { + expect(sum(input)).toEqual(expected); + }); +}); diff --git a/Sprint-1/package-lock.json b/Sprint-1/package-lock.json index 83e427d0b..542194aa0 100644 --- a/Sprint-1/package-lock.json +++ b/Sprint-1/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { - "jest": "^29.7.0" + "jest": "^29.7.0", + "prettier": "3.9.6" } }, "node_modules/@ampproject/remapping": { @@ -3195,6 +3196,22 @@ "node": ">=8" } }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", diff --git a/Sprint-1/package.json b/Sprint-1/package.json index 330755010..115159cd9 100644 --- a/Sprint-1/package.json +++ b/Sprint-1/package.json @@ -10,6 +10,7 @@ "author": "", "license": "ISC", "devDependencies": { - "jest": "^29.7.0" + "jest": "^29.7.0", + "prettier": "3.9.6" } } diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 29dad81f0..9a02dbcf7 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,13 +1,21 @@ // Refactor the implementation of includes to use a for...of loop +//my comments +//make a copy of the array +//check if target is in the array function includes(list, target) { - for (let index = 0; index < list.length; index++) { - const element = list[index]; - if (element === target) { - return true; + const targetFoundInArr = []; + for (const li of list) { + if (li === target) { + targetFoundInArr.push(li); } } - return false; + if (targetFoundInArr.length === 0) { + return false; + } + if (targetFoundInArr.length >= 1) { + return true; + } } - +console.log(includes([1, 2, 3, 4, 55, 6, null, 6, 7], 6)); module.exports = includes;