diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index b22590bc6..3f3c2a301 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -6,8 +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]; + let median = null; + //return null if the list is not an array + if (!Array.isArray(list)) return median; + + // return null if none of the items in the array is a number + if (!list.some((item) => typeof item === "number")) return median; + + let numericArray = list.filter((item) => typeof item === "number"); + let sortedArray = numericArray.toSorted((a, b) => a - b); + const middleIndex = Math.floor(sortedArray.length / 2); + + //check if the number of items in the array are even or odd + // and then calculate the median accordingly + if (sortedArray.length % 2 === 0) + median = (sortedArray[middleIndex - 1] + sortedArray[middleIndex]) / 2; + else median = sortedArray[middleIndex]; + return median; } diff --git a/Sprint-1/fix/median.test.js b/Sprint-1/fix/median.test.js index 21da654d7..c262c3776 100644 --- a/Sprint-1/fix/median.test.js +++ b/Sprint-1/fix/median.test.js @@ -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..b2b47750f 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1 +1,7 @@ -function dedupe() {} +function dedupe(arr) { + if (!Array.isArray(arr)) throw new Error(arr + " is not an array"); + else if (arr.length === 0) return arr; + else return Array.from(new Set(arr)); +} + +module.exports = dedupe; diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index 23e0f8638..dfe9b17e4 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -10,18 +10,66 @@ E.g. dedupe(['a','a','a','b','b','c']) target output: ['a','b','c'] E.g. dedupe([5, 1, 1, 2, 3, 2, 5, 8]) target output: [5, 1, 2, 3, 8] E.g. dedupe([1, 2, 1]) target output: [1, 2] */ +describe("dedupe", () => { + // Given an empty array + // When passed to the dedupe function + // Then it should return an empty array + it("given an empty array it should return an empty array", () => { + const array = []; + const dedupeArray = dedupe(array); + expect(dedupeArray).toEqual([]); + }); -// Acceptance Criteria: + // Given an array with no duplicates + // When passed to the dedupe function + // Then it should return a copy of the original array + [["a", "b", "c"], ["A", 1, "j", "?"], ["c"]].forEach((val) => + it(`returns copy of the original array if there are no duplicates in [${val}]`, () => + expect(dedupe(val)).toEqual(val)) + ); + // Given an array with strings or numbers + // When passed to the dedupe function + // Then it should remove the duplicate values, preserving the first occurrence of each element + [ + { input: [1, 2, 1, 3, 1, 2, 10, 5, 0, 10], expected: [1, 2, 3, 10, 5, 0] }, + { input: [1, 2, 1, 4], expected: [1, 2, 4] }, + { input: [1, 1, 1, 1, 1], expected: [1] }, + { + input: ["banana", "apple", "apple", "banana", "apple", "banana"], + expected: ["banana", "apple"], + }, + { + input: [" ", "empty", "", " ", "", "empty"], + expected: [" ", "empty", ""], + }, + { input: ["2", "2", "3", "1"], expected: ["2", "3", "1"] }, + ].forEach(({ input, expected }) => + it(`returns a copy of array removing the duplicates from [${input}]`, () => + expect(dedupe(input)).toEqual(expected)) + ); -// 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"); + // Given an input value that is not array could be null or undefined or just a number or string + // When passed to the dedupe function + // Then it should thrown an error + test("should thrown an error if the input is null", () => { + expect(() => dedupe(null)).toThrow(null + " is not an array"); + }); -// Given an array with no duplicates -// When passed to the dedupe function -// Then it should return a copy of the original array + test("should thrown an error if the input is a number", () => { + const number = 123; + expect(() => dedupe(number)).toThrow(number + " is not an array"); + }); + test("should thrown an error if the input is a string", () => { + const string = "this is a string"; + expect(() => dedupe(string)).toThrow(string + " is not an array"); + }); -// 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 + test("should thrown an error if the input is undefined", () => { + expect(() => dedupe(undefined)).toThrow(undefined + " is not an array"); + }); + + test("should thrown an error if the input is an object", () => { + const emptyObject = {}; + expect(() => dedupe(emptyObject)).toThrow(emptyObject + " is not an array"); + }); +}); diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 6dd76378e..35df39b4c 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,4 +1,7 @@ -function findMax(elements) { +function findMax(array) { + if (!Array.isArray(array)) throw new Error(array + " is not an array"); + const numbersArray = array.filter((value) => typeof value === "number"); + return Math.max(...numbersArray); } module.exports = findMax; diff --git a/Sprint-1/implement/max.test.js b/Sprint-1/implement/max.test.js index 82f18fd88..fd83711c7 100644 --- a/Sprint-1/implement/max.test.js +++ b/Sprint-1/implement/max.test.js @@ -12,32 +12,124 @@ We have set things up already so that this file can see your function from the o 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"); - -// 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 - -// 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 decimal numbers -// When passed to the max function -// Then it should return the largest decimal number - -// 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 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 +describe("findMax", () => { + // Given an empty array + // When passed to the max function + // Then it should return -Infinity + it("if an empty array is passed to the the findMax function, -Infinity should be returned", () => { + emptyArray = []; + expect(findMax(emptyArray)).toEqual(-Infinity); + }); + + // Given an array with one number + // When passed to the max function + // Then it should return that number + [[1], [70], [0], [-25], [100129]].forEach((val) => + it(`When an array with only one number is passed i.e. [${val}], it should return that number`, () => + expect(findMax(val)).toEqual(val[0])) + ); + + // Given an array with both positive and negative numbers + // When passed to the max function + // Then it should return the largest number overall + [ + { input: [12, -2, 4, 6, 0], expected: 12 }, + { input: [2, 5, 990, -4], expected: 990 }, + { input: [0, -1, -5], expected: 0 }, + { input: [0, -1, 300, 3], expected: 300 }, + ].forEach(({ input, expected }) => + it(`returns the max number from the 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 + [ + { input: [-4, -2, -1902, -2, -1], expected: -1 }, + { input: [-9088, -9087, -990788, -4888777], expected: -9087 }, + { input: [-1, -5], expected: -1 }, + ].forEach(({ input, expected }) => + it(`returns the max number from the array of negative numbers only [${input}]`, () => + 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 + [ + { input: [-4.2, 2.8, -19.8009, 2.4, 1.5], expected: 2.8 }, + { input: [-90.88, 0.001, -990.788], expected: 0.001 }, + { input: [-1.11, -5.3], expected: -1.11 }, + ].forEach(({ input, expected }) => + it(`returns the max number from the array of decimal numbers [${input}]`, () => + 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 + [ + { input: [-4, -2, "what is this", -1902, -2, "??", -1], expected: -1 }, + { + input: [-9088, ".oi9e9", "1000000", -9087, 990788, -4888777], + expected: 990788, + }, + { input: [-1.11, "here", -5.233, "ignore me please"], expected: -1.11 }, + ].forEach(({ input, expected }) => + it(`returns the max number from the array of numbers and non-numbers values [${input}]`, () => + 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 + + /* Ans: If there is no number in the array than considering the behavior for the above inputs + the least surprising value in return would be -Infinity as our array has zero elements which are numbers*/ + [ + { + input: ["Not a number", "what is this", "least surprising", "??", "what"], + expected: -Infinity, + }, + { + input: ["kkdkas", "Ahan!", "23"], + expected: -Infinity, + }, + { + input: ["here", "Least surprising", "????", "vale is", "-Infinity"], + expected: -Infinity, + }, + ].forEach(({ input, expected }) => + it(`returns the least surprising value for only non-numbers array [${input}]`, () => + expect(findMax(input)).toEqual(expected)) + ); + + // Given an input that is not array could be null or undefined or just a number or string + // When passed to the findMax function + // Then it should thrown an error + + test("should thrown an error if the input is null", () => { + expect(() => findMax(null)).toThrow(null + " is not an array"); + }); + + test("should thrown an error if the input is a number", () => { + const number = 980; + expect(() => findMax(number)).toThrow(number + " is not an array"); + }); + test("should thrown an error if the input is a string", () => { + const string = "just a string"; + expect(() => findMax(string)).toThrow(string + " is not an array"); + }); + + test("should thrown an error if the input is undefined", () => { + expect(() => findMax(undefined)).toThrow(undefined + " is not an array"); + }); + + test("should thrown an error if the input is an object", () => { + const emptyObject = {}; + expect(() => findMax(emptyObject)).toThrow( + emptyObject + " is not an array" + ); + }); +}); diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 9062aafe3..e30b2631a 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,4 +1,11 @@ -function sum(elements) { +function sum(array) { + if (!Array.isArray(array)) throw new Error(array + " is not an array"); + let numbersArray = array.filter((value) => typeof value === "number"); + const sum = numbersArray.reduce( + (accumulator, currentValue) => accumulator + currentValue, + 0 + ); + return sum; } module.exports = sum; diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index dd0a090ca..3f76f6ea1 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -8,29 +8,96 @@ E.g. sum(['hey', 10, 'hi', 60, 10]), target output: 80 (ignore any non-numerical const sum = require("./sum.js"); -// Acceptance Criteria: +describe("sum", () => { + // Given an empty array + // When passed to the sum function + // Then it should return 0 + it("0 should be return when an empty array is passed", () => + expect(sum([])).toEqual(0)); -// 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 + [[1], [22], [-29], [0]].forEach((input) => + it(`an array with just one number [${input}] should return that number`, () => + expect(sum(input)).toEqual(input[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 + [ + { input: [-1, -2, -100], expected: -103 }, + { input: [-26, 0, -90], expected: -116 }, + { input: [20, -20, 0, 45], expected: 45 }, + ].forEach(({ input, expected }) => + it(`array containing negative numbers [${input}] should return the correct sum`, () => + 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 + // Given an array with decimal/float numbers + // When passed to the sum function + // Then it should return the correct total sum + [ + { input: [1.1, 2.222, 100.001], expected: 103.32300000000001 }, + { input: [26.55, 0.001, -90.34], expected: -63.789 }, + { input: [-0.01, 45.9], expected: 45.89 }, + ].forEach(({ input, expected }) => + it(`array containing decimal/float numbers [${input}] should return the correct sum`, () => + 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: [1.1, "what", 2.222, "is", "this???", " ", 100.001], + expected: 103.32300000000001, + }, + { input: [26.55, "Okay", "!!", 0.001, -90.34], expected: -63.789 }, + { input: [1, "12", 45], expected: 46 }, + ].forEach(({ input, expected }) => + it(`array containing non-number values [${input}] should ignore them and return the correct sum of numbers in it`, () => + 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 + // 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: ["what", "is", "this???", " "], + expected: 0, + }, + { input: ["26.55", "Okay", "!!"], expected: 0 }, + { input: ["write", "whatever", "%-959"], expected: 0 }, + ].forEach(({ input, expected }) => + it(`array containing only non-number values [${input}] should should return 0`, () => + 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 + // Given an input value that is not array could be null or undefined or just a number or string + // When passed to the sum function + // Then it should thrown an error + test("should thrown an error if the input is null", () => { + expect(() => sum(null)).toThrow(null + " is not an array"); + }); -// 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("should thrown an error if the input is a number", () => { + const number = 123; + expect(() => sum(number)).toThrow(number + " is not an array"); + }); + test("should thrown an error if the input is a string", () => { + const string = "this is a string"; + expect(() => sum(string)).toThrow(string + " is not an array"); + }); + + test("should thrown an error if the input is undefined", () => { + expect(() => sum(undefined)).toThrow(undefined + " is not an array"); + }); + + test("should thrown an error if the input is an object", () => { + const emptyObject = {}; + expect(() => sum(emptyObject)).toThrow(emptyObject + " is not an array"); + }); +}); diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 29dad81f0..cc167f1bb 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,11 +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) { - return true; - } + for (const element of list) { + if (element === target) return true; } return false; } diff --git a/Sprint-1/stretch/aoc-2018-day1/solution.js b/Sprint-1/stretch/aoc-2018-day1/solution.js index e69de29bb..4063bb76e 100644 --- a/Sprint-1/stretch/aoc-2018-day1/solution.js +++ b/Sprint-1/stretch/aoc-2018-day1/solution.js @@ -0,0 +1,17 @@ +const fs = require("fs"); //getting file system to read file + +function getFinalFrequency() { + let finalFrequency = 0; + + const data = fs.readFileSync("input.txt", "utf8"); + const numbers = data + .split("\n") + .map(Number) // to convert split substrings into numbers + .filter((n) => !isNaN(n)); //filter out any non number values + for (const number of numbers) { + finalFrequency += number; + } + return finalFrequency; +} + +console.log("final frequency is " + getFinalFrequency());