diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..4ebe9f50e 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -13,3 +13,5 @@ const address = { }; console.log(`My house number is ${address[0]}`); +//My houseNumber will be undefined +console.log(`My house number is ${address["houseNumber"]}`); diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..5c092528f 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -14,3 +14,7 @@ const author = { for (const value of author) { console.log(value); } +// TypeError, for is not iterable object, it used for arrays. +for (const value of Object.values(author)) { + console.log(value); +} \ No newline at end of file diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..03ce9e808 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -13,3 +13,8 @@ const recipe = { console.log(`${recipe.title} serves ${recipe.serves} ingredients: ${recipe}`); + +// The code will not log the ingredients, only the object. +for (const ingredient of recipe.ingredients) { + console.log(ingredient); +} \ No newline at end of file diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..f6b4a8f47 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,14 @@ -function contains() {} -module.exports = contains; +function contains(object, property) { + if ( + object === null || + typeof object !== "object" || + Array.isArray(object) + ) { + + return false; + } + + return Object.hasOwn(object, property); +} +module.exports = contains; \ No newline at end of file diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..c2e11af7a 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -1,6 +1,6 @@ const contains = require("./contains.js"); -/* +/* Implement a function called contains that checks an object contains a particular property @@ -10,7 +10,7 @@ as the object contains a key of 'a' E.g. contains({a: 1, b: 2}, 'c') // returns false as the object doesn't contains a key of 'c' */ - +const object = { a: 1, b: 2 }; // Acceptance criteria: // Given a contains function @@ -20,16 +20,28 @@ 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", () => { + expect(contains({}, "any")).toBe(false); +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true - +test("contains returns true for existing property", () => { + expect(contains(object, "a")).toBe(true); + expect(contains(object, "b")).toBe(true); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false - +test("contains returns false for non-existent property", () => { + expect(contains(object, "c")).toBe(false); +}); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("contains returns false for invalid input like arrays", () => { + expect(contains([1, 2, 3], "1")).toBe(false); + expect(contains(null, "anything")).toBe(false); + expect(contains(42, "toString")).toBe(false); + expect(contains("string", "length")).toBe(false); +}); \ No newline at end of file diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..3fef171d8 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,9 @@ -function createLookup() { - // implementation here +function createLookup(currencyPairs){ + const lookup = {}; + for (const [countryCode, currencyCode] of currencyPairs) { + 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..74a08a817 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,7 +1,22 @@ 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 countryCurrencyPairs = [ + ['US', 'USD'], + ['CA', 'CAD'], + ['GB', 'GBP'], + ['NG', 'NGN'] + ]; + + const expectedLookup = { + 'US': 'USD', + 'CA': 'CAD', + 'GB': 'GBP', + 'NG': 'NGN', + }; + expect(createLookup(countryCurrencyPairs)).toEqual(expectedLookup); +}); /* Create a lookup object of key value pairs from an array of code pairs @@ -33,3 +48,14 @@ It should return: 'CA': 'CAD' } */ + test('handles mixed data correctly', () => { + const input = [['NG', 'NGN'], ['FR', 'EUR'], ['GB', 'GBP']]; + const expected = { NG: 'NGN', FR: 'EUR', GB: 'GBP' }; + expect(createLookup(input)).toEqual(expected); + }); + + test('returns empty object for empty input', () => { + const input = []; + const expected = {}; + expect(createLookup(input)).toEqual(expected); + }); \ No newline at end of file diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..4f4cf32a6 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,16 +1,17 @@ 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 [key, ...rest] = pair.split("="); + const value = rest.join("="); // Join the rest in case the value contains '=' + queryParams[decodeURIComponent(key)] = decodeURIComponent(value); + } - - return queryParams; + return queryParams; } module.exports = parseQueryString; diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..ac7abd13d 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -10,3 +10,23 @@ test("parses querystring values containing =", () => { "equation": "x=y+1", }); }); +test("parses querystring with multiple values", () => { + expect(parseQueryString("humanleg=2&spider=6&dog=4")).toEqual({ + "humanleg": "2", + "spider": "6", + "dog": "4", + }); +}); +test("parses querystring with empty values", () => { + expect(parseQueryString("a=&b=2&c=")).toEqual({ + "a": "", + "b": "2", + "c": "", + }); +}); +test("parses querystring with special characters", () => { + expect(parseQueryString("name=Mayowa%20Fadare&age=25")).toEqual({ + "name": "Mayowa Fadare", + "age": "25", + }); +}); \ No newline at end of file diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..af3af3016 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 Error("Input must be an array"); + } + const counts = Object.create(null); + for (const item of items) { + if (typeof item !== "string" && typeof item !== "number") { + throw new Error("Items must be strings or numbers"); + } + counts[item] = (counts[item] || 0) + 1; + } + return counts; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..11deccb8e 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -1,4 +1,5 @@ -const tally = require("./tally.js"); +const tally = require("./tally.js") + /** * tally array @@ -19,16 +20,26 @@ const tally = require("./tally.js"); // Given a function called tally // When passed an array of items // Then it should return an object containing the count for each unique item - +test("tally on an array with multiple items returns correct counts", () => { + expect(tally(['a', 'b', 'a', 'c', 'b', 'a'])).toEqual({ + a: 3, b: 2, c: 1 }); +}); // 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 empty object", () => { + expect(tally([])).toEqual({}); +}); // Given an array with duplicate items // When passed to tally // Then it should return counts for each unique item +test("tally on an array with one item returns count of 1", () => { + expect(tally(['a'])).toEqual({ a: 1 }); +}); // Given an invalid input like a string // When passed to tally // Then it should throw an error +test("tally throws error for non-array input", () => { + expect(() => tally("not an array")).toThrow("Input must be an array"); +}); diff --git a/Sprint-2/interpret/invent.test.js b/Sprint-2/interpret/invent.test.js new file mode 100644 index 000000000..986d6dae3 --- /dev/null +++ b/Sprint-2/interpret/invent.test.js @@ -0,0 +1,43 @@ +const invert = require("./invert.js"); + + +// a) What is the current return value when invert is called with { a : 1 } +test("invert returns correct inverted object", () => { + const input = { a: 1, b: 2 }; + const expectedOutput = { '1': 'a', '2': 'b' }; + expect(invert(input)).toEqual(expectedOutput); +}); + +// b) What is the current return value when invert is called with { a: 1, b: 2 } +test("invert with numeric values returns string keys", () => { + const input = { a: 1, b: 2 }; + const expectedOutput = { '1': 'a', '2': 'b' }; + expect(invert(input)).toEqual(expectedOutput); +}); + +// c) What is the target return value when invert is called with {a : 1, b: 2} +test("invert with string values returns correct inverted object", () => { + const input = { a: '1', b: '2' }; + const expectedOutput = { '1': 'a', '2': 'b' }; + expect(invert(input)).toEqual(expectedOutput); +}); + +// c) What does Object.entries return? Why is it needed in this program? +test("Object.entries returns key-value pairs", () => { + const obj = { a: '1', b: '2' }; + const entries = Object.entries(obj); + expect(entries).toEqual([['a', '1'], ['b', '2']]); +}); +// d) Explain why the current return value is different from the target output +test("invert handles numeric values as strings", () => { + const input = { a: 1, b: 2 }; + const expectedOutput = { '1': 'a', '2': 'b' }; + expect(invert(input)).toEqual(expectedOutput); +}); + +// e) Fix the implementation of invert (and write tests to prove it's fixed!) +test("invert handles empty object", () => { + const input = {}; + const expectedOutput = {}; + expect(invert(input)).toEqual(expectedOutput); +}); \ No newline at end of file diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..844f0fc71 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -6,24 +6,35 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} -function invert(obj) { +function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + const stringValue = String(value); // Ensure value is a string + if (invertedObj.hasOwnProperty(value)) { + throw new Error(`Duplicate value found: ${value} for keys ${invertedObj[value]} and ${key}`); + } + invertedObj[stringValue] = key; } - return invertedObj; } -// a) What is the current return value when invert is called with { a : 1 } +module.exports = invert; + +// a) What is the current return value when invert is called with { a : 1 } +//{key : 1} because invertedObj.key means object "invertedObj" has a key property with the exact name "key" and we need to add a key that its name is the value of key property. // b) What is the current return value when invert is called with { a: 1, b: 2 } +//{key : 1, key : 2} because invertedObj.key means object "invertedObj" has a key property with the exact name "key" and we need to add a key that its name is the value of key property. // c) What is the target return value when invert is called with {a : 1, b: 2} +//{1 : a ,2 : b} because invertedObj.key means object "invertedObj" has a key property with the exact name "key" and we need to add a key that its name is the value of key property. -// c) What does Object.entries return? Why is it needed in this program? +// d) What does Object.entries return? Why is it needed in this program? +//Object.entries returns an array of key-value pairs from the object. -// d) Explain why the current return value is different from the target output +// e) Explain why the current return value is different from the target output +//The current return value is different because the keys in the inverted object are being set to the string representation of the original values, while the target output expects the keys to be the original values themselves. -// e) Fix the implementation of invert (and write tests to prove it's fixed!) +// f) Fix the implementation of invert (and write tests to prove it's fixed!) +//The implementation has been fixed to ensure that the values are converted to strings before being used as keys in the inverted object. Additionally, it checks for duplicate values to prevent overwriting keys in the inverted object. \ No newline at end of file diff --git a/Sprint-2/package-lock.json b/Sprint-2/package-lock.json index 9b4c725d6..1e82b54f7 100644 --- a/Sprint-2/package-lock.json +++ b/Sprint-2/package-lock.json @@ -27,14 +27,15 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.7", - "picocolors": "^1.0.0" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -172,9 +173,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { @@ -182,9 +183,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, "license": "MIT", "engines": { @@ -202,121 +203,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", - "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", - "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.8" + "@babel/types": "^7.28.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -565,15 +472,15 @@ } }, "node_modules/@babel/template": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", - "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -599,15 +506,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", - "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1325,9 +1231,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1579,9 +1485,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -3153,9 +3059,9 @@ "license": "MIT" }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -3543,16 +3449,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/Sprint-2/stretch/count-words.js b/Sprint-2/stretch/count-words.js index 8e85d19d7..f5917fc7a 100644 --- a/Sprint-2/stretch/count-words.js +++ b/Sprint-2/stretch/count-words.js @@ -1,7 +1,7 @@ /* Count the number of times a word appears in a given string. - Write a function called countWords that + Write a function called countWords that: - takes a string as an argument - returns an object where - the keys are the words from the string and @@ -20,9 +20,13 @@ ## Advanced challenges -1. Remove all of the punctuation (e.g. ".", ",", "!", "?") to tidy up the results +1. Remove all of the punctuation (e.g. ".", ",", "!", "?") to tidy up the results. + e.g. countWords("Hello, world!") should return { Hello: 1, world: 1 } 2. Ignore the case of the words to find more unique words. e.g. (A === a, Hello === hello) + e.g. countWords("Hello, hello, world!") should return { Hello: 1, world: 1 } -3. Order the results to find out which word is the most common in the input +3. Order the results to find out which word is the most common in the input string. + e.g. countWords("you and me and you") should return { you: 2, and: 2, me: 1 } but sorted by the count of each word. + e.g. countWords("you and me and you") should return { you: 2, and: 2, me: 1 } but sorted by the count of each word. */ diff --git a/Sprint-2/stretch/mode.js b/Sprint-2/stretch/mode.js index 3f7609d79..9edd78e2a 100644 --- a/Sprint-2/stretch/mode.js +++ b/Sprint-2/stretch/mode.js @@ -9,24 +9,31 @@ // into smaller functions using the stages above function calculateMode(list) { - // track frequency of each value - let freqs = new Map(); + const freqs = buildFrequencyMap(list); + return findMostFrequentValue(freqs); +} - for (let num of list) { - if (typeof num !== "number") { - continue; - } +// Stage 1: Frequency mapping +function buildFrequencyMap(list) { + const freqs = new Map(); + for (let 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; +} + +// Stage 2: Determine mode +function findMostFrequentValue(freqs) { let maxFreq = 0; - let mode; + let mode = NaN; + for (let [num, freq] of freqs) { if (freq > maxFreq) { - mode = num; maxFreq = freq; + mode = num; } } diff --git a/Sprint-2/stretch/till.js b/Sprint-2/stretch/till.js index 6a08532e7..ae8225323 100644 --- a/Sprint-2/stretch/till.js +++ b/Sprint-2/stretch/till.js @@ -22,10 +22,17 @@ const till = { }; const totalAmount = totalTill(till); -// a) What is the target output when totalTill is called with the till object +// a) What is the target output when totalTill is called with the till object? +// The target output is the total amount in pounds, formatted as a string with a pound sign +// e.g. "£2.00" // b) Why do we need to use Object.entries inside the for...of loop in this function? +// Object.entries is used to get an array of key-value pairs from the till object, allowing +// us to iterate over each coin and its corresponding quantity. + // c) What does coin * quantity evaluate to inside the for...of loop? +// coin * quantity evaluates to the total value of that type of coin in pence. // d) Write a test for this function to check it works and then fix the implementation of totalTill +// The test should check that totalTill returns the correct total amount in pounds for a given till object.