diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..10965921 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,23 @@ +module.exports = { + env: { + browser: true, + es2021: true, + node: true, + 'jest/globals': true, + }, + extends: [ + 'airbnb-base', + 'plugin:jest/recommended', + ], + parserOptions: { + ecmaVersion: 13, + sourceType: 'module', + }, + rules: { + quotes: ['error', 'single', { avoidEscape: true }], + 'max-len': 0, + 'no-console': 'off', + 'no-plusplus': 'off', + }, + plugins: ['jest'], +}; diff --git a/1-exercises/A-undefined/exercise.js b/1-exercises/A-undefined/exercise.js index 0acfc78d..dfdf00b8 100644 --- a/1-exercises/A-undefined/exercise.js +++ b/1-exercises/A-undefined/exercise.js @@ -9,12 +9,12 @@ For each example, can you explain why we are seeing undefined? */ -// Example 1 +// Example 1 - declaration of variable 'a' doesn't assign a value let a; console.log(a); -// Example 2 +// Example 2 - function is not returning anything function sayHello() { let message = "Hello"; } @@ -23,7 +23,7 @@ let hello = sayHello(); console.log(hello); -// Example 3 +// Example 3 - user argument is not passed to the function function sayHelloToUser(user) { console.log(`Hello ${user}`); } @@ -31,6 +31,6 @@ function sayHelloToUser(user) { sayHelloToUser(); -// Example 4 -let arr = [1,2,3]; +// Example 4 - arr doesn't have a value at index 3 (it only has 0,1,2 indexes) +let arr = [1, 2, 3]; console.log(arr[3]); diff --git a/1-exercises/B-while-loop/exercise.js b/1-exercises/B-while-loop/exercise.js index b459888f..b3408a44 100644 --- a/1-exercises/B-while-loop/exercise.js +++ b/1-exercises/B-while-loop/exercise.js @@ -1,13 +1,19 @@ /* - while loops can be useful when you want to execute some code as long as some condition is true. + while loops can be useful when you want to execute some code as long as some condition is true. Using a while loop, complete the function below so it logs (using console.log) the first n even numbers as a comma-seperated string. The list of numbers should start with 0. n is being passed in as a parameter. */ -function evenNumbers(n) { - // TODO -} +const evenNumbers = (n) => { + let i = 0; + const evens = []; + while (evens.length < n) { + evens.push(i); + i += 2; + } + console.log(evens.join(',')); +}; evenNumbers(3); // should output 0,2,4 evenNumbers(0); // should output nothing diff --git a/1-exercises/C-while-loop-with-array/exercise.js b/1-exercises/C-while-loop-with-array/exercise.js index d584cd75..02d7455f 100644 --- a/1-exercises/C-while-loop-with-array/exercise.js +++ b/1-exercises/C-while-loop-with-array/exercise.js @@ -5,19 +5,23 @@ */ const BIRTHDAYS = [ - "January 7th", - "February 12th", - "April 3rd", - "April 5th", - "May 3rd", - "July 11th", - "July 17th", - "September 28th", - "November 15th" + 'January 7th', + 'February 12th', + 'April 3rd', + 'April 5th', + 'May 3rd', + 'July 11th', + 'July 17th', + 'September 28th', + 'November 15th', ]; -function findFirstJulyBDay(birthdays) { - // TODO -} +const findFirstJulyBDay = (birthdays) => { + let i = 0; + while (i < birthdays.length) { + if (birthdays[i].includes('July')) return birthdays[i]; + i += 1; + } +}; console.log(findFirstJulyBDay(BIRTHDAYS)); // should output "July 11th" diff --git a/1-exercises/D-do-while/exercise.js b/1-exercises/D-do-while/exercise.js index f10d0764..0cb45fd7 100644 --- a/1-exercises/D-do-while/exercise.js +++ b/1-exercises/D-do-while/exercise.js @@ -1,15 +1,24 @@ +/* eslint-disable no-multi-assign */ /* Sometimes when using loops, we'll want to execute the body of the loop at least once. We can make sure this happens by using a do-while loop. - If the condition in a while loop is initially false, the body of the loop will never execute - But in a do-while loop, because the condition is checked after the body, we know that it will always execute at least once - + Using a do-while loop, write a function which returns the sum of the first n even numbers (starting from 0) */ -function evenNumbersSum(n) { - // TODO -} +const evenNumbersSum = (n) => { + let evenNumber = 0; + let count = 0; + let sumEvenNumbers = 0; + do { + sumEvenNumbers += evenNumber; + evenNumber += 2; + count++; + } while (count < n); + return sumEvenNumbers; +}; console.log(evenNumbersSum(3)); // should output 6 console.log(evenNumbersSum(0)); // should output 0 -console.log(evenNumbersSum(10)); // should output 90 \ No newline at end of file +console.log(evenNumbersSum(10)); // should output 90 diff --git a/1-exercises/E-for-loop/exercise1.js b/1-exercises/E-for-loop/exercise1.js index db5fac64..7d2d0bf0 100644 --- a/1-exercises/E-for-loop/exercise1.js +++ b/1-exercises/E-for-loop/exercise1.js @@ -4,11 +4,8 @@ Change the while loop below into a for loop. */ - // Change the below code to use a for loop instead of a while loop. -let i = 0; -while(i < 26) { - console.log(String.fromCharCode(97 + i)); - i++; +for (let i = 0; i < 26; i++) { + console.log(String.fromCharCode(97 + i)); } // The output shouldn't change. diff --git a/1-exercises/E-for-loop/exercise2.js b/1-exercises/E-for-loop/exercise2.js index 081002b2..0657d9d4 100644 --- a/1-exercises/E-for-loop/exercise2.js +++ b/1-exercises/E-for-loop/exercise2.js @@ -11,23 +11,27 @@ */ const WRITERS = [ - "Virginia Woolf", - "Zadie Smith", - "Jane Austen", - "Bell Hooks", - "Yukiko Motoya" -] + 'Virginia Woolf', + 'Zadie Smith', + 'Jane Austen', + 'Bell Hooks', + 'Yukiko Motoya', +]; const AGES = [ - 59, - 40, - 41, - 63, - 49 + 59, + 40, + 41, + 63, + 49, ]; // TODO - Write for loop code here +for (let i = 0; i < WRITERS.length; i++) { + console.log(`${WRITERS[i]} is ${AGES[i]} years old`); +} + /* The output should look something like this: diff --git a/1-exercises/F-for-of-loop/exercise.js b/1-exercises/F-for-of-loop/exercise.js index 65585c6a..d19ad4e0 100644 --- a/1-exercises/F-for-of-loop/exercise.js +++ b/1-exercises/F-for-of-loop/exercise.js @@ -1,16 +1,24 @@ +/* eslint-disable no-restricted-syntax */ /* - A for-of loop is a easy and way of looping through the elements of an array, string or any other "iterable object" (think sequence of elements). + A for-of loop is a easy and way of looping through the elements of an array, string or any other "iterable object" (think sequence of elements). */ // TODO Use a for-of loop to output each of the tube stations below. -let tubeStations = [ - "Aldgate", - "Baker Street", - "Picadilly Circus", - "Oxford Street", - "Tottenham Court Road" +const tubeStations = [ + 'Aldgate', + 'Baker Street', + 'Picadilly Circus', + 'Oxford Street', + 'Tottenham Court Road', ]; +for (const station of tubeStations) { + console.log(station); +} // TODO Use a for-of loop to capitalise and output each letter in the string seperately. -let str = "codeyourfuture"; +const str = 'codeyourfuture'; + +for (const letter of str) { + console.log(letter.toUpperCase()); +} diff --git a/2-mandatory/1-weather-report.js b/2-mandatory/1-weather-report.js index dcc2bdb0..89fd890f 100644 --- a/2-mandatory/1-weather-report.js +++ b/2-mandatory/1-weather-report.js @@ -1,6 +1,6 @@ /* Imagine we're making a weather app! - + We have a list of cities that the user wants to track. We also already have a temperatureService function which will take a city as a parameter and return a temparature. @@ -11,53 +11,50 @@ - Hint: you can call the temperatureService function from your function */ -function getTemperatureReport(cities) { - // TODO -} - +const getTemperatureReport = (cities) => cities.map((e) => `The temperature in ${e} is ${temperatureService(e)} degrees`); /* ======= TESTS - DO NOT MODIFY ===== */ function temperatureService(city) { - let temparatureMap = new Map(); - - temparatureMap.set('London', 10); - temparatureMap.set('Paris', 12); - temparatureMap.set('Barcelona', 17); - temparatureMap.set('Dubai', 27); - temparatureMap.set('Mumbai', 29); - temparatureMap.set('São Paulo', 23); - temparatureMap.set('Lagos', 33); - - return temparatureMap.get(city); + const temparatureMap = new Map(); + + temparatureMap.set('London', 10); + temparatureMap.set('Paris', 12); + temparatureMap.set('Barcelona', 17); + temparatureMap.set('Dubai', 27); + temparatureMap.set('Mumbai', 29); + temparatureMap.set('São Paulo', 23); + temparatureMap.set('Lagos', 33); + + return temparatureMap.get(city); } test("should return a temperature report for the user's cities", () => { - let usersCities = [ - "London", - "Paris", - "São Paulo" - ] - - expect(getTemperatureReport(usersCities)).toEqual([ - "The temperature in London is 10 degrees", - "The temperature in Paris is 12 degrees", - "The temperature in São Paulo is 23 degrees" - ]); + const usersCities = [ + 'London', + 'Paris', + 'São Paulo', + ]; + + expect(getTemperatureReport(usersCities)).toEqual([ + 'The temperature in London is 10 degrees', + 'The temperature in Paris is 12 degrees', + 'The temperature in São Paulo is 23 degrees', + ]); }); test("should return a temperature report for the user's cities (alternate input)", () => { - let usersCities = [ - "Barcelona", - "Dubai" - ] - - expect(getTemperatureReport(usersCities)).toEqual([ - "The temperature in Barcelona is 17 degrees", - "The temperature in Dubai is 27 degrees" - ]); + const usersCities = [ + 'Barcelona', + 'Dubai', + ]; + + expect(getTemperatureReport(usersCities)).toEqual([ + 'The temperature in Barcelona is 17 degrees', + 'The temperature in Dubai is 27 degrees', + ]); }); test("should return an empty array if the user hasn't selected any cities", () => { - expect(getTemperatureReport([])).toEqual([]); -}); \ No newline at end of file + expect(getTemperatureReport([])).toEqual([]); +}); diff --git a/2-mandatory/2-retrying-random-numbers.js b/2-mandatory/2-retrying-random-numbers.js index 10aab37d..42bdae6e 100644 --- a/2-mandatory/2-retrying-random-numbers.js +++ b/2-mandatory/2-retrying-random-numbers.js @@ -5,20 +5,24 @@ // This function shouldn't be changed function generateRandomNumber() { - console.log("Generating number..."); - return Math.round(Math.random() * 100); + console.log('Generating number...'); + return Math.round(Math.random() * 100); } -function getRandomNumberGreaterThan50() { - // TODO - implement using a do-while loop -} +const getRandomNumberGreaterThan50 = () => { + let number = 0; + do { + number = generateRandomNumber(); + } while (number <= 50); + return number; +}; /* ======= TESTS - DO NOT MODIFY ===== */ -test("Returned value should always be greater than 50", () => { - expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); - expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); - expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); - expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); - expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); +test('Returned value should always be greater than 50', () => { + expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); + expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); + expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); + expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); + expect(getRandomNumberGreaterThan50()).toBeGreaterThan(50); }); diff --git a/2-mandatory/3-financial-times.js b/2-mandatory/3-financial-times.js index 2ce6fb73..b5ac86b2 100644 --- a/2-mandatory/3-financial-times.js +++ b/2-mandatory/3-financial-times.js @@ -1,81 +1,104 @@ +/* eslint-disable no-restricted-syntax */ /* Imagine you are working on the Financial Times web site! They have a list of article titles stored in an array. The home page of the web site has a headline section, which only has space for article titles which are 65 characters or less. Implement the function below, which will return a new array containing only article titles which will fit. */ -function potentialHeadlines(allArticleTitles) { - // TODO -} +const potentialHeadlines = (allArticleTitles) => { + const answer = []; + for (const articleTitle of allArticleTitles) { + if (articleTitle.length <= 65) { + answer.push(articleTitle); + } + } + return answer; +}; /* The editor of the FT likes short headlines with only a few words! Implement the function below, which returns the title with the fewest words. (you can assume words will always be seperated by a space) */ -function titleWithFewestWords(allArticleTitles) { - // TODO -} +const titleWithFewestWords = (allArticleTitles) => { + let minLen = allArticleTitles[0].split(' ').length; + let index = 0; + for (let i = 1; i < allArticleTitles.length; i++) { + if (allArticleTitles[i].split(' ').length < minLen) { + minLen = allArticleTitles[i].split(' ').length; + index = i; + } + } + return allArticleTitles[index]; +}; /* The editor of the FT has realised that headlines which have numbers in them get more clicks! Implement the function below to return a new array containing all the headlines which contain a number. (Hint: remember that you can also loop through the characters of a string if you need to) */ -function headlinesWithNumbers(allArticleTitles) { - // TODO -} +const headlinesWithNumbers = (allArticleTitles) => { + const answer = []; + for (const articleTitle of allArticleTitles) { + if (/[0-9]/g.test(articleTitle)) { + answer.push(articleTitle); + } + } + return answer; +}; /* The Financial Times wants to understand what the average number of characters in an article title is. Implement the function below to return this number - rounded to the nearest integer. */ -function averageNumberOfCharacters(allArticleTitles) { - // TODO -} - - +const averageNumberOfCharacters = (allArticleTitles) => { + let totalChars = 0; + for (const articleTitle of allArticleTitles) { + totalChars += articleTitle.length; + } + return Math.round(totalChars / allArticleTitles.length); +}; /* ======= List of Articles - DO NOT MODIFY ===== */ const ARTICLE_TITLES = [ - "Streaming wars drive media groups to spend more than $100bn on new content", - "Amazon Prime Video India country head: streaming is driving a TV revolution", - "Aerospace chiefs prepare for bumpy ride in recovery of long-haul flights", - "British companies look to muscle in on US retail investing boom", - "Libor to take firm step towards oblivion on New Year's Day", - "Audit profession unattractive to new recruits, says PwC boss", - "Chinese social media users blast Elon Musk over near miss in space", - "Companies raise over $12tn in 'blockbuster' year for global capital markets", - "The three questions that dominate investment", - "Brussels urges Chile's incoming president to endorse EU trade deal", + 'Streaming wars drive media groups to spend more than $100bn on new content', + 'Amazon Prime Video India country head: streaming is driving a TV revolution', + 'Aerospace chiefs prepare for bumpy ride in recovery of long-haul flights', + 'British companies look to muscle in on US retail investing boom', + "Libor to take firm step towards oblivion on New Year's Day", + 'Audit profession unattractive to new recruits, says PwC boss', + 'Chinese social media users blast Elon Musk over near miss in space', + "Companies raise over $12tn in 'blockbuster' year for global capital markets", + 'The three questions that dominate investment', + "Brussels urges Chile's incoming president to endorse EU trade deal", ]; /* ======= TESTS - DO NOT MODIFY ===== */ -test("should only return potential headlines", () => { - expect(new Set(potentialHeadlines(ARTICLE_TITLES))).toEqual(new Set([ - "British companies look to muscle in on US retail investing boom", - "Libor to take firm step towards oblivion on New Year's Day", - "Audit profession unattractive to new recruits, says PwC boss", - "The three questions that dominate investment" - ])); +test('should only return potential headlines', () => { + expect(new Set(potentialHeadlines(ARTICLE_TITLES))).toEqual(new Set([ + 'British companies look to muscle in on US retail investing boom', + "Libor to take firm step towards oblivion on New Year's Day", + 'Audit profession unattractive to new recruits, says PwC boss', + 'The three questions that dominate investment', + ])); }); -test("should return an empty array for empty input", () => { - expect(potentialHeadlines([])).toEqual([]); +test('should return an empty array for empty input', () => { + expect(potentialHeadlines([])).toEqual([]); }); -test("should return the title with the fewest words", () => { - expect(titleWithFewestWords(ARTICLE_TITLES)).toEqual("The three questions that dominate investment"); +test('should return the title with the fewest words', () => { + expect(titleWithFewestWords(ARTICLE_TITLES)).toEqual('The three questions that dominate investment'); }); -test("should only return headlines containing numbers", () => { - expect(new Set(headlinesWithNumbers(ARTICLE_TITLES))).toEqual(new Set([ - "Streaming wars drive media groups to spend more than $100bn on new content", - "Companies raise over $12tn in 'blockbuster' year for global capital markets" - ])); +test('should only return headlines containing numbers', () => { + expect(new Set(headlinesWithNumbers(ARTICLE_TITLES))).toEqual(new Set([ + 'Streaming wars drive media groups to spend more than $100bn on new content', + "Companies raise over $12tn in 'blockbuster' year for global capital markets", + ])); }); -test("should return the average number of characters in a headline", () => { - expect(averageNumberOfCharacters(ARTICLE_TITLES)).toEqual(65); +test('should return the average number of characters in a headline', () => { + expect(averageNumberOfCharacters(ARTICLE_TITLES)).toEqual(65); }); diff --git a/2-mandatory/4-stocks-V2-with-arrow-Functions.js b/2-mandatory/4-stocks-V2-with-arrow-Functions.js new file mode 100644 index 00000000..e84df462 --- /dev/null +++ b/2-mandatory/4-stocks-V2-with-arrow-Functions.js @@ -0,0 +1,89 @@ +/* + THESE EXERCISES ARE QUITE HARD. JUST DO YOUR BEST, AND COME WITH QUESTIONS IF YOU GET STUCK :) + + Imagine we a working for a finance company. Below we have: + - an array of stock tickers + - an array of arrays containing the closing price for each stock in each of the last 5 days. + For example, CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS[2] contains the prices for the last 5 days for STOCKS[2] (which is amzn) +*/ + +/* ======= Stock data - DO NOT MODIFY ===== */ +const STOCKS = ['aapl', 'msft', 'amzn', 'googl', 'tsla']; + +const CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS = [ + [179.19, 180.33, 176.28, 175.64, 172.99], // AAPL + [340.69, 342.45, 334.69, 333.20, 327.29], // MSFT + [3384.44, 3393.39, 3421.37, 3420.74, 3408.34], // AMZN + [2951.88, 2958.13, 2938.33, 2928.30, 2869.45], // GOOGL + [1101.30, 1093.94, 1067.00, 1008.87, 938.53], // TSLA +]; + +/* + We want to understand what the average price over the last 5 days for each stock is. + Implement the below function, which + - Takes this CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS array as input (remember, it's an array of arrays) + - Returns an array containing the average price over the last 5 days for each stock. + For example, the first element of the resulting array should contain Apple’s (aapl) average stock price for the last 5 days. + The second element should be Microsoft's (msft) average price, and so on. + The average value should be rounded to 2 decimal places, and should be a number (not a string) + + Hint 1: To calculate the average of a set of values, you can add them together and divide by the number of values. + So the average of 5, 10 and 20 is (5 + 10 + 20) / 3 = 11.67 + Hint 2: If the problem seems complex, try breaking it down into smaller problems. + Solve the smaller problems, and then build those solutions back up to solve the larger problem. + Functions can help with this! +*/ + +const getAveragePrices = (arr) => arr.map((e) => Math.round((e.reduce((a, i) => a + i, 0) / e.length) * 100) / 100); + +/* + We also want to see what the change in price is from the first day to the last day for each stock. + Implement the below function, which + - Takes this CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS array as input (remember, it's an array of arrays) + - Returns an array containing the price change over the last 5 days for each stock. + For example, the first element of the resulting array should contain Apple’s (aapl) price change for the last 5 days. + In this example it would be: + (Apple's price on the 5th day) - (Apple's price on the 1st day) = 172.99 - 179.19 = -6.2 + The price change value should be rounded to 2 decimal places, and should be a number (not a string) +*/ + +const getPriceChanges = (arr) => arr.map((e) => Math.round((e[e.length - 1] - e[0]) * 100) / 100); + +/* + As part of a financial report, we want to see what the highest price was for each stock in the last 5 days. + Implement the below function, which + - Takes 2 parameters: + - the CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS array as input (remember, it's an array of arrays) + - the STOCKS array + - Returns an array of strings describing what the highest price was for each stock. + For example, the first element of the array should be: "The highest price of AAPL in the last 5 days was 180.33" + The test will check for this exact string. + The stock ticker should be capitalised. + The price should be shown with exactly 2 decimal places. +*/ +const highestPriceDescriptions = (closingPricesForAllStocks, stocks) => closingPricesForAllStocks.map((e, i) => `The highest price of ${stocks[i].toUpperCase()} in the last 5 days was ${Math.max(...e).toFixed(2)}`); + +/* ======= TESTS - DO NOT MODIFY ===== */ +test('should return the average price for each stock', () => { + expect(getAveragePrices(CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS)).toEqual( + [176.89, 335.66, 3405.66, 2929.22, 1041.93], + ); +}); + +test('should return the price change for each stock', () => { + expect(getPriceChanges(CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS)).toEqual( + [-6.2, -13.4, 23.9, -82.43, -162.77], + ); +}); + +test('should return a description of the highest price for each stock', () => { + expect(highestPriceDescriptions(CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS, STOCKS)).toEqual( + [ + 'The highest price of AAPL in the last 5 days was 180.33', + 'The highest price of MSFT in the last 5 days was 342.45', + 'The highest price of AMZN in the last 5 days was 3421.37', + 'The highest price of GOOGL in the last 5 days was 2958.13', + 'The highest price of TSLA in the last 5 days was 1101.30', + ], + ); +}); diff --git a/2-mandatory/4-stocks.js b/2-mandatory/4-stocks.js index 72d62f94..a82c6ee3 100644 --- a/2-mandatory/4-stocks.js +++ b/2-mandatory/4-stocks.js @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-syntax */ /* THESE EXERCISES ARE QUITE HARD. JUST DO YOUR BEST, AND COME WITH QUESTIONS IF YOU GET STUCK :) @@ -8,21 +9,21 @@ */ /* ======= Stock data - DO NOT MODIFY ===== */ -const STOCKS = ["aapl", "msft", "amzn", "googl", "tsla"]; +const STOCKS = ['aapl', 'msft', 'amzn', 'googl', 'tsla']; const CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS = [ - [179.19, 180.33, 176.28, 175.64, 172.99], // AAPL - [340.69, 342.45, 334.69, 333.20, 327.29], // MSFT - [3384.44, 3393.39, 3421.37, 3420.74, 3408.34], // AMZN - [2951.88, 2958.13, 2938.33, 2928.30, 2869.45], // GOOGL - [1101.30, 1093.94, 1067.00, 1008.87, 938.53] // TSLA + [179.19, 180.33, 176.28, 175.64, 172.99], // AAPL + [340.69, 342.45, 334.69, 333.20, 327.29], // MSFT + [3384.44, 3393.39, 3421.37, 3420.74, 3408.34], // AMZN + [2951.88, 2958.13, 2938.33, 2928.30, 2869.45], // GOOGL + [1101.30, 1093.94, 1067.00, 1008.87, 938.53], // TSLA ]; /* We want to understand what the average price over the last 5 days for each stock is. Implement the below function, which - Takes this CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS array as input (remember, it's an array of arrays) - - Returns an array containing the average price over the last 5 days for each stock. + - Returns an array containing the average price over the last 5 days for each stock. For example, the first element of the resulting array should contain Apple’s (aapl) average stock price for the last 5 days. The second element should be Microsoft's (msft) average price, and so on. The average value should be rounded to 2 decimal places, and should be a number (not a string) @@ -33,9 +34,19 @@ const CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS = [ Solve the smaller problems, and then build those solutions back up to solve the larger problem. Functions can help with this! */ -function getAveragePrices(closingPricesForAllStocks) { - // TODO -} +const getAveragePrices = (closingPricesForAllStocks) => { + const averages = []; + for (const stock of closingPricesForAllStocks) { + let average = 0; + for (const stockPrice of stock) { + average += stockPrice; + } + averages.push(Math.round((average / 5) * 100) / 100); + } + return averages; +}; + +const getAveragePricesV2 = (arr) => arr.map((e) => Math.round((e.reduce((a, i) => a + i, 0) / 5) * 100) / 100); /* We also want to see what the change in price is from the first day to the last day for each stock. @@ -47,9 +58,14 @@ function getAveragePrices(closingPricesForAllStocks) { (Apple's price on the 5th day) - (Apple's price on the 1st day) = 172.99 - 179.19 = -6.2 The price change value should be rounded to 2 decimal places, and should be a number (not a string) */ -function getPriceChanges(closingPricesForAllStocks) { - // TODO -} +const getPriceChanges = (closingPricesForAllStocks) => { + const differences = []; + for (const stock of closingPricesForAllStocks) { + const difference = stock[4] - stock[0]; + differences.push(Math.round(difference * 100) / 100); + } + return differences; +}; /* As part of a financial report, we want to see what the highest price was for each stock in the last 5 days. @@ -63,32 +79,35 @@ function getPriceChanges(closingPricesForAllStocks) { The stock ticker should be capitalised. The price should be shown with exactly 2 decimal places. */ -function highestPriceDescriptions(closingPricesForAllStocks, stocks) { - // TODO -} - +const highestPriceDescriptions = (closingPricesForAllStocks, stocks) => { + const answer = []; + for (let i = 0; i < closingPricesForAllStocks.length; i++) { + answer.push(`The highest price of ${stocks[i].toUpperCase()} in the last 5 days was ${Math.max(...closingPricesForAllStocks[i]).toFixed(2)}`); + } + return answer; +}; /* ======= TESTS - DO NOT MODIFY ===== */ -test("should return the average price for each stock", () => { - expect(getAveragePrices(CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS)).toEqual( - [176.89, 335.66, 3405.66, 2929.22, 1041.93] - ); +test('should return the average price for each stock', () => { + expect(getAveragePrices(CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS)).toEqual( + [176.89, 335.66, 3405.66, 2929.22, 1041.93], + ); }); -test("should return the price change for each stock", () => { - expect(getPriceChanges(CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS)).toEqual( - [-6.2, -13.4, 23.9, -82.43, -162.77] - ); +test('should return the price change for each stock', () => { + expect(getPriceChanges(CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS)).toEqual( + [-6.2, -13.4, 23.9, -82.43, -162.77], + ); }); -test("should return a description of the highest price for each stock", () => { - expect(highestPriceDescriptions(CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS, STOCKS)).toEqual( - [ - "The highest price of AAPL in the last 5 days was 180.33", - "The highest price of MSFT in the last 5 days was 342.45", - "The highest price of AMZN in the last 5 days was 3421.37", - "The highest price of GOOGL in the last 5 days was 2958.13", - "The highest price of TSLA in the last 5 days was 1101.30" - ] - ); +test('should return a description of the highest price for each stock', () => { + expect(highestPriceDescriptions(CLOSING_PRICES_LAST_5_DAYS_FOR_ALL_STOCKS, STOCKS)).toEqual( + [ + 'The highest price of AAPL in the last 5 days was 180.33', + 'The highest price of MSFT in the last 5 days was 342.45', + 'The highest price of AMZN in the last 5 days was 3421.37', + 'The highest price of GOOGL in the last 5 days was 2958.13', + 'The highest price of TSLA in the last 5 days was 1101.30', + ], + ); }); diff --git a/3-extra/1-factorial.js b/3-extra/1-factorial.js index 31f8052c..b792fca7 100644 --- a/3-extra/1-factorial.js +++ b/3-extra/1-factorial.js @@ -4,24 +4,28 @@ For example, 3! is 6 (because 3 * 2 * 1 = 6) 5! is 120 (because 5 * 4 * 3 * 2 * 1 = 120) - - Using a loop, complete the function below so it returns the factorial of the number being passed in. + + Using a loop, complete the function below so it returns the factorial of the number being passed in. */ -function factorial(input) { - // TODO -} +const factorial = (input) => { + let answer = 1; + for (let i = 2; i <= input; i++) { + answer *= i; + } + return answer; +}; /* ======= TESTS - DO NOT MODIFY ===== */ -test("3! should be 6", () => { - expect(factorial(3)).toEqual(6); +test('3! should be 6', () => { + expect(factorial(3)).toEqual(6); }); -test("5! should be 120", () => { - expect(factorial(5)).toEqual(120); +test('5! should be 120', () => { + expect(factorial(5)).toEqual(120); }); -test("10! should be 3628800", () => { - expect(factorial(10)).toEqual(3628800); +test('10! should be 3628800', () => { + expect(factorial(10)).toEqual(3628800); }); diff --git a/3-extra/2-array-of-objects.js b/3-extra/2-array-of-objects.js index ee57960f..ae479ca1 100644 --- a/3-extra/2-array-of-objects.js +++ b/3-extra/2-array-of-objects.js @@ -1,82 +1,90 @@ +/* eslint-disable no-restricted-syntax */ /* This exercise includes an array of objects. You can read more about objects here: https://javascript.info/object Imagine you're working for an online store selling books (like Amazon). Below, we have an array of book objects. Each object contains the title of the book, the genre, and a rating based on user reviews. - + We want to find the title of the highest rated book in each genre to showcase on our home page. Implement a function which takes the array of books as a parameter, and returns an array of book titles. Each title in the resulting array should be the highest rated book in its genre. */ -function getHighestRatedInEachGenre(books) { - // TODO -} - +const getHighestRatedInEachGenre = (books) => { + const answer = {}; + for (const book of books) { + if (!answer[book.genre] || answer[book.genre].rating < book.rating) { + answer[book.genre] = { + title: book.title, + rating: book.rating, + }; + } + } + return Object.values(answer).map((e) => e.title); +}; /* ======= Book data - DO NOT MODIFY ===== */ const BOOKS = [ - { - title: "The Lion, the Witch and the Wardrobe", - genre: "children", - rating: 4.7 - }, - { - title: "Sapiens: A Brief History of Humankind", - genre: "non-fiction", - rating: 4.7 - }, - { - title: "Nadiya's Fast Flavours", - genre: "cooking", - rating: 4.7 - }, - { - title: "Harry Potter and the Philosopher's Stone", - genre: "children", - rating: 4.8 - }, - { - title: "A Life on Our Planet", - genre: "non-fiction", - rating: 4.8 - }, - { - title: "Dishoom: The first ever cookbook from the much-loved Indian restaurant", - genre: "cooking", - rating: 4.85 - }, - { - title: "Gangsta Granny Strikes Again!", - genre: "children", - rating: 4.9 - }, - { - title: "Diary of a Wimpy Kid", - genre: "children", - rating: 4.6 - }, - { - title: "BOSH!: Simple recipes. Unbelievable results. All plants.", - genre: "cooking", - rating: 4.6 - }, - { - title: "The Book Your Dog Wishes You Would Read", - genre: "non-fiction", - rating: 4.85 - }, -] - + { + title: 'The Lion, the Witch and the Wardrobe', + genre: 'children', + rating: 4.7, + }, + { + title: 'Sapiens: A Brief History of Humankind', + genre: 'non-fiction', + rating: 4.7, + }, + { + title: "Nadiya's Fast Flavours", + genre: 'cooking', + rating: 4.7, + }, + { + title: "Harry Potter and the Philosopher's Stone", + genre: 'children', + rating: 4.8, + }, + { + title: 'A Life on Our Planet', + genre: 'non-fiction', + rating: 4.8, + }, + { + title: 'Dishoom: The first ever cookbook from the much-loved Indian restaurant', + genre: 'cooking', + rating: 4.85, + }, + { + title: 'Gangsta Granny Strikes Again!', + genre: 'children', + rating: 4.9, + }, + { + title: 'Diary of a Wimpy Kid', + genre: 'children', + rating: 4.6, + }, + { + title: 'BOSH!: Simple recipes. Unbelievable results. All plants.', + genre: 'cooking', + rating: 4.6, + }, + { + title: 'The Book Your Dog Wishes You Would Read', + genre: 'non-fiction', + rating: 4.85, + }, +]; /* ======= TESTS - DO NOT MODIFY ===== */ -test("should return the highest rated book in each genre", () => { - expect(new Set(getHighestRatedInEachGenre(BOOKS))).toEqual(new Set( - [ - "The Book Your Dog Wishes You Would Read", - "Gangsta Granny Strikes Again!", - "Dishoom: The first ever cookbook from the much-loved Indian restaurant" - ] - )); -}); \ No newline at end of file +test('should return the highest rated book in each genre', () => { + expect(new Set(getHighestRatedInEachGenre(BOOKS))).toEqual(new Set( + [ + 'The Book Your Dog Wishes You Would Read', + 'Gangsta Granny Strikes Again!', + 'Dishoom: The first ever cookbook from the much-loved Indian restaurant', + ], + )); +}); diff --git a/3-extra/3-fibonacci.js b/3-extra/3-fibonacci.js index 9ef9aec7..13075c4f 100644 --- a/3-extra/3-fibonacci.js +++ b/3-extra/3-fibonacci.js @@ -1,8 +1,8 @@ /* The Fibonacci Sequence is a famous sequence of numbers. Read more here: https://www.mathsisfun.com/numbers/fibonacci-sequence.html - + The sequence starts with 0 and 1. Each number after that, is the sum of the previous 2 numbers in the sequence. - So the third number in the sequence is 1, because 0 + 1 = 1. + So the third number in the sequence is 1, because 0 + 1 = 1. Now we have 0, 1, 1. The fourth number in the sequence is 2, because 1 + 1 = 2. (the last 2 numbers in the sequence were 1 and 1) Now we have 0, 1, 1, 2. @@ -13,25 +13,29 @@ - the input n will be passed in to the function as an argument, and will be a number greater than 2 */ -function generateFibonacciSequence(n) { - // TODO -} +const generateFibonacciSequence = (n) => { + const answer = [0, 1]; + for (let i = 2; i < n; i++) { + answer.push(answer[i - 1] + answer[i - 2]); + } + return answer; +}; /* ======= TESTS - DO NOT MODIFY ===== */ -test("should return the first 10 numbers in the Fibonacci Sequence", () => { - expect(generateFibonacciSequence(10)).toEqual( - [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] - ); +test('should return the first 10 numbers in the Fibonacci Sequence', () => { + expect(generateFibonacciSequence(10)).toEqual( + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34], + ); }); -test("should return the first 5 numbers in the Fibonacci Sequence", () => { - expect(generateFibonacciSequence(5)).toEqual( - [0, 1, 1, 2, 3] - ); +test('should return the first 5 numbers in the Fibonacci Sequence', () => { + expect(generateFibonacciSequence(5)).toEqual( + [0, 1, 1, 2, 3], + ); }); -test("should return the first 15 numbers in the Fibonacci Sequence", () => { - expect(generateFibonacciSequence(15)).toEqual( - [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377] - ); -}); \ No newline at end of file +test('should return the first 15 numbers in the Fibonacci Sequence', () => { + expect(generateFibonacciSequence(15)).toEqual( + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377], + ); +}); diff --git a/package.json b/package.json index dc4e9ace..268ab4e9 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,10 @@ }, "homepage": "https://github.com/CodeYourFuture/JavaScript-Core-1-Coursework-Week3#readme", "devDependencies": { + "eslint": "^8.6.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^25.3.4", "jest": "^26.6.3" } }