Skip to content

Commit 2c3c3f8

Browse files
HD-40307gHD-40307g
HD-40307g
authored and
HD-40307g
committed
Add LuhnAlgorithm.js and LuhnAlgorithm.test.js
1 parent d8588f9 commit 2c3c3f8

File tree

2 files changed

+167
-0
lines changed

2 files changed

+167
-0
lines changed

Diff for: Maths/LuhnAlgorithm.js

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* Luhn algorithm, also known as the “Modulus 10” or “mod 10” algorithm.
3+
* This algorithm is a simple checksum formula used to validate the authenticity of credit card numbers.
4+
* The Luhn algorithm works by doubling every second digit from right to left, adding the resulting digits, and then checking if the total is divisible by 10.
5+
* If it is, the credit card number is considered valid.
6+
* The Luhn algorithm is widely used in credit card verification and is specified in ISO/IEC 7812-1.
7+
* It is not intended to be a cryptographically secure hash function but rather a simple method to detect accidental errors, not malicious attacks.
8+
*/
9+
10+
// Valid credit card numbers
11+
export const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
12+
export const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
13+
export const valid3 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
14+
export const valid4 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
15+
export const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];
16+
17+
// Invalid credit card numbers
18+
export const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
19+
export const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
20+
export const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
21+
export const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
22+
export const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];
23+
24+
// Mixed batch of credit card numbers
25+
export const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
26+
export const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
27+
export const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
28+
export const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
29+
export const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];
30+
31+
export const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];
32+
33+
/**
34+
* Validates a credit card number using the Luhn Algorithm.
35+
* @param {number[]} numArr - Array representing the credit card number.
36+
* @returns {boolean} - True if the card is valid, false otherwise.
37+
*/
38+
export function validateCred(numArr) {
39+
let total = 0;
40+
for (let i = numArr.length - 1; i >= 0; i--) {
41+
let currValue = numArr[i];
42+
// Double every other digit starting from the second-to-last
43+
if ((numArr.length - 1 - i) % 2 === 1) {
44+
currValue *= 2;
45+
if (currValue > 9) {
46+
currValue -= 9;
47+
}
48+
}
49+
total += currValue;
50+
}
51+
return total % 10 === 0;
52+
};
53+
54+
/**
55+
* Finds invalid credit card numbers from a batch.
56+
* @param {number[][]} cards - Array of credit card numbers.
57+
* @returns {number[][]} - Array of invalid credit card numbers.
58+
*/
59+
export function findInvalidCards(cards) {
60+
return cards.filter(card => !validateCred(card));
61+
};
62+
63+
/**
64+
* Identifies credit card companies that issued invalid card numbers.
65+
* @param {number[][]} invalidBatch - Array of invalid credit card numbers.
66+
* @returns {string[]} - Array of company names.
67+
*/
68+
export function idInvalidCardCompanies(invalidBatch) {
69+
const companies = new Set();
70+
invalidBatch.forEach(card => {
71+
switch (card[0]) {
72+
case 3:
73+
companies.add('Amex');
74+
break;
75+
case 4:
76+
companies.add('Visa');
77+
break;
78+
case 5:
79+
companies.add('Mastercard');
80+
break;
81+
case 6:
82+
companies.add('Discover');
83+
break;
84+
default:
85+
console.warn('Company not found for card starting with:', card[0]);
86+
}
87+
});
88+
return Array.from(companies);
89+
};
90+
91+
// Example Usage
92+
console.log(validateCred(valid1)); // Should print true
93+
console.log(validateCred(invalid1)); // Should print false
94+
console.log(findInvalidCards(batch)); // Find all invalid cards
95+
console.log(idInvalidCardCompanies(findInvalidCards(batch))); // Find companies of invalid cards

Diff for: Maths/test/LuhnAlgorithm.test.js

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Import the functions to be tested
2+
import { validateCred, findInvalidCards, idInvalidCardCompanies } from '../LuhnAlgorithm.js';
3+
4+
// Import credit card numbers to be tested
5+
import { valid1, valid2, valid4, valid3, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, batch} from '../LuhnAlgorithm.js'
6+
7+
// Test suite for credit card validation
8+
9+
//Test validateCred function
10+
function testValidateCred() {
11+
console.log('Running tests for validateCred...');
12+
13+
// Valid test cases
14+
if (![valid1, valid2, valid3, valid4, valid5].every(card => validateCred(card))) {
15+
console.error('FAILED: validateCred should return true for all valid cards');
16+
}
17+
if ([invalid1, invalid2, invalid3, invalid4, invalid5].some(card => validateCred(card))) {
18+
console.error('FAILED: validateCred should return false for all invalid cards');
19+
} else {
20+
console.log('PASSED: Valid card test');
21+
};
22+
23+
// Invalid test cases
24+
if (validateCred(invalid1 || invalid2 || invalid3 || invalid4 || invalid5)) {
25+
console.error('FAILED: validateCred should return false for invalid cards');
26+
} else {
27+
console.log('PASSED: Invalid card test');
28+
}
29+
};
30+
31+
//Test findInvalidCards function
32+
function testFindInvalidCards(batch) {
33+
console.log('Running tests for findInvalidCards...');
34+
const invalidCards = findInvalidCards(batch);
35+
36+
// Check if the result only contains invalid cards
37+
const allInvalid = invalidCards.every(card => !validateCred(card));
38+
39+
if (!allInvalid) {
40+
console.error('FAILED: findInvalidCards should return only invalid cards');
41+
} else {
42+
console.log('PASSED: Find invalid cards test');
43+
}
44+
};
45+
46+
// Test idInvalidCardCompanies function
47+
function testIdInvalidCardCompanies() {
48+
console.log('Running tests for idInvalidCardCompanies...');
49+
const companies = idInvalidCardCompanies(batch);
50+
51+
if (!companies.includes('Visa') || !companies.includes('Mastercard') || !companies.includes('Amex') || !companies.includes('Discover')) {
52+
console.error('FAILED: idInvalidCardCompanies should include all expected companies');
53+
} else if (companies.includes('Unknown')) {
54+
console.error('FAILED: idInvalidCardCompanies should not include unrecognized prefixes');
55+
} else {
56+
console.log('PASSED: Identify invalid card companies test');
57+
}
58+
};
59+
60+
//Run all tests
61+
function runAllTests() {
62+
console.log('Starting test suite...');
63+
testValidateCred();
64+
testFindInvalidCards(batch);
65+
testIdInvalidCardCompanies();
66+
console.log('Testing edge cases...');
67+
console.assert(findInvalidCards([[]]).length === 0, 'FAILED: findInvalidCards should handle empty arrays');
68+
console.log('All tests completed.');
69+
};
70+
71+
// Run the test suite
72+
runAllTests();

0 commit comments

Comments
 (0)