From e3d10bce8c3637755df11e5c4607721fc2da1ca9 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 13:46:06 +0000 Subject: [PATCH 01/17] fix and predict anything that isn't working --- Sprint-2/debug/address.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..9d3ae06c2 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,5 +1,5 @@ // Predict and explain first... - +// this code will give an error because the address is not an array and we should use dot notation to access houseNumber. // This code should log out the houseNumber from the address object // but it isn't working... // Fix anything that isn't working @@ -12,4 +12,4 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address.houseNumber}`); From b1444af922734d0cc144e9988da10abbcba9770c Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 13:53:32 +0000 Subject: [PATCH 02/17] fix and predict anything that isn't working --- Sprint-2/debug/author.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..339460094 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,5 +1,5 @@ // Predict and explain first... - +// this code will give an error because the for...of is generally used to iterate over iterable objects like arrays or strings. thus, we should use for...in loop to iterate over the properties of an object. // This program attempts to log out all the property values in the object. // But it isn't working. Explain why first and then fix the problem @@ -11,6 +11,6 @@ const author = { alive: true, }; -for (const value of author) { - console.log(value); -} +for (const value in author) { + console.log(`${value}: ${author[value]}`); +}; From fb7daba5114319fcc038911fb4e57933204eed9d Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 14:08:06 +0000 Subject: [PATCH 03/17] fix and predict anything that isn't working --- Sprint-2/debug/recipe.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..8bdeb2dd5 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,5 +1,5 @@ // Predict and explain first... - +// This code will not log out the ingredients correctly.we should access the ingredients array specifically. // This program should log out the title, how many it serves and the ingredients. // Each ingredient should be logged on a new line // How can you fix it? @@ -10,6 +10,12 @@ const recipe = { ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; -console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +console.log(`${recipe.title} +serves ${recipe.serves} +ingredients: +${recipe.ingredients[0] +} +${recipe.ingredients[1]} +${recipe.ingredients[2]} +${recipe.ingredients[3]} +`); From 285095c89d2197b8bc163862eff1b2c6a79529f4 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 14:40:54 +0000 Subject: [PATCH 04/17] implement a function called contains --- Sprint-2/implement/contains.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..f147caeaa 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,8 @@ -function contains() {} +function contains(input, propertyName) { + if (input && typeof input === 'object' && !Array.isArray(input)) { + return input.hasOwnProperty(propertyName); + } + return false; +}; module.exports = contains; From a63ca9151144ca3d027a4a9cf0d70b2a2a0b9cf3 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 14:42:40 +0000 Subject: [PATCH 05/17] implement a jest file that checks an object contains a particular property --- Sprint-2/implement/contains.test.js | 38 ++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..90478d58f 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -16,20 +16,52 @@ as the object doesn't contains a key of 'c' // Given a contains function // When passed an object and a property name // Then it should return true if the object contains the property, false otherwise - +test("given a contains function ,returns true for existing property, false otherwise", () => { + const input = {a: 1, b: 2}; + const propertyName = 'a'; + const currentOutput = contains(input, propertyName); + const targetOutput = true; + expect(currentOutput).toBe(targetOutput); +}); // Given an empty object // When passed to contains // Then it should return false -test.todo("contains on empty object returns false"); - +test("given an empty object, contains returns false",()=>{ + const input = {}; + const propertyName = 'anyProp'; + const currentOutput = contains(input,propertyName); + const targetOutput = false; + expect(currentOutput).toBe(targetOutput); +}); // 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, returns true for existing property",()=>{ + const input = {x:10,y:20,z:30}; + const propertyName = 'y'; + const currentOutput = contains(input,propertyName); + const targetOutput = true; + expect(currentOutput).toBe(targetOutput); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("given an object with properties, returns false for non-existing property",()=>{ + const input = {x:10,y:20,z:30}; + const propertyName = 'a'; + const currentOutput = contains(input,propertyName); + const targetOutput = false; + expect(currentOutput).toBe(targetOutput); +}); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("given invalid parameters like an array, contains returns false",()=>{ + const input = [1,2,3]; + const propertyName = '0'; + const currentOutput = contains(input,propertyName); + const targetOutput = false; + expect(currentOutput).toBe(targetOutput); +}); \ No newline at end of file From 80bd54c642e29832a289324036c82106d053e363 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 15:10:59 +0000 Subject: [PATCH 06/17] implement a function called lookup --- Sprint-2/implement/lookup.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..d21e67073 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,9 @@ -function createLookup() { - // implementation here +function createLookup(pairs) { + const lookup = {}; + for (const [countryCode, currencyCode] of pairs) { + lookup[countryCode] = currencyCode; + } + return lookup; } module.exports = createLookup; From 0404dc5ebdfecf3c2b97f9fee2beed4757f5347a Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 15:12:15 +0000 Subject: [PATCH 07/17] creat a jest file for lookup code --- Sprint-2/implement/lookup.test.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..5e5301bda 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,15 @@ 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'], ['GB', 'GBP']]; + const currentOutput = createLookup(input); + const targetOutput = { + 'US': 'USD', + 'CA': 'CAD', + 'GB': 'GBP' + }; + expect(currentOutput).toEqual(targetOutput); +}); /* From 1b6db2ae5b2c2d947bf701e1c63ae971bdc24ca7 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 15:57:31 +0000 Subject: [PATCH 08/17] fix the function --- Sprint-2/implement/querystring.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..2b80ff428 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,12 +1,25 @@ function parseQueryString(queryString) { const queryParams = {}; - if (queryString.length === 0) { + if(!queryString) { return queryParams; } + if (queryString.startsWith("?")) { + queryString = queryString.slice(1); + } + const keyValuePairs = queryString.split("&"); - for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); + if (!pair) continue; + const firstEq = pair.indexOf("="); + let key; + let value; + if (firstEq === -1) { + key = pair; + value = ""; + } else { + key = pair.slice(0, firstEq); + value = pair.slice(firstEq + 1); + } queryParams[key] = value; } From 02f764a020bd3bcbc79193cdc5fe3574933b73a5 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 15:58:16 +0000 Subject: [PATCH 09/17] create a jest file for querystring function --- Sprint-2/implement/querystring.test.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..8fce8228b 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -6,7 +6,21 @@ const parseQueryString = require("./querystring.js") test("parses querystring values containing =", () => { - expect(parseQueryString("equation=x=y+1")).toEqual({ - "equation": "x=y+1", - }); + expect(parseQueryString("equation=x=y+1")).toEqual({ equation: "x=y+1" }); }); + +test("parses multiple key=value pairs", () => { + expect(parseQueryString("a=1&b=2")).toEqual({ a: "1", b: "2" }); +}); + +test("parses empty querystring", () => { + expect(parseQueryString("")).toEqual({}); +}); + +test("parses key with no '=' (a)", () => { + expect(parseQueryString("a")).toEqual({ a: "" }); +}); + +test("last value wins for duplicate keys", () => { + expect(parseQueryString("a=1&a=2")).toEqual({ a: "2" }); +}); \ No newline at end of file From a31ecb50cc7b938625783fe0f9eb315407610c77 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 16:07:11 +0000 Subject: [PATCH 10/17] implement a function called tally --- Sprint-2/implement/tally.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..54f3eef76 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,16 @@ -function tally() {} +function tally(items) { + if (!Array.isArray(items)) { + throw new TypeError('Input must be an array'); + } + const tallyResult = {}; + for (const item of items) { + if (tallyResult[item] === undefined) { + tallyResult[item] = 1; + } else { + tallyResult[item]++; + } + } + return tallyResult; +} module.exports = tally; From 4d32436b6aee6c4f9ea61074b3abc7503680809a Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 16:07:45 +0000 Subject: [PATCH 11/17] create a jest file for tally code --- Sprint-2/implement/tally.test.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..64391033d 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -20,15 +20,35 @@ const tally = require("./tally.js"); // When passed an array of items // Then it should return an object containing the count for each unique item +test("tally returns counts for each unique item", () => { + const input = ['a', 'a', 'b', 'c']; + const expectedOutput = { a: 2, b: 1, c: 1 }; + expect(tally(input)).toEqual(expectedOutput); +}); // 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"); + +test("tally on an empty array returns an empty object", () => { + const input = []; + const expectedOutput = {}; + expect(tally(input)).toEqual(expectedOutput); +}); // Given an array with duplicate items // When passed to tally // Then it should return counts for each unique item +test("tally counts each unique item correctly", () => { + const input = ['a', 'b', 'a', 'c', 'b', 'a']; + const expectedOutput = { a: 3, b: 2, c: 1 }; + expect(tally(input)).toEqual(expectedOutput); +}); // Given an invalid input like a string // When passed to tally // Then it should throw an error + +test("tally throws an error for non-array input", () => { + const input = "not an array"; + expect(() => tally(input)).toThrow(TypeError); +}); \ No newline at end of file From 3e0ac567d47d1ea79f979f9087fc4a2f4755000b Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Sun, 16 Nov 2025 16:19:18 +0000 Subject: [PATCH 12/17] fix implementation and write tests to prove it's worked --- Sprint-2/interpret/invert.js | 59 +++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..7db085cdf 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -6,24 +6,69 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} +//function invert(obj) { +// const invertedObj = {}; + + // for (const [key, value] of Object.entries(obj)) { + // invertedObj.key = value; + // } + + // return invertedObj; +//} + +// a) What is the current return value when invert is called with { a : 1 }: {key: 1} + +// b) What is the current return value when invert is called with { a: 1, b: 2 }: {key: 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 returns an array of a given object's own enumerable string-keyed property [key, value] pairs. It is needed in this program to iterate over each key-value pair in the object so that we can swap them when creating the inverted object. + +// d) Explain why the current return value is different from the target output? +// The current return value is different from the target output because in the line (invertedObj.key = value;), the property name 'key' is being used literally instead of using the variable (key). This means that every iteration of the loop is overwriting the same property 'key' in the inverted object, resulting in only the last value being stored. + +// e) Fix the implementation of invert (and write tests to prove it's fixed!) + +// Fixed implementation: + + function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } return invertedObj; } +module.exports = invert; -// a) What is the current return value when invert is called with { a : 1 } -// b) What is the current return value when invert is called with { a: 1, b: 2 } +// Test cases: -// c) What is the target return value when invert is called with {a : 1, b: 2} +const invert = require('./invert'); -// c) What does Object.entries return? Why is it needed in this program? +// single key: -// d) Explain why the current return value is different from the target output +test('invert single key-value pair', () => { + expect(invert({ a: 1 })).toEqual({ "1": "a" }); +}); -// e) Fix the implementation of invert (and write tests to prove it's fixed!) +// multiple keys: + +test('invert multiple key-value pairs', () => { + expect(invert({ a: 1, b: 2 })).toEqual({ "1": "a", "2": "b" }); +}); + +// Empty object: + +test('invert empty object', () => { + expect(invert({})).toEqual({}); +}); + +// Non-string values: + +test('invert with non-string values', () => { + expect(invert({ x: 10, y: 20 })).toEqual({ "10": "x", "20": "y" }); +}); \ No newline at end of file From 046c190609cb147ea164c3ae91aec19176ba2859 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Mon, 24 Nov 2025 17:13:30 +0000 Subject: [PATCH 13/17] implement functions and answer questions --- Sprint-2/stretch/count-words.js | 19 ++++++++++ Sprint-2/stretch/mode.test.js | 6 +++ Sprint-2/stretch/till.js | 67 ++++++++++++++++++++++++++++++--- 3 files changed, 86 insertions(+), 6 deletions(-) diff --git a/Sprint-2/stretch/count-words.js b/Sprint-2/stretch/count-words.js index 8e85d19d7..958261e70 100644 --- a/Sprint-2/stretch/count-words.js +++ b/Sprint-2/stretch/count-words.js @@ -26,3 +26,22 @@ 3. Order the results to find out which word is the most common in the input */ + +function countWords(inputString) { + + const cleanedString = inputString.replace(/[.,!?]/g, '').toLowerCase(); + const wordsArray = cleanedString.split(/\s+/); + const wordCount = {}; + + for (const word of wordsArray) { + if (wordCount[word] === undefined) { + wordCount[word] = 1; + } else { + wordCount[word]++; + } + } + + return wordCount; +} + +module.exports = countWords; \ No newline at end of file diff --git a/Sprint-2/stretch/mode.test.js b/Sprint-2/stretch/mode.test.js index ca33c28a3..89bcc0ddc 100644 --- a/Sprint-2/stretch/mode.test.js +++ b/Sprint-2/stretch/mode.test.js @@ -6,6 +6,12 @@ const calculateMode = require("./mode.js"); // When calculateMode is called on the array // Then it should return the number that appears most frequently in the array +test("calculateMode is a function ,returns the most frequent number", () => { + const nums = [1, 2, 2, 3, 4]; + + expect(typeof calculateMode).toBe("function"); + expect(calculateMode(nums)).toBe(2); +}); // Example: // Given [2,4,1,2,3,2,1] // When calculateMode is called on [2,4,1,2,3,2,1] diff --git a/Sprint-2/stretch/till.js b/Sprint-2/stretch/till.js index 6a08532e7..a8ca5eb72 100644 --- a/Sprint-2/stretch/till.js +++ b/Sprint-2/stretch/till.js @@ -4,16 +4,47 @@ // When this till object is passed to totalTill // Then it should return the total amount in pounds +//function totalTill(till) { +//let total = 0; + +//for (const [coin, quantity] of Object.entries(till)) { +// total += coin * quantity; +//} + +// return `£${total / 100}`; +//} + +//const till = { +// "1p": 10, +// "5p": 6, +// "50p": 4, +// "20p": 10, +//}; +//const totalAmount = totalTill(till); + +// a) What is the target output when totalTill is called with the till object? +// Answer: £4.10 + +// b) Why do we need to use Object.entries inside the for...of loop in this function? +// Answer: Object.entries is used to convert the till object into an array of [key, value] pairs, allowing us to iterate over each coin type and its quantity. +// c) What does coin * quantity evaluate to inside the for...of loop? +// Answer: coin * quantity evaluates to NaN because coin is a string (e.g., "1p") and cannot be directly multiplied by a number. + +// d) Write a test for this function to check it works and then fix the implementation of totalTill? + + +// Fix implementation function totalTill(till) { let total = 0; for (const [coin, quantity] of Object.entries(till)) { - total += coin * quantity; + // Remove the 'p' and convert to number + const coinValue = Number(coin.replace("p", "")); + total += coinValue * quantity; } return `£${total / 100}`; } - const till = { "1p": 10, "5p": 6, @@ -22,10 +53,34 @@ const till = { }; const totalAmount = totalTill(till); -// a) What is the target output when totalTill is called with the till object +module.exports = totalTill; -// b) Why do we need to use Object.entries inside the for...of loop in this function? +// test cases: -// c) What does coin * quantity evaluate to inside the for...of loop? +const totalTill = require("./till.js"); + +test("totalTill calculates the total amount in pounds from the till object", () => { + const till = { + "1p": 10, + "5p": 6, + "50p": 4, + "20p": 10, + }; + + expect(totalTill(till)).toBe("£4.10"); +}); + +// Additional test cases +test("totalTill returns £0.00 for an empty till", () => { + const till = {}; + + expect(totalTill(till)).toBe("£0.00"); +}); + +test("totalTill handles tills with only one type of coin", () => { + const till = { + "100p": 5, + }; -// d) Write a test for this function to check it works and then fix the implementation of totalTill + expect(totalTill(till)).toBe("£5.00"); +}); From 35ac58481dc7475bc299087a175151ae293a9c2f Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Wed, 26 Nov 2025 16:04:11 +0000 Subject: [PATCH 14/17] modified recipe function to let it work to any number of ingredients --- Sprint-2/debug/recipe.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 8bdeb2dd5..6819c8244 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -10,12 +10,10 @@ const recipe = { ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; -console.log(`${recipe.title} +console.log(`${recipe.title} serves ${recipe.serves} -ingredients: -${recipe.ingredients[0] -} -${recipe.ingredients[1]} -${recipe.ingredients[2]} -${recipe.ingredients[3]} -`); +ingredients:`); + +recipe.ingredients.forEach(ingredient => { + console.log(ingredient); +}); \ No newline at end of file From 9fc13aac2d5208906ce3686fd63ebac5bf135eeb Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Wed, 26 Nov 2025 16:32:56 +0000 Subject: [PATCH 15/17] fix the code to let key and value be percent-encoded --- Sprint-2/implement/querystring.js | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 2b80ff428..33eed4d43 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,25 +1,33 @@ function parseQueryString(queryString) { const queryParams = {}; - if(!queryString) { + + if (!queryString) { return queryParams; } - if (queryString.startsWith("?")) { + + if (queryString.startsWith("?")) { queryString = queryString.slice(1); } - + const keyValuePairs = queryString.split("&"); + for (const pair of keyValuePairs) { - if (!pair) continue; + if (!pair) continue; + const firstEq = pair.indexOf("="); + let key; - let value; + let value; + if (firstEq === -1) { - key = pair; + // No "=" found → key with empty value + key = decodeURIComponent(pair); value = ""; } else { - key = pair.slice(0, firstEq); - value = pair.slice(firstEq + 1); + key = decodeURIComponent(pair.slice(0, firstEq)); + value = decodeURIComponent(pair.slice(firstEq + 1)); } + queryParams[key] = value; } @@ -27,3 +35,4 @@ function parseQueryString(queryString) { } module.exports = parseQueryString; +console.log(parseQueryString("?text=Hello%20World&amount=5%25")); From 99836eb50078ed42cd149097654bcc9e09621462 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Wed, 26 Nov 2025 16:48:40 +0000 Subject: [PATCH 16/17] fix one line in the code and add two line to print the output --- Sprint-2/implement/tally.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index 54f3eef76..8b09ead0d 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -2,7 +2,9 @@ function tally(items) { if (!Array.isArray(items)) { throw new TypeError('Input must be an array'); } - const tallyResult = {}; + + const tallyResult = Object.create(null); + for (const item of items) { if (tallyResult[item] === undefined) { tallyResult[item] = 1; @@ -10,7 +12,11 @@ function tally(items) { tallyResult[item]++; } } + return tallyResult; } module.exports = tally; + +console.log("Test : tally with 'toString':"); +console.log(tally(["toString", "toString"])); From 54171f942c5fb54a5d7621feddb2ab82d2457e61 Mon Sep 17 00:00:00 2001 From: Alaa Tagi Date: Wed, 26 Nov 2025 17:10:11 +0000 Subject: [PATCH 17/17] fix the function and jest file --- Sprint-2/stretch/mode.js | 33 +++++++++++++++++++++++---------- Sprint-2/stretch/mode.test.js | 25 ++++++++++++++----------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/Sprint-2/stretch/mode.js b/Sprint-2/stretch/mode.js index 3f7609d79..055e5b063 100644 --- a/Sprint-2/stretch/mode.js +++ b/Sprint-2/stretch/mode.js @@ -8,29 +8,42 @@ // refactor calculateMode by splitting up the code // into smaller functions using the stages above -function calculateMode(list) { - // track frequency of each value - let freqs = new Map(); - for (let num of list) { - if (typeof num !== "number") { - continue; - } +// Helper function to count frequency of numbers: +function countFrequencies(list) { + const freqs = new Map(); + + for (const num of list) { + if (typeof num !== "number") continue; freqs.set(num, (freqs.get(num) || 0) + 1); } - // Find the value with the highest frequency + return freqs; +} + +// Helper function to find mode from frequency map: + +function findMode(freqs) { let maxFreq = 0; let mode; - for (let [num, freq] of freqs) { + + for (const [num, freq] of freqs) { if (freq > maxFreq) { - mode = num; maxFreq = freq; + mode = num; } } return maxFreq === 0 ? NaN : mode; } + +// Main function: + +function calculateMode(list) { + const freqs = countFrequencies(list); + return findMode(freqs); +} + module.exports = calculateMode; diff --git a/Sprint-2/stretch/mode.test.js b/Sprint-2/stretch/mode.test.js index 89bcc0ddc..742ada992 100644 --- a/Sprint-2/stretch/mode.test.js +++ b/Sprint-2/stretch/mode.test.js @@ -5,34 +5,37 @@ const calculateMode = require("./mode.js"); // Given an array of numbers // When calculateMode is called on the array // Then it should return the number that appears most frequently in the array - -test("calculateMode is a function ,returns the most frequent number", () => { - const nums = [1, 2, 2, 3, 4]; - - expect(typeof calculateMode).toBe("function"); - expect(calculateMode(nums)).toBe(2); -}); +describe("calculateMode()", () => { + test("is a function and returns the most frequent number", () => { + const nums = [1, 2, 2, 3, 4]; + expect(typeof calculateMode).toBe("function"); + expect(calculateMode(nums)).toBe(2); + }); // Example: // Given [2,4,1,2,3,2,1] // When calculateMode is called on [2,4,1,2,3,2,1] // Then it should return 2 */ -describe("calculateMode()", () => { test("returns the most frequent number in an array", () => { const nums = [2, 4, 1, 2, 3, 2, 1]; - expect(calculateMode(nums)).toEqual(2); }); test("returns the first mode in case of multiple modes", () => { const nums = [1, 2, 2, 3, 3]; - expect(calculateMode(nums)).toEqual(2); }); test("ignores non-number values", () => { const nums = [1, 3, "2", 2, 3, null]; - expect(calculateMode(nums)).toEqual(3); }); + + test("returns NaN for an empty array", () => { + expect(calculateMode([])).toBeNaN(); + }); + + test("returns NaN if array has no numbers", () => { + expect(calculateMode(["a", "b", null])).toBeNaN(); + }); });