Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Sprint-3/4-stretch/card-validator.js

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This program is correct and concise as well. I can see that some mathematics or computing techniques were used to solve this challenge. Can you explain what line 9, 14, 20 of your code does respectively? And why would you choose such particular feature over other implementation techniques? Thank you very much for your clarification.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 9 (!‌/^\d‍{16}$‍/.te‍st(‍...)) u‌ses a regular expression (R‌egEx) to validate tha‍t the string conta‍ins exactly 16 digits and absolutely n‍othing‍ else. ^‌ and $ an‍chor the matching to the absolute start and end of the string, whil‌e \d{16} enforces‌ exactly 16 continuous digit characters.

Why choose this feature: It‍ allows us to perform two checks simultaneously (string length and character validation) in a‍ single declarativ‍e line. The alternative would be manually looping through the string and test‍ing char codes individually, which is more verbose and error-prone.

Line 14 (new Set(digits)).si‌ze < 2): passes the array of numbers into a JavaScript Set. Becau‍se a set only allows unique values, any duplicate digits are‌ auto‌matic‍ally‍ stripped a‌way. We t‌hen look a‍t th‍e si‌ze prop‍erty to‌ see how many unique numbers are left.

Why choose th‌is feature‍: It eliminates the n‍eed to create a nested tracking array or a manual tracking object (like a frequency counter map). Using the native Set‌ data structure is faster to write, easier to scan visually, a‌nd highly performan‌t.

Line 20 (digits.reduce(...)): utilizes the built-in. The reduce() array method collapses (accumulates) the whole array down into a single summation value, starting fro‌m an initial value of 0.

Why choose this feature: It aligns with clean, functional programming standards by keeping dat‌a trans‌formations immutab‌le. It allows us to calculate the sum dire‍ctly into a const variabl‍e, avoiding the boilerplate syntax and mutable states of traditional for or w‌h‌ile index-incrementing loops‌.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Validates a credit card number string against the following rules:
// - Must be exactly 16 digits (no letters or other characters)
// - Must contain at least two different digits
// - The final digit must be even
// - The sum of all digits must be greater than 16

function isValidCardNumber(cardNumber) {
// Rule 1: must be exactly 16 digit characters
if (!/^\d{16}$/.test(cardNumber)) return false;

const digits = cardNumber.split("").map(Number);

// Rule 2: at least two different digits must be present
if (new Set(digits).size < 2) return false;

// Rule 3: final digit must be even
if (digits[15] % 2 !== 0) return false;

// Rule 4: sum of all digits must be greater than 16
const sum = digits.reduce((acc, d) => acc + d, 0);
if (sum <= 16) return false;

return true;
}

module.exports = isValidCardNumber;
30 changes: 30 additions & 0 deletions Sprint-3/4-stretch/card-validator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const isValidCardNumber = require("./card-validator");

test("should return true for a valid card number", () => {
expect(isValidCardNumber("9999777788880000")).toEqual(true);
expect(isValidCardNumber("6666666666661666")).toEqual(true);
});

test("should return false when card contains non-digit characters", () => {
expect(isValidCardNumber("a92332119c011112")).toEqual(false);
});

test("should return false when card has fewer than 16 digits", () => {
expect(isValidCardNumber("123456789012345")).toEqual(false);
});

test("should return false when card has more than 16 digits", () => {
expect(isValidCardNumber("12345678901234567")).toEqual(false);
});

test("should return false when all digits are the same", () => {
expect(isValidCardNumber("4444444444444444")).toEqual(false);
});

test("should return false when final digit is odd", () => {
expect(isValidCardNumber("6666666666666661")).toEqual(false);
});

test("should return false when sum of digits is not greater than 16", () => {
expect(isValidCardNumber("1111111111111110")).toEqual(false);
});
20 changes: 17 additions & 3 deletions Sprint-3/4-stretch/password-validator.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
const previousPasswords = ["Pass1!", "Hello1#", "Secure1$"];

function passwordValidator(password) {
return password.length < 5 ? false : true
if (password.length < 5) {
return false;
} if (!/[A-Z]/.test(password)) {
return false;
} if (!/[a-z]/.test(password)) {
return false;
} if (!/[0-9]/.test(password)) {
return false;
} if (!/[!#$%.\*&]/.test(password)) {
return false;
} if (previousPasswords.includes(password)) {
return false;
}
return true;
}


module.exports = passwordValidator;
module.exports = { passwordValidator, previousPasswords };
50 changes: 27 additions & 23 deletions Sprint-3/4-stretch/password-validator.test.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
/*
Password Validation
const { passwordValidator } = require("./password-validator");

Write a program that should check if a password is valid
and returns a boolean
test("should return false when password has fewer than 5 characters", () => {
expect(passwordValidator("Ab1!")).toEqual(false);
});

To be valid, a password must:
- Have at least 5 characters.
- Have at least one English uppercase letter (A-Z)
- Have at least one English lowercase letter (a-z)
- Have at least one number (0-9)
- Have at least one of the following non-alphanumeric symbols: ("!", "#", "$", "%", ".", "*", "&")
- Must not be any previous password in the passwords array.
test("should return false when password has no uppercase letter", () => {
expect(passwordValidator("hello1!")).toEqual(false);
});

You must breakdown this problem in order to solve it. Find one test case first and get that working
*/
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);
}
);
test("should return false when password has no lowercase letter", () => {
expect(passwordValidator("HELLO1!")).toEqual(false);
});

test("should return false when password has no number", () => {
expect(passwordValidator("Hello!")).toEqual(false);
});

test("should return false when password has no special character", () => {
expect(passwordValidator("Hello1")).toEqual(false);
});

test("should return false when password is a previous password", () => {
expect(passwordValidator("Pass1!")).toEqual(false);
});

test("should return true for a valid password meeting all criteria", () => {
expect(passwordValidator("Valid1!")).toEqual(true);
expect(passwordValidator("MyPass1$")).toEqual(true);
});
Loading