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
71 changes: 71 additions & 0 deletions Sprint-3/4-stretch/card-validator.js
Original file line number Diff line number Diff line change
@@ -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 &&

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 looks correct, but can you read the task specification again? See what the return type of the function is meant to be.

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.

Noted, I have updated the return type to boolean

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;
43 changes: 43 additions & 0 deletions Sprint-3/4-stretch/card-validator.test.js
Original file line number Diff line number Diff line change
@@ -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);
});
7 changes: 7 additions & 0 deletions Sprint-3/4-stretch/find.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 13 additions & 3 deletions Sprint-3/4-stretch/password-validator.js
Original file line number Diff line number Diff line change
@@ -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),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

good use of regular expressions here

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;
module.exports = passwordValidator;
43 changes: 35 additions & 8 deletions Sprint-3/4-stretch/password-validator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
);
// 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);
});
Loading