diff --git a/Sprint-3/4-stretch/card-validator.js b/Sprint-3/4-stretch/card-validator.js new file mode 100644 index 0000000000..dfb00afd85 --- /dev/null +++ b/Sprint-3/4-stretch/card-validator.js @@ -0,0 +1,71 @@ +/* +Here are the rules for a valid number: + +- Number must be 16 digits, all of them must be numbers. +- You must have at least two different digits represented (all of the digits cannot be the same). +- The final digit must be even. +- The sum of all the digits must be greater than 16. + +For example, the following credit card numbers are valid: + +```markdown +9999777788880000 +6666666666661666 +``` + +And the following credit card numbers are invalid: + +```markdown +a92332119c011112 (invalid characters) +4444444444444444 (only one type of number) +1111111111111110 (sum less than 16) +6666666666666661 (odd final number) +``` + +These are the requirements your project needs to fulfill: + +- Make a JavaScript file with a name that describes its contents. +- Create a function with a descriptive name which makes it clear what the function does. The function should take one argument, the credit card number to validate. +- Write at least 2 comments that explain to others what a line of code is meant to do. +- Return a boolean from the function to indicate whether the credit card number is valid. + +Good luck! +*/ + +const validateCard = (card) => { + const cardStr = String(card); + // Must have 16 digits + const has16Digits = cardStr.length === 16; + // Must be all digits + const isAllDigits = /^\d+$/.test(cardStr); + // Must have at least 2 numbers + const hasMoreThanOneDigit = cardStr.length > 1; + // Final digit must be even + const hasEvenFinalDigit = isAllDigits && (Number(cardStr) % 10) % 2 === 0; + // Sum of numbers must be at least 16 + const sumOfNumbers = isAllDigits + ? cardStr.split("").reduce((acc, num) => acc + Number(num), 0) + : 0; + + const hasSumOver15 = sumOfNumbers > 15; + + // Must have more than one type of number + const hasMultipleDistinctDigits = new Set(cardStr.split("")).size > 1; + + return has16Digits && + hasMoreThanOneDigit && + hasEvenFinalDigit && + hasSumOver15 && + hasMultipleDistinctDigits + ? true + : false; +}; + +console.log(validateCard(9999777788880000)); // true +console.log(validateCard(6666666666661666)); // true +console.log(validateCard("a92332119c011112")); // false +console.log(validateCard(4444444444444444)); // false +console.log(validateCard(1111111111111110)); // false +console.log(validateCard(6666666666666661)); // false + +module.exports = validateCard; diff --git a/Sprint-3/4-stretch/card-validator.test.js b/Sprint-3/4-stretch/card-validator.test.js new file mode 100644 index 0000000000..40b0f05c36 --- /dev/null +++ b/Sprint-3/4-stretch/card-validator.test.js @@ -0,0 +1,43 @@ +const validateCard = require("./card-validator"); + +test("should have 16 digits, all numbers", () => { + const cardNumber = 9999777788880000; + const result = validateCard(cardNumber); + expect(result).toBe(true); +}); + +test("should not have less than 16 digits", () => { + const cardNumber = 99997777; + const result = validateCard(cardNumber); + expect(result).toBe(false); +}); + +test("should have at least two different distinct digits", () => { + const cardNumber = 9999777788880000; + const result = validateCard(cardNumber); + expect(result).toBe(true); +}); + +test("should have even final digit", () => { + const cardNumber = 6666666666661666; + const result = validateCard(cardNumber); + expect(result).toBe(true); +}); + +test("total sum of numbers should be greater than 15", () => { + const cardNumber = 6666666666661666; + const result = validateCard(cardNumber); + expect(result).toBe(true); +}); + +test("single repeating digit is invalid", () => { + const cardNumber = 4444444444444444; + const result = validateCard(cardNumber); + expect(result).toBe(false); +}); + +test("digits cannot include non numerals", () => { + const cardNumber = "a92332119c011112"; + const result = validateCard(cardNumber); + expect(result).toBe(false); +}); diff --git a/Sprint-3/4-stretch/find.js b/Sprint-3/4-stretch/find.js index c7e79a2f21..968756c8dd 100644 --- a/Sprint-3/4-stretch/find.js +++ b/Sprint-3/4-stretch/find.js @@ -20,6 +20,13 @@ console.log(find("code your future", "z")); // Pay particular attention to the following: // a) How the index variable updates during the call to find +// The index starts at 0 and increments by one at each iteration as long as the nested if statement is not triggered. In the case of find("code your future", "u"), the if statement is triggered at index 7 because a match is found for letter u at this index. The while loop is exited and the number 7 is returned by the find function. In the case of find("code your future", "z") no match is found by the time the while loop terminates. In this case the find function returns -1 to indicate the letter z was not found in the string + // b) What is the if statement used to check +// The if statement is used to check if the current letter in the string (str[index]) matches the target letter (char). If a match is found (str[index] === char) it will cause an early exit from the while loop at the current index which will be returned by the find function + // c) Why is index++ being used? +// index++ is being used because the while loop does not have a built in iterator (like the for loop). Index is initiated at 0 outside the while loop and at each iteration, whenever the if statement is not triggered, index++ adds 1 to the index number + // d) What is the condition index < str.length used for? +// The condition index < str.length is used to set the upper bound of the loop (the loop will run while index number is less than str.length and will terminate once index is equal to str.length, causing the while loop to stop. If there is no condition to terminate the while loop it will run infinitely diff --git a/Sprint-3/4-stretch/password-validator.js b/Sprint-3/4-stretch/password-validator.js index b55d527dba..776cfdf878 100644 --- a/Sprint-3/4-stretch/password-validator.js +++ b/Sprint-3/4-stretch/password-validator.js @@ -1,6 +1,16 @@ function passwordValidator(password) { - return password.length < 5 ? false : true -} + const previousPasswords = ["heLlo5.", "Su1ma#"]; + + const checks = { + minLength: password.length > 4, + hasUpperCase: /[A-Z]/.test(password), + hasLowerCase: /[a-z]/.test(password), + hasNumber: /[0-9]/.test(password), + hasSymbol: /[!#$%.*&]/.test(password), + notPreviousPassword: !previousPasswords.includes(password), + }; + return Object.values(checks).every(Boolean); +} -module.exports = passwordValidator; \ No newline at end of file +module.exports = passwordValidator; diff --git a/Sprint-3/4-stretch/password-validator.test.js b/Sprint-3/4-stretch/password-validator.test.js index 8fa3089d6b..59238a78d7 100644 --- a/Sprint-3/4-stretch/password-validator.test.js +++ b/Sprint-3/4-stretch/password-validator.test.js @@ -16,11 +16,38 @@ You must breakdown this problem in order to solve it. Find one test case first a */ const isValidPassword = require("./password-validator"); test("password has at least 5 characters", () => { - // Arrange - const password = "12345"; - // Act - const result = isValidPassword(password); - // Assert - expect(result).toEqual(true); -} -); \ No newline at end of file + // Arrange + const password = "Pen5!"; + // Act + const result = isValidPassword(password); + // Assert + expect(result).toEqual(true); +}); + +test("returns true for a valid password", () => { + expect(isValidPassword("Pen5!")).toBe(true); +}); + +test("returns false for a short password", () => { + expect(isValidPassword("Pen!")).toBe(false); +}); + +test("returns false if there is no uppercase English letter", () => { + expect(isValidPassword("pen5!")).toBe(false); +}); + +test("returns false if there is no lowercase English letter", () => { + expect(isValidPassword("PEN5!")).toBe(false); +}); + +test("returns false if there is no number", () => { + expect(isValidPassword("PENf!")).toBe(false); +}); + +test("returns false if there is no symbol", () => { + expect(isValidPassword("Pen5a")).toBe(false); +}); + +test("returns false if password is a previous password", () => { + expect(isValidPassword("heLlo5.")).toBe(false); +});