diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index b22590bc6..bee1d7889 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -6,9 +6,18 @@ // 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 numbers = list.filter((e) => typeof e === "number" && !isNaN(e)); + + if (numbers.length === 0) return null; + numbers.sort((a, b) => a - b); + const length = numbers.length; + const middleIndex = Math.floor(length / 2); + if (length % 2 === 0) { + return (numbers[middleIndex - 1] + numbers[middleIndex]) / 2; + } else { + return numbers[middleIndex]; + } } module.exports = calculateMedian; diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 781e8718a..786c89e75 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1 +1,13 @@ -function dedupe() {} +function dedupe(arr) { + if (arr.length === 0) return []; + const dedupeArray = []; + for (let i = 0; i < arr.length; i++) { + if (!dedupeArray.includes(arr[i])) { + dedupeArray.push(arr[i]); + } + } + + return dedupeArray; +} +console.log(dedupe([1, 1, 2])); +module.exports = dedupe; diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index 23e0f8638..42a59ac36 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -1,4 +1,4 @@ -const dedupe = require("./dedupe.js"); +const dedupe = require("./dedupe"); /* Dedupe Array @@ -16,12 +16,56 @@ E.g. dedupe([1, 2, 1]) target output: [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"); +describe("dedupe()", () => { + [{ input: [], expected: [] }].forEach(({ input, expected }) => + it(`given an empty array, it returns an empty array [${input}]`, () => { + expect(dedupe(input)).toStrictEqual(expected); + }) + ); + // Given an array with no duplicates + // Then it should return a copy of the original array + [{ input: [1, 2, 3, 4], expected: [1, 2, 3, 4] }].forEach( + ({ input, expected }) => + it(`should return same input values [${input}] without duplicate`, () => { + expect(dedupe(input)).toStrictEqual(expected); + }) + ); -// Given an array with no duplicates -// When passed to the dedupe function -// Then it should return a copy of the original array + // When passed to the dedupe function + // Given an array with strings or numbers + // When passed to the dedupe function + // Then it should remove the duplicate values, preserving the first occurence of each element -// Given an array with strings or numbers -// When passed to the dedupe function -// Then it should remove the duplicate values, preserving the first occurence of each element + [ + { input: [1, 2, 5, 5, "a", 5, 10, 10, "a"], expected: [1, 2, 5, "a", 10] }, + { + input: ["apple", "banana", "orange", "apple", "banana", 1, 3, 4, 1], + expected: ["apple", "banana", "orange", 1, 3, 4], + }, + ].forEach(({ input, expected }) => + it(`should return deduplicated array for [${input}]`, () => { + expect(dedupe(input)).toStrictEqual(expected); + }) + ); +}); + +test("returns a copy, not the original array", () => { + const input = [1, 1, 2]; + const result = dedupe(input); + + expect(result).toStrictEqual([1, 2]); + expect(result).not.toBe(input); +}); + +it("does not mutate the original array", () => { + const input = [2, 3, 5]; + dedupe(input); + + expect(input).toStrictEqual([2, 3, 5]); +}); + +test("result has only distinct elements", () => { + const result = dedupe([1, 1, 2, 2, 3]); + + expect(new Set(result).size).toBe(result.length); +}); diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 6dd76378e..855261203 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,4 +1,20 @@ function findMax(elements) { + if (!Array.isArray(elements)) return "invalid elements"; + const numberList = []; + for (let i = 0; i < elements.length; i++) { + if (typeof elements[i] === "number" && !Number.isNaN(elements[i])) { + numberList.push(elements[i]); + } + } + if (numberList.length === 0) return -Infinity; + let max = numberList[0]; + + for (let i = 1; i < numberList.length; i++) { + if (max < numberList[i]) { + max = numberList[i]; + } + } + return max; } module.exports = findMax; diff --git a/Sprint-1/implement/max.test.js b/Sprint-1/implement/max.test.js index 82f18fd88..62617c970 100644 --- a/Sprint-1/implement/max.test.js +++ b/Sprint-1/implement/max.test.js @@ -16,28 +16,76 @@ 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"); +describe("findMax()", () => { + [{ input: [], expected: -Infinity }].forEach(({ input, expected }) => + it(`should return ${expected} for empty [${input}]`, () => { + expect(findMax(input)).toEqual(expected); + }) + ); -// Given an array with one number -// When passed to the max function -// Then it should return that number + // Given an array with one number + // When passed to the max function + // Then it should return that number -// Given an array with both positive and negative numbers -// When passed to the max function -// Then it should return the largest number overall + [{ input: [50], expected: 50 }].forEach(({ input, expected }) => + it(`should return ${expected} for array [${input}]`, () => { + 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 + // Given an array with both positive and negative numbers + // When passed to the max function + // Then it should return the largest number overall -// Given an array with decimal numbers -// When passed to the max function -// Then it should return the largest decimal number + [{ input: [2, 5, 6, -1, 0, 25, -30], expected: 25 }].forEach( + ({ input, expected }) => { + it(`should return ${expected} for positive and negative numbers in the array`, () => { + 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 + // Given an array with just negative numbers + // When passed to the max function + // Then it should return the closest one to zero + [{ input: [-1, -10, -7, -20], expected: -1 }].forEach(({ input, expected }) => + it(`should return negative number nearest to zero`, () => { + 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 + // Given an array with decimal numbers + // When passed to the max function + // Then it should return the largest decimal number + + [{ input: [0.5, 0.1, 0.56, 0.8, "1.2"], expected: 0.8 }].forEach( + ({ input, expected }) => + it(`should return the largest decimal number from the array`, () => { + expect(findMax(input)).toBeCloseTo(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 + [ + { + input: ["edak", "ofonime", "", "@", -4, 10, 6, 50, -100, "300"], + expected: 50, + }, + ].forEach(({ input, expected }) => + it(`should return max numerical value from the array`, () => { + 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 + [{ input: ["peter", "", "@", "Hi"], expected: -Infinity }].forEach( + ({ input, expected }) => + it(`should return "invalid elements" for non-numeric values`, () => { + expect(findMax(input)).toEqual(expected); + }) + ); +}); diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 9062aafe3..cefe28c02 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,4 +1,18 @@ function sum(elements) { + if (!Array.isArray(elements)) return "invalid elements"; + if (elements.length === 0) return 0; + const number = []; + for (const part of elements) { + if (typeof part === "number" && !Number.isNaN(x)) { + number.push(part); + } + } + if (number.length === 0) return "invalid elements"; + let sumOfNum = 0; + for (let i = 0; i < number.length; i++) { + sumOfNum += number[i]; + } + return sumOfNum; } module.exports = sum; diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index dd0a090ca..4ace641d4 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -10,27 +10,73 @@ const sum = require("./sum.js"); // Acceptance Criteria: -// Given an empty array -// When passed to the sum function -// Then it should return 0 -test.todo("given an empty array, returns 0") - -// Given an array with just one number -// When passed to the sum function -// Then it should return that number - -// Given an array containing negative numbers -// When passed to the sum function -// Then it should still return the correct total sum - -// Given an array with decimal/float numbers -// When passed to the sum function -// Then it should return the correct total sum - -// 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 - -// 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 +describe("sum()", () => { + // Given an empty array + // When passed to the sum function + // Then it should return 0 + [{ input: [], expected: 0 }].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); + + // Given an array with just one number + // When passed to the sum function + // Then it should return that number + + [{ input: [30], expected: 30 }].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); + + // Given an array containing negative numbers + // When passed to the sum function + // Then it should still return the correct total sum + + [{ input: [-1, -3, -4, -11], expected: -19 }].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); + + // Given an array with decimal/float numbers + // When passed to the sum function + // Then it should return the correct total sum + + [{ input: [0.5, 0.2, 0.11, 0.89, 0.3], expected: 2 }].forEach( + ({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(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 + + [ + { + input: ["evan", 3, "mike", 20, 6, "", "/", undefined, null, 20], + expected: 49, + }, + ].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + 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 + [ + { + input: ["evan", "mike", "",undefined], + expected: "invalid elements", + }, + ].forEach(({ input, expected }) => + it(`should return ${expected} for [${input}]`, () => { + expect(sum(input)).toEqual(expected); + }) + ); +}); diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 29dad81f0..8c9ae2e66 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,8 +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]; + for (const element of list) { if (element === target) { return true; }