diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..25549074 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint", + "streetsidesoftware.code-spell-checker", + "eamodio.gitlens", + "ritwickdey.LiveServer", + "vsliveshare.vsliveshare" + ] +} diff --git a/week-3/debug/format-as-12-hours.js b/week-3/debug/format-as-12-hours.js index 56b83a5b..b59c277c 100644 --- a/week-3/debug/format-as-12-hours.js +++ b/week-3/debug/format-as-12-hours.js @@ -26,5 +26,81 @@ console.assert( // formatAs12HourClock currently has a 🐛 // a) Write an assertion to check the return value of formatAs12HourClock when it is called with an input "17:42" +const currentOutput3 = formatAs12HourClock("17:42"); +const targetOutput3 = "5:42 pm"; +console.assert( + currentOutput3 === targetOutput3, + "current output: %s, target output: %s", + currentOutput3, + targetOutput3 +); + + + // b) Check the assertion output and explain what the bug is +//Bug: The current implementation does not properly handle the following: + +//Times where the minutes (:mm) are non-zero (e.g., "17:42"). +//Times within the 12-hour range (like "08:00") are incorrectly labeled am without checking the context of midnight or noon. +//Times at the hour of 12 (e.g., "12:00" or "00:00") do not follow 12-hour clock conventions. + + // c) Now fix the bug and re-run all your assertions +function formatAs12HourClock(time) { + const hours = Number(time.slice(0, 2)); + const minutes = time.slice(3); // Extract the `:mm` part + if (hours === 0) { + return `12:${minutes} am`; // Midnight case + } else if (hours === 12) { + return `12:${minutes} pm`; // Noon case + } else if (hours > 12) { + return `${hours - 12}:${minutes} pm`; // Afternoon case + } + return `${time} am`; // Morning case +} + +// Assertions +const currentOutput = formatAs12HourClock("08:00"); +const targetOutput = "08:00 am"; +console.assert( + currentOutput === targetOutput, + "current output: %s, target output: %s", + currentOutput, + targetOutput +); + +const currentOutput2 = formatAs12HourClock("23:00"); +const targetOutput2 = "11:00 pm"; +console.assert( + currentOutput2 === targetOutput2, + "current output: %s, target output: %s", + currentOutput2, + targetOutput2 +); + +const currentOutput3 = formatAs12HourClock("17:42"); +const targetOutput3 = "5:42 pm"; +console.assert( + currentOutput3 === targetOutput3, + "current output: %s, target output: %s", + currentOutput3, + targetOutput3 +); + +const currentOutput4 = formatAs12HourClock("00:00"); +const targetOutput4 = "12:00 am"; +console.assert( + currentOutput4 === targetOutput4, + "current output: %s, target output: %s", + currentOutput4, + targetOutput4 +); + +const currentOutput5 = formatAs12HourClock("12:00"); +const targetOutput5 = "12:00 pm"; +console.assert( + currentOutput5 === targetOutput5, + "current output: %s, target output: %s", + currentOutput5, + targetOutput5 +); diff --git a/week-3/implement/get-angle-type.js b/week-3/implement/get-angle-type.js index 9dd3a210..bd0f7c64 100644 --- a/week-3/implement/get-angle-type.js +++ b/week-3/implement/get-angle-type.js @@ -1,23 +1,40 @@ -// Implement a function getAngleType, and tests for each of the acceptance criteria. +// Test cases +console.assert( + getAngleType(90) === "Right angle", + "Test failed: Expected 'Right angle' for input 90" +); -// Acceptance criteria: +console.assert( + getAngleType(45) === "Acute angle", + "Test failed: Expected 'Acute angle' for input 45" +); -// Identify Right Angles: -// When the angle is exactly 90 degrees, -// Then the function should return "Right angle" +console.assert( + getAngleType(135) === "Obtuse angle", + "Test failed: Expected 'Obtuse angle' for input 135" +); -// Identify Acute Angles: -// When the angle is less than 90 degrees, -// Then the function should return "Acute angle" +console.assert( + getAngleType(180) === "Straight angle", + "Test failed: Expected 'Straight angle' for input 180" +); -// Identify Obtuse Angles: -// When the angle is greater than 90 degrees and less than 180 degrees, -// Then the function should return "Obtuse angle" +console.assert( + getAngleType(270) === "Reflex angle", + "Test failed: Expected 'Reflex angle' for input 270" +); -// Identify Straight Angles: -// When the angle is exactly 180 degrees, -// Then the function should return "Straight angle" +console.assert( + getAngleType(0) === "Acute angle", + "Test failed: Expected 'Acute angle' for input 0" +); -// Identify Reflex Angles: -// When the angle is greater than 180 degrees and less than 360 degrees, -// Then the function should return "Reflex angle" +console.assert( + getAngleType(360) === "Invalid angle", + "Test failed: Expected 'Invalid angle' for input 360" +); + +console.assert( + getAngleType(-45) === "Invalid angle", + "Test failed: Expected 'Invalid angle' for input -45" +); diff --git a/week-3/implement/get-card-value.js b/week-3/implement/get-card-value.js index 0dd74fbc..8846f868 100644 --- a/week-3/implement/get-card-value.js +++ b/week-3/implement/get-card-value.js @@ -1,31 +1,39 @@ -// This problem involves playing cards: https://en.wikipedia.org/wiki/Standard_52-card_deck - -// You will need to implement a function getCardValue - -// You need to write assertions for your function to check it works in different cases - -// Acceptance criteria: - -// Given a card string in the format "A♠" (representing a card in blackjack), -// When the function getCardValue is called with this card string as input, -// Then it should return the numerical card value - -// Handle Number Cards (2-10): -// Given a card with a rank between "2" and "10", -// When the function is called with such a card, -// Then it should return the numeric value corresponding to the rank (e.g., "5" should return 5). - -// Handle Face Cards (J, Q, K): -// Given a card with a rank of "J," "Q," or "K", -// When the function is called with such a card, -// Then it should return the value 10, as these cards are worth 10 points each in blackjack. - -// Handle Ace (A): -// Given a card with a rank of "A", -// When the function is called with an Ace, -// Then it should, by default, assume the Ace is worth 11 points, which is a common rule in blackjack. - -// Handle Invalid Cards: -// Given a card with an invalid rank (neither a number nor a recognized face card), -// When the function is called with such a card, -// Then it should throw an error indicating "Invalid card rank." +function getCardValue(card) { + const rank = card.slice(0, -1); + if (!isNaN(rank)) { + // Handle number cards + const num = parseInt(rank); + if (num >= 2 && num <= 10) { + return num; + } + } else if (rank === "J" || rank === "Q" || rank === "K") { + // Handle face cards + return 10; + } else if (rank === "A") { + // Handle Ace + return 11; + } else { + // Handle invalid cards + throw new Error("Invalid card rank."); + } +} +// Test number cards +console.assert(getCardValue("2♠") === 2, "Test Case 1 Failed"); +console.assert(getCardValue("5♦") === 5, "Test Case 2 Failed"); +console.assert(getCardValue("10♣") === 10, "Test Case 3 Failed"); + +// Test face cards +console.assert(getCardValue("J♠") === 10, "Test Case 4 Failed"); +console.assert(getCardValue("Q♦") === 10, "Test Case 5 Failed"); +console.assert(getCardValue("K♣") === 10, "Test Case 6 Failed"); + +// Test Ace +console.assert(getCardValue("A♥") === 11, "Test Case 7 Failed"); + +// Test invalid card +try { + getCardValue("Z♠"); + console.assert(false, "Test Case 8 Failed"); +} catch (e) { + console.assert(e.message === "Invalid card rank.", "Test Case 8 Passed"); +} diff --git a/week-3/implement/is-proper-fraction.js b/week-3/implement/is-proper-fraction.js index 31da32b5..bfed988c 100644 --- a/week-3/implement/is-proper-fraction.js +++ b/week-3/implement/is-proper-fraction.js @@ -1,35 +1,29 @@ -// You wil need to implement a function isProperFraction -// You need to write assertions for your function to check it works in different cases - -// Terms: -// Fractions: https://www.bbc.co.uk/bitesize/topics/zt9n6g8/articles/zjxpp4j -// Written here like this: 1/2 == Numerator/Denominator - -// Acceptance criteria: - -// Proper Fraction check: -// Input: numerator = 2, denominator = 3 -// target output: true -// Explanation: The fraction 2/3 is a proper fraction, where the numerator is less than the denominator. The function should return true. - -// Improper Fraction check: -// Input: numerator = 5, denominator = 2 -// target output: false -// Explanation: The fraction 5/2 is an improper fraction, where the numerator is greater than or equal to the denominator. The function should return false. - -// Zero Denominator check: -// Input: numerator = 3, denominator = 0 -// No target output: Error (Denominator cannot be zero) -// Explanation: The function should throw an error when the denominator is zero, as it's not a valid fraction. - -// Negative Fraction check: -// Input: numerator = -4, denominator = 7 -// target output: true -// Explanation: The fraction -4/7 is a proper fraction because the absolute value of the numerator (4) is less than the denominator (7). The function should return true. - -// Equal Numerator and Denominator check: -// Input: numerator = 3, denominator = 3 -// target output: false -// Explanation: The fraction 3/3 is not a proper fraction because the numerator is equal to the denominator. The function should return false. - -// These acceptance criteria cover a range of scenarios to ensure that the isProperFraction function handles both proper and improper fractions correctly and handles potential errors such as a zero denominator. +function isProperFraction(numerator, denominator) { + if (denominator === 0) { + throw new Error("Denominator cannot be zero"); + } + return Math.abs(numerator) < Math.abs(denominator); +} + +// Proper Fraction check +console.assert(isProperFraction(2, 3) === true, "Test Case 1 Failed"); + +// Improper Fraction check +console.assert(isProperFraction(5, 2) === false, "Test Case 2 Failed"); + +// Zero Denominator check +try { + isProperFraction(3, 0); + console.assert(false, "Test Case 3 Failed"); +} catch (e) { + console.assert( + e.message === "Denominator cannot be zero", + "Test Case 3 Passed" + ); +} + +// Negative Fraction check +console.assert(isProperFraction(-4, 7) === true, "Test Case 4 Failed"); + +// Equal Numerator and Denominator check +console.assert(isProperFraction(3, 3) === false, "Test Case 5 Failed"); diff --git a/week-3/implement/is-valid-triangle.js b/week-3/implement/is-valid-triangle.js index 7b22836b..82c42065 100644 --- a/week-3/implement/is-valid-triangle.js +++ b/week-3/implement/is-valid-triangle.js @@ -1,40 +1,23 @@ -// Implement a function isValidTriangle -// 🗝️ Terms -// the Triangle Inequality says: the sum of any two sides is always greater than the third side. -// practical examples: -// Side a = 3 -// Side b = 3 -// Side c = 3 - -// This is a valid triangle, because a plus b = 6 and 6 is greater than 3 -// Another way to write this is a + b > c -// It's also true that b + c > a -// It's also true that a + c > b - -// In our function isValidTriangle, we need to return false for any triangle where the sum of any two sides is less than or equal to the length of the third side. -// and we need to return true for any triangle where the sum of any two sides is greater than the length of the third side. - -// Acceptance criteria: - -// Given the lengths of three sides of a triangle (a, b, c), -// When the function isValidTriangle is called with these side lengths as input, -// Then it should: - -// scenario: invalid triangle -// Given the side lengths a, b, and c, -// When the sum of any two side lengths is less than or equal to the length of the third side (i.e., a + b <= c, a + c <= b, b + c <= a), -// Then it should return false because these conditions violate the Triangle Inequality, which states that the sum of the lengths of any two sides of a triangle must be greater than the length of the third side. - -// scenario: invalid triangle -// Check for Valid Input: -// Given the sides a, b, and c, -// When any of the sides are less than or equal to zero, -// Then it should return false because a triangle cannot have zero or negative side lengths. - -// scenario: valid triangle -// Given valid side lengths where the sum of any two sides is greater than the third side, -// When the function is called with these values as input, -// Then it should return true because the input forms a valid triangle. - -// This specification outlines the behavior of the isValidTriangle function for different input scenarios, ensuring it properly checks for invalid side lengths and whether they form a valid triangle according to the Triangle Inequality Theorem. +function isValidTriangle(a, b, c) { + if (a <= 0 || b <= 0 || c <= 0) { + return false; // Invalid sides + } + return a + b > c && a + c > b && b + c > a; +} + +// Test invalid triangle with sum of two sides less than or equal to the third side +console.assert(isValidTriangle(1, 2, 3) === false, "Test Case 1 Failed"); +console.assert(isValidTriangle(1, 3, 2) === false, "Test Case 2 Failed"); +console.assert(isValidTriangle(3, 1, 2) === false, "Test Case 3 Failed"); + +// Test invalid triangle with zero or negative sides +console.assert(isValidTriangle(0, 2, 3) === false, "Test Case 4 Failed"); +console.assert(isValidTriangle(-1, 2, 3) === false, "Test Case 5 Failed"); +console.assert(isValidTriangle(2, -1, 3) === false, "Test Case 6 Failed"); +console.assert(isValidTriangle(2, 3, -1) === false, "Test Case 7 Failed"); + +// Test valid triangle +console.assert(isValidTriangle(3, 4, 5) === true, "Test Case 8 Failed"); +console.assert(isValidTriangle(6, 8, 10) === true, "Test Case 9 Failed"); +console.assert(isValidTriangle(7, 10, 5) === true, "Test Case 10 Failed"); diff --git a/week-3/refactor/format-as-12-hours.js b/week-3/refactor/format-as-12-hours.js index 41603122..1b264461 100644 --- a/week-3/refactor/format-as-12-hours.js +++ b/week-3/refactor/format-as-12-hours.js @@ -1,6 +1,16 @@ -// There is an implementation of format-as-12-hours.js in the debug directory -// Copy that implementation in here, and improve it: -// That implementation currently uses the expression Number(time.slice(0, 2)) twice -// Store this expression in a variable and reference it twice in the function in the correct place +function isLeapYear(year) { + if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) { + return true; + } + return false; +} +function isLeapYear(year) { + const divisibleBy4 = year % 4 === 0; + const divisibleBy100 = year % 100 === 0; + const divisibleBy400 = year % 400 === 0; -// Explain why it makes more sense to store this expression in a variable + if ((divisibleBy4 && !divisibleBy100) || divisibleBy400) { + return true; + } + return false; +}