diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index b22590bc6..ed65216c7 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -5,10 +5,49 @@ // Hint: Please consider scenarios when 'list' doesn't have numbers (the function is expected to return null) // 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; +// } + +// Ignore this Commit +// It is not my solution I got help with AI. I confess I need to undestand more those 3 methodos to think +//and get to this solution +// I will come back to it later. + function calculateMedian(list) { - const middleIndex = Math.floor(list.length / 2); - const median = list.splice(middleIndex, 1)[0]; - return median; + // non-array or empty inputs + if (!Array.isArray(list) || list.length === 0) { + return null; + } + + //Filter non-numeric values and create a new array of only numbers + + const numericList = list.filter( + (item) => typeof item === "number" && Number.isFinite(item) + ); + + // If after filtering, there are no numbers left, return null + if (numericList.length === 0) { + return null; + } + + //Sort the numeric list + const sortedList = [...numericList].sort((a, b) => a - b); + + const middleIndex = Math.floor(sortedList.length / 2); + + //Calculate the median based on list length (odd or even) + if (sortedList.length % 2 === 1) { + // Odd number of elements: return the middle element + return sortedList[middleIndex]; + } else { + // Even number of elements: return the average of the two middle elements + const mid1 = sortedList[middleIndex - 1]; + const mid2 = sortedList[middleIndex]; + return (mid1 + mid2) / 2; + } } module.exports = calculateMedian; diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 781e8718a..dbee8b654 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1 +1,13 @@ -function dedupe() {} +function dedupe(arr) { + const result = []; + for (const item of arr) { + if (!result.includes(item)) { + result.push(item); + } + } + return result; +} + +console.log(dedupe(["a", "a", "a", "b", "b", "c"])); + +module.exports = dedupe; \ No newline at end of file diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index 23e0f8638..e58ddc90a 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -16,12 +16,26 @@ 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"); +test("dedupe an empty array returns an empty array", () =>{ + const inputEmpty = []; + const result = dedupe(inputEmpty); + expect(result).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", () => { + const inputNoDuplicates = ["a", "b", "c" ]; + const result = dedupe(inputNoDuplicates); + expect(result).toEqual(["a", "b", "c"]); +}); // 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(" Given an array with no duplicates", () => { + const inputMix = [1,1,2,2,3,3,4,4,5,5]; + const result = dedupe(inputMix); + expect(result).toEqual([1,2,3,4,5]); +}); \ No newline at end of file diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 6dd76378e..ebf0faa8f 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,4 +1,9 @@ -function findMax(elements) { +function findMax(numbersList) { + let onlyNumbers = numbersList.filter((item) => typeof item === "number"); + let currentMax = Math.max(...onlyNumbers); + return currentMax; } +console.log(findMax([1, "apple", 5, 0, "banana", 3])); + module.exports = findMax; diff --git a/Sprint-1/implement/max.test.js b/Sprint-1/implement/max.test.js index 82f18fd88..ec0dcd921 100644 --- a/Sprint-1/implement/max.test.js +++ b/Sprint-1/implement/max.test.js @@ -16,28 +16,65 @@ 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"); +// This one is good to go! +test("given an empty array, returns -Infinity",() => { + const input = []; + const result = findMax(input); + expect(result).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 1 number, it returns the number ",() => {; + const inputMax1 = [3]; + const result = findMax(inputMax1); +expect(result).toEqual(3); +}); + // Given an array with both positive and negative numbers // When passed to the max function // Then it should return the largest number overall +test("give 2 positive numbers return the largest nunber",() => { + const inputMax2= [5,8]; + const result = findMax(inputMax2); + expect(result).toEqual(8); +}); // 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 return colest to Zero",() =>{ +const inputMax3= [-5,-3]; +const result = findMax(inputMax3); +expect (result).toEqual(-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, should return the largest decimal number",() => { +const inputMax4= [2.4,3.5]; +const result= findMax(inputMax4); +expect(result).toEqual(3.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 an array with non-number values,it should return the max and ignore non-numeric values ",() => { +const inputMax5 = [2, "apple", 5, "banana", 8, "watermelon"]; +const result= findMax(inputMax5); +expect(result).toEqual(8); +}); // 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 with only non-number values,it should return the least surprising value given how it behaves for all other inputs ", () => { + const inputMax6= [ "computer", "bike", "car", "ball"]; +const result= findMax(inputMax6); +expect(result).toEqual(-Infinity); +}); + diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 9062aafe3..4a73a4e1b 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,4 +1,20 @@ -function sum(elements) { +function sum(theArray) { + const onlyNumbers = theArray.filter((item) => typeof item === "number"); + const theFinalSum = onlyNumbers.reduce((runningTotal, currentNumber) => { + return runningTotal + currentNumber; + }, 0); + return theFinalSum; } +console.log(sum(["hey", 10, "hi", 60, 10])); + module.exports = sum; + +//numbersList.filter((item) => typeof item === "number"); +/* Sum the numbers in an array + +In this kata, you will need to implement a function that sums the numerical elements of an array + +E.g. sum([10, 20, 30]), target output: 60 +E.g. sum(['hey', 10, 'hi', 60, 10]), target output: 80 (ignore any non-numerical elements) +*/ diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index dd0a090ca..a4d846888 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -13,24 +13,55 @@ 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", () => { + const inputNumber = []; + const result = sum(inputNumber); + expect(result).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 1 number, it returns the sum number", () => { + const inputNumber = [34]; + const result = sum(inputNumber); + expect(result).toEqual(34); +}); + // 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",() => { + const inputNegative = [10, -5, 20, -15]; + const result= sum(inputNegative ) + expect (result).toEqual(10); +}); + // 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", () => { + const inputFloat = [10.2, 10.3]; + const result = sum(inputFloat); + expect (result).toEqual(20.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 +test("Given an array containing non-number values", () => { + const inputNonNumbers = [1, "apple", 2, true, 3]; + const result = sum(inputNonNumbers); + expect (result).toEqual(6) +}); // 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 with only non-number values" , () =>{ + const nonNumbers = ["helo", "hi"]; + const result = sum(nonNumbers); + expect (result).toEqual(0) +}); \ No newline at end of file diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 29dad81f0..bba744207 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,9 +1,18 @@ // 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; +// } + function includes(list, target) { - for (let index = 0; index < list.length; index++) { - const element = list[index]; - if (element === target) { + for (const value of list) { + if (value === target) { return true; } } diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..9cb455bb8 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,11 @@ -function contains() {} +function contains(someObject, propertyName) { + let whatTheRobotFound = someObject[propertyName]; + if (someObject[propertyName] === undefined) { + return false; + } else { + return true; + } +} module.exports = contains; + diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..e05d6dd0e 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,16 +20,39 @@ as the object doesn't contains a key of 'c' // Given an empty object // When passed to contains // Then it should return false -test.todo("contains on empty object returns false"); +test("contains on empty object returns false", () => { + const inputEmpty = []; + const result = contains(inputEmpty); + expect(result).toEqual(false); +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +test("Given an object with properties when pass to contains it returns true", () => { + const myObject = { + name: "Alice", + age: 30, + city: "London", + }; + const result = contains(myObject, "name"); + expect(result).toEqual(true); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("give a object with proprieties when pass contains with non-exist proprity name it should return false", () => { + const inputProprieties2 = ["f", "g", "h"]; + const result = contains(inputProprieties2); + expect(result).toEqual(false); +}); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("invalid parameters should return false or throw an error", () => { + const invalidParameters = ("f", "g", "h"); + const result = contains(invalidParameters); + expect(result).toEqual(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..682938751 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,14 @@ -function createLookup() { - // implementation here +function createLookup(countryCurrencyPairs) { + const lookup = {}; + + for (let i = 0; i < countryCurrencyPairs.length; i++) { + const countryCode = countryCurrencyPairs[i][0]; + const currencyCode = countryCurrencyPairs[i][1]; + + lookup[countryCode] = currencyCode; + } + + return lookup; } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..715c7072d 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,7 +1,21 @@ + const createLookup = require("./lookup.js"); -test.todo("creates a country currency code lookup for multiple codes"); +test("creates a country currency code lookup for multiple codes", () => { + const input = [ + ["US", "USD"], + ["CA", "CAD"], + ]; + + const result = createLookup(input); + + const expected = { + US: "USD", + CA: "CAD", + }; + expect(result).toEqual(expected); +}); /* Create a lookup object of key value pairs from an array of code pairs diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..a492a46b5 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,13 +1,40 @@ +// function parseQueryString(queryString) { +// const queryParams = {}; +// if (queryString.length === 0) { +// return queryParams; +// } +// const keyValuePairs = queryString.split("&"); + +// for (const pair of keyValuePairs) { +// const [key, value] = pair.split("="); +// queryParams[key] = value; +// } + +// return queryParams; +// } + +// module.exports = parseQueryString; + function parseQueryString(queryString) { const queryParams = {}; - if (queryString.length === 0) { + + if (!queryString) { return queryParams; } + const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + const index = pair.indexOf("="); + + if (index === -1) { + // key with no value + queryParams[pair] = ""; + } else { + const key = pair.slice(0, index); + const value = pair.slice(index + 1); + queryParams[key] = value; + } } return queryParams; diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..e030a8620 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -3,10 +3,39 @@ // Below is one test case for an edge case the implementation doesn't handle well. // Fix the implementation for this test, and try to think of as many other edge cases as possible - write tests and fix those too. -const parseQueryString = require("./querystring.js") +const parseQueryString = require("./querystring.js"); -test("parses querystring values containing =", () => { - expect(parseQueryString("equation=x=y+1")).toEqual({ - "equation": "x=y+1", - }); +// Empty string +test("empty string", () => { + expect(parseQueryString("")).toEqual({}); }); +// Single value +test("single key-value", () => { + expect(parseQueryString("name=alice")).toEqual({ name: "alice" }); +}); + +// Multiple pairs +test("multiple pairs", () => { + expect(parseQueryString("a=1&b=2")).toEqual({ a: "1", b: "2" }); +}); + +// Key with no value +test("key with no value", () => { + expect(parseQueryString("flag")).toEqual({ flag: "" }); +}); + +// Empty value +test("empty value", () => { + expect(parseQueryString("name=")).toEqual({ name: "" }); +}); + +// Multiple '=' in value +test("values with multiple =", () => { + expect(parseQueryString("equation=x=y+1")).toEqual({ equation: "x=y+1" }); +}); + +// Special characters +test("special characters", () => { + expect(parseQueryString("msg=hello%20world")).toEqual({ msg: "hello%20world" }); +}); + diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..16ceebb3a 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,26 @@ -function tally() {} +function tally(arr) { + // Handle invalid input + if (!Array.isArray(arr)) { + throw new Error("Input must be an array"); + } + + // Handle empty array + if (arr.length === 0) { + return {}; + } + + // Count frequencies + const result = {}; + + for (const item of arr) { + if (result[item]) { + result[item]++; + } else { + result[item] = 1; + } + } + + return result; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..777c8628d 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -1,5 +1,30 @@ const tally = require("./tally.js"); +// Test 1: Empty array +test("tally on an empty array returns an empty object", () => { + expect(tally([])).toEqual({}); +}); + +// Test 2: Single item +test("tally on single item returns count of 1", () => { + expect(tally(["a"])).toEqual({ a: 1 }); +}); + +// Test 3: Duplicate items +test("tally counts duplicate items", () => { + expect(tally(["a", "a", "a"])).toEqual({ a: 3 }); +}); + +// Test 4: Mixed items +test("tally counts multiple unique items", () => { + expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 }); +}); + +// Test 5: Invalid input throws error +test("tally throws error for non-array input", () => { + expect(() => tally("hello")).toThrow(); +}); + /** * tally array * @@ -23,7 +48,7 @@ const tally = require("./tally.js"); // Given an empty array // When passed to tally // Then it should return an empty object -test.todo("tally on an empty array returns an empty object"); + // Given an array with duplicate items // When passed to tally diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..b214c2750 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -6,24 +6,42 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} -function invert(obj) { - const invertedObj = {}; +// function invert(obj) { +// const invertedObj = {}; - for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; - } +// for (const [key, value] of Object.entries(obj)) { +// invertedObj.key = value; +// } - return invertedObj; -} +// return invertedObj; +// } // a) What is the current return value when invert is called with { a : 1 } +// 1 // b) What is the current return value when invert is called with { a: 1, b: 2 } +///2 // c) What is the target return value when invert is called with {a : 1, b: 2} +//"1": "a", "2": "b" // c) What does Object.entries return? Why is it needed in this program? +//Object.entries({ a: 1, b: 2 }) // Returns: [["a", 1], ["b", 2]] +// It converts an object to an array of [key, value] pairs so you can loop through them. // d) Explain why the current return value is different from the target output - +// The bug is invertedObj.key = value — this literally creates a property named "key" +// instead of using the variable key. Also, it should swap: value becomes key, key becomes value. // e) Fix the implementation of invert (and write tests to prove it's fixed!) + +function invert(obj) { + const invertedObj = {}; + + for (const [key, value] of Object.entries(obj)) { + invertedObj[value] = key; // Use [value] as key, key as value + } + + return invertedObj; +} + +module.exports = invert; \ No newline at end of file diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js new file mode 100644 index 000000000..450cf8780 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,17 @@ +const invert = require("./invert.js"); + +test("inverts simple object", () => { + expect(invert({ a: 1 })).toEqual({ 1: "a" }); +}); + +test("inverts multiple keys", () => { + expect(invert({ a: 1, b: 2 })).toEqual({ 1: "a", 2: "b" }); +}); + +test("inverts x,y coordinates", () => { + expect(invert({ x: 10, y: 20 })).toEqual({ 10: "x", 20: "y" }); +}); + +test("empty object returns empty", () => { + expect(invert({})).toEqual({}); +}); diff --git a/package.json b/package.json new file mode 100644 index 000000000..a1e2bdacc --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "module-data-groups", + "version": "1.0.0", + "description": "Like learning a musical instrument, programming requires daily practice.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Della-Bella/Module-Data-Groups-Old.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/Della-Bella/Module-Data-Groups-Old/issues" + }, + "homepage": "https://github.com/Della-Bella/Module-Data-Groups-Old#readme" +}