diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index 5c5b796e1..2273eb249 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -6,9 +6,37 @@ // or contains values that aren't numbers (the function is expected to throw - see the tests). function calculateMedian(list) { - const middleIndex = Math.floor(list.length / 2); - const median = list.splice(middleIndex, 1)[0]; - return median; + if (!Array.isArray(list)) { + throw new Error("calculateMedian requires an array of numbers"); + } + if (list.length === 0) { + throw new Error("calculateMedian requires a non-empty array"); + } + + for (item of list) { + if (typeof item === "string") { + throw new Error("calculateMedian requires an array of numbers"); + } + if (item === null) { + throw new Error("calculateMedian requires an array of numbers"); + } + if (list.includes(undefined)) { + throw new Error("calculateMedian requires an array of numbers"); + } + } + + const sorted = list.toSorted((a, b) => a - b); + const oddNum = list.length % 2 === 1; + + if (oddNum) { + const middleIndex = Math.floor(list.length / 2); + return sorted[middleIndex]; + } else { + const middleIndex = Math.floor(list.length / 2); + const middle = middleIndex - 1; + const median = (sorted[middleIndex] + sorted[middle]) / 2; + return median; + } } module.exports = calculateMedian; diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 781e8718a..8999ed2cf 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1 +1,14 @@ -function dedupe() {} +function dedupe(arr) { + if (arr.length === 0) { + return arr; + } + const newArr = []; + for (const item of arr) { + if (!newArr.includes(item)) { + newArr.push(item); + } + } + return newArr; +} + +module.exports = dedupe; diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index d7c8e3d8e..fb0ae2dad 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -16,13 +16,24 @@ 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(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, should return a copy of the original array", () => { + const original = ["a", 11, "55"]; + const expected = dedupe(original); + expect(expected).toEqual(original); + expect(expected).not.toBe(original); +}); // 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 an array of strings and numbers, should return a new array with duplicates removed", () => { + expect(dedupe(["a", "a", 33, 33, 1])).toEqual(["a", 33, 1]); +}); diff --git a/Sprint-1/implement/describe-median.js b/Sprint-1/implement/describe-median.js index 3381cfc0a..e6a0a4033 100644 --- a/Sprint-1/implement/describe-median.js +++ b/Sprint-1/implement/describe-median.js @@ -20,6 +20,13 @@ function calculateMedian(list) { } // Implement this function. See describe-median.test.js for the acceptance criteria. -function describeMedian(list) {} +function describeMedian(list) { + try { + const median = calculateMedian(list); + return "The median is " + median; + } catch (error) { + return "Could not calculate a median: " + error.message; + } +} module.exports = describeMedian; diff --git a/Sprint-1/implement/describe-median.test.js b/Sprint-1/implement/describe-median.test.js index e7d18a264..56a34a674 100644 --- a/Sprint-1/implement/describe-median.test.js +++ b/Sprint-1/implement/describe-median.test.js @@ -21,12 +21,27 @@ const describeMedian = require("./describe-median.js"); // When passed to describeMedian // Then it should return "The median is " followed by the median // Delete this test.todo and replace it with a test. -test.todo('given [1, 2, 3], returns "The median is 2"'); +test('given [1, 2, 3], returns "The median is 2"', () => { + expect(describeMedian([1, 2, 3])).toEqual("The median is 2"); +}); // Given an empty array // When passed to describeMedian // Then it should return "Could not calculate a median: calculateMedian requires a non-empty array" +test('given an empty array,should return "Could not calculate a median: calculateMedian requires a non-empty array"', () => { + expect(describeMedian([])).toEqual( + "Could not calculate a median: calculateMedian requires a non-empty array" + ); +}); // Given something that isn't an array of numbers, e.g. "banana" // When passed to describeMedian // Then it should return "Could not calculate a median: calculateMedian requires an array of numbers" +test('given something that is not an array of numbers, should return "Could not calculate a median: calculateMedian requires an array of numbers"', () => { + expect(describeMedian(32)).toEqual( + "Could not calculate a median: calculateMedian requires an array of numbers" + ); + expect(describeMedian("banana")).toEqual( + "Could not calculate a median: calculateMedian requires an array of numbers" + ); +}); diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 6dd76378e..8d7a48b81 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,4 +1,19 @@ function findMax(elements) { + if (!Array.isArray(elements)) { + throw new Error("findMax requires an array of numbers"); + } + if (elements.includes(NaN)) { + throw new Error("findMax requires an array of numbers"); + } + if (elements.length === 0) { + return -Infinity; + } + + if (elements.length === 1) { + return elements[0]; + } + const sortedList = elements.toSorted((a, b) => a - b); + return sortedList.at(-1); } module.exports = findMax; diff --git a/Sprint-1/implement/max.test.js b/Sprint-1/implement/max.test.js index ff3fbb5e5..b7df06eeb 100644 --- a/Sprint-1/implement/max.test.js +++ b/Sprint-1/implement/max.test.js @@ -16,28 +16,58 @@ 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([])).toEqual(-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([4])).toEqual(4); +}); // 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 both positive and negative numbers, should returns the largest number overall", () => { + expect(findMax([4, -2])).toEqual(4); +}); // 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 just negative numbers, should return the closest one to zero", () => { + expect(findMax([-2, -54])).toEqual(-2); +}); // 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, should return the largest decimal number", () => { + expect(findMax([3.5, 10.8])).toEqual(10.8); +}); // Given an array containing a value that isn't a number // When passed to the max function // Then it should throw Error("findMax requires an array of numbers") - +test("throws an error when an array contains a non-number", () => { + expect(() => findMax([10, NaN, 22])).toThrow( + "findMax requires an array of numbers" + ); +}); // Given something that isn't an array at all, such as "hey", 42 or no argument // When passed to the max function // Then it should throw Error("findMax requires an array of numbers") +test("throws an error when input is a string", () => { + expect(() => findMax("hello")).toThrow( + "findMax requires an array of numbers" + ); +}); + +test("throws an error when input is a number", () => { + expect(() => findMax(42)).toThrow("findMax requires an array of numbers"); +}); + +test("throws an error when no argument is provided", () => { + expect(() => findMax()).toThrow("findMax requires an array of numbers"); +}); diff --git a/Sprint-1/implement/mean.js b/Sprint-1/implement/mean.js index 36909ea1f..dee0001c4 100644 --- a/Sprint-1/implement/mean.js +++ b/Sprint-1/implement/mean.js @@ -1,3 +1,26 @@ -function calculateMean(list) {} +function calculateMean(list) { + if (!Array.isArray(list)) { + throw new Error("calculateMean requires an array of numbers"); + } + for (const item of list) { + if (typeof item !== "number") { + throw new Error("calculateMean requires an array of numbers"); + } + } + if (list.length === 0) { + throw new Error("calculateMean requires a non-empty array"); + } + if (list.length === 1) { + return list[0]; + } + + let result = 0; + let totalItem = 0; + for (const item of list) { + totalItem += item; + result = totalItem / list.length; + } + return result; +} module.exports = calculateMean; diff --git a/Sprint-1/implement/mean.test.js b/Sprint-1/implement/mean.test.js index 847b88676..a959e2f77 100644 --- a/Sprint-1/implement/mean.test.js +++ b/Sprint-1/implement/mean.test.js @@ -23,28 +23,65 @@ const calculateMean = require("./mean.js"); // When passed to calculateMean // Then it should return their mean // Delete this test.todo and replace it with a test. -test.todo("given [1, 2, 6], returns 3"); +test("given [1, 2, 6], returns 3", () => { + expect(calculateMean([1, 2, 6])).toEqual(3); +}); // Given an array with a single number // When passed to calculateMean // Then it should return that number +test("given an array with a single number, should return that number", () => { + expect(calculateMean([54])).toEqual(54); +}); // Given an array containing negative or decimal numbers // When passed to calculateMean // Then it should return the correct mean +test("given an array containing negative or decimal numbers, should return the correct mean", () => { + expect(calculateMean([-3, 3.6, -10, 2.2])).toEqual(-1.8); +}); // Given an empty array // When passed to calculateMean // Then it should throw Error("calculateMean requires a non-empty array") +test("given an empty array,should throw Error(calculateMean requires a non-empty array)", () => { + expect(() => calculateMean([])).toThrow( + "calculateMean requires a non-empty array" + ); +}); // Given a value that isn't an array, e.g. "banana", 42, null or {} // When passed to calculateMean // Then it should throw Error("calculateMean requires an array of numbers") +test("given a value that is not an array,should throw new Error(calculateMean requires an array of numbers)", () => { + expect(() => calculateMean("banana")).toThrow( + "calculateMean requires an array of numbers" + ); + expect(() => calculateMean(42)).toThrow( + "calculateMean requires an array of numbers" + ); + expect(() => calculateMean(null)).toThrow( + "calculateMean requires an array of numbers" + ); + expect(() => calculateMean({})).toThrow( + "calculateMean requires an array of numbers" + ); +}); // Given no argument at all // When passed to calculateMean // Then it should throw Error("calculateMean requires an array of numbers") +test("given no argument at all, should throw Error(calculateMean requires an array of numbers)", () => { + expect(() => calculateMean()).toThrow( + "calculateMean requires an array of numbers" + ); +}); // Given an array containing a non-number value, e.g. [1, "2", 3] // When passed to calculateMean // Then it should throw Error("calculateMean requires an array of numbers") +test("given an array containing a non-number value, should throw Error(calculateMean requires an array of numbers)", () => { + expect(() => calculateMean([1, 5, "13"])).toThrow( + "calculateMean requires an array of numbers" + ); +}); diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 9062aafe3..1597eb352 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,4 +1,21 @@ function sum(elements) { + if (!Array.isArray(elements)) { + throw new Error("sum requires an array of numbers"); + } + if (elements.includes(NaN)) { + throw new Error("sum requires an array of numbers"); + } + if (elements.length === 0) { + return 0; + } + if (elements.length === 1) { + return elements[0]; + } + let total = 0; + for (const item of elements) { + total += item; + } + return total; } module.exports = sum; diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index a288e0f0a..27c5aee45 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -13,24 +13,48 @@ 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([])).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 with just one number, should return that number", () => { + expect(sum([1])).toEqual(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 containing negative numbers,should return the correct total sum", () => { + expect(sum([-2, -4, -1])).toEqual(-7); +}); // 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 wit decimal numbers, should return correct total sum", () => { + expect(sum([3.1, 2.1, 8.8])).toEqual(14); +}); // Given an array containing a value that isn't a number // When passed to the sum function // Then it should throw Error("sum requires an array of numbers") +test("given an array containing a value that is not a number, should throw Error(sum requires an array of numbers)", () => { + expect(() => sum([NaN, 21])).toThrow("sum requires an array of numbers"); +}); // Given something that isn't an array at all, such as "hey", 42 or no argument // When passed to the sum function // Then it should throw Error("sum requires an array of numbers") +test("given something that isn't an array at all, should throw Error(sum requires an array of numbers)", () => { + expect(() => sum(21)).toThrow("sum requires an array of numbers"); +}); + +test("given something that isn't an array at all, should throw Error(sum requires an array of numbers)", () => { + expect(() => sum("hello")).toThrow("sum requires an array of numbers"); +}); +test("given something that isn't an array at all, should throw Error(sum requires an array of numbers)", () => { + expect(() => sum()).toThrow("sum requires an array of numbers"); +}); diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 29dad81f0..6aeac0b5d 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,9 +1,8 @@ // 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) { + for (const item of list) { + if (item === target) { return true; } } diff --git a/Sprint-1/stretch/aoc-2018-day1/solution.js b/Sprint-1/stretch/aoc-2018-day1/solution.js index e69de29bb..1ad8adc19 100644 --- a/Sprint-1/stretch/aoc-2018-day1/solution.js +++ b/Sprint-1/stretch/aoc-2018-day1/solution.js @@ -0,0 +1,15 @@ +const fs = require("fs"); +const input = fs.readFileSync("./input.txt", "utf-8"); + +function calculateFrequency(input) { + let frequency = 0; + const nums = input.trim().split("\n").map(Number); + + for (num of nums) { + frequency += num; + } + return frequency; +} +console.log(calculateFrequency(input)); + +//529