Credit Card Checker Challenge Project (JavaScript)

// All valid credit card numbers const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]; const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9]; const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6]; const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5]; const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6]; // All invalid credit card numbers const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5]; const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3]; const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4]; const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5]; const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4]; // Can be either valid or invalid const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4]; const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9]; const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3]; const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3]; const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3]; // An array of all the arrays above const batch = [ valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5, ]; // Add your functions below: const validateCred = (array) => { let arr = array.slice(); let sum = 0; let digit = arr[arr.length - 1]; for (let i = arr.length - 1; i >= 0; i--) { if (i % 2 === 0) { arr[i] = arr[i] * 2; if (arr[i] > 9) { arr[i] -= 9; } } else { } } for (let i = 0; i < arr.length; i++) { sum += arr[i]; } if (sum % digit === 0) { return true; } else { return false; } }; const findInvalidCards = (array) => { let invalidArray = []; let validArray = []; array.forEach((arr) => { if (validateCred(arr)) { validArray.push(arr); } else { invalidArray.push(arr); } }); console.log("valid:"); console.log(validArray); console.log("Invalid:"); console.log(invalidArray); return invalidArray; }; const idInvalidCardCompanies = (array) => { let cardCompanies = []; for (const card of array) { let firstDigit = card[0]; let companyName; switch (firstDigit) { case 3: companyName = "Amex (American Express)"; break; case 4: companyName = "Visa"; break; case 5: companyName = "Mastercard"; break; case 6: companyName = "Discover"; break; default: console.log('Company not found'); continue; } if (!cardCompanies.includes(companyName)) { cardCompanies.push(companyName); } } return cardCompanies; }; //console.log(validateCred(valid3)); //findInvalidCards(batch); console.log('Cards: ' + idInvalidCardCompanies(findInvalidCards(batch)));

Ktotz

Hello guys, I have spent quite a few hours on this project and finally came up with my solution. Please kindly check it out here and let me know how I can improve/refactor my code.

I found the first function most challenging to me. When I finally completed the first function, it’s already so long! I had to separate every step clearly. Therefore, I have added some comments to clarify my thought process and hope for better readability. Thank you!

Hi everyone, I’m a bit stuck on this project, and wonder if anyone can provide a bit of assistance, I’ve tried looking through some official documentation and everything and am still a bit confused.

Around the part of creating the validateCred() function of this assignment that uses the Luhn algorithm. My first instinct for this problem is to loop over the array backwards, using the length property

for (let i = arr.length - 1; i > 0; i--)

, however the constraint of doubling every other number is a bit confusing to me

Given that only every other is changed, what happens if we revise the increment to,

i -= 2

?

This will necessitate,

let i = arr.length - 2; i -= 2
1 Like

I had not thought about this, I guess if the increment is changed to - 2, it would go to every other index in the array instead.

1 Like

Note also where we start, arr.length - 2 so we skip the last element of the array.

1 Like

Good tips, thank you!

1 Like

Here is what I come up with for this project


Here is my project without the extra challenges

Please tell me what you guys think
Thanks

Did you validate your own credit card with this? If not, then did you validate a known active credit card? Sadly, that is the only way to be absolutely sure our code works. It is, after all, a credit card validity checking program.

// Web Development Foundations - Challenge Project: Credit Card Checker // All valid credit card numbers const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]; const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9]; const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6]; const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5]; const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6]; // All invalid credit card numbers const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5]; const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3]; const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4]; const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5]; const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4]; // Can be either valid or invalid const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4]; const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9]; const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3]; const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3]; const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3]; // An array of all the arrays above const batch = [ valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5, ]; // Add your functions below: const validateCred = (card) => { const len = card.length; let sum = 0; for (let i = len - 1, currentPos = 1; i >= 0; i--, currentPos++) { let digit = card[i]; // double every other number // from last(which is pos:1): double every even digit if (currentPos % 2 == 0) { digit *= 2; // subtract 9 if greater than 9 digit -= digit > 9 ? 9 : 0; } sum += digit; } return sum % 10 === 0; }; function findInvalidCards(arr) { return arr.filter((c) => !validateCred(c)); } function idInvalidCardCompanies(invalidCards) { const companies = { 3: "Amex (American Express)", 4: "Visa", 5: "Mastercard", 6: "Discover", }; const issuers = []; invalidCards.forEach((c) => { const firstDigit = c[0]; if (companies.hasOwnProperty(firstDigit)) { // add only once if (!issuers.includes(companies[firstDigit])) { issuers.push(companies[firstDigit]); } } else console.log("Company not found"); }); return issuers; } // TEST 1 const invalidCards = findInvalidCards(batch); const invalidCardIssuerCompanies = idInvalidCardCompanies(invalidCards); console.log('invalid card issuer companies:',invalidCardIssuerCompanies); // TEST 2 : 5 invalid + 3 invalid mystery card console.log('Total Invalid Cards: ',invalidCards.length) //8 // console.log([mystery1,mystery2,mystery3,mystery4,mystery5].map(validateCred)) //3 invalid card

I guess every companies issued invalid cards

Here’s my solution to this challenge project:

I checked it against a real credit card and it correctly validated
it

1 Like

Hi everyone! Hope you all are ok and improving in your code journey.

I have reached to finish this exercise some minutes ago and here is my answer. If anyone could give me some feedback it would be really appreciated :slight_smile:

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];

// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];


// Add your functions below:
const validateCred = array => {
    const finalNumber = array.reduceRight((accumulator, checkNumber, index) => {
        let value = checkNumber;
        //console.log('Este es el checkNumber: ' + checkNumber);
        //console.log('Este es el accumulator: ' + accumulator);
        //console.log(array.length - 1 - index)
        if ((array.length - 1 - index) % 2 !== 0) {
            value *= 2;
            //console.log('Este es valor de los números impares: ' + value);

            if (value > 9) {
                value = value - 9;
            }
        }
        //console.log('Esta es la suma: ' + (accumulator + value));
        const newAccumulator = accumulator + value;
        return newAccumulator;
    });
    //console.log(finalNumber)
    //console.log(finalNumber % 10 === 0);
    return finalNumber % 10 === 0;
};


validateCred(valid1);

const findInvalidCards = nestedArray => {
    const invalidCards = nestedArray.filter(array => {
       const finalNumber = array.reduceRight((accumulator, checkNumber, index) => {
            let value = checkNumber;
            //console.log('Este es el checkNumber: ' + checkNumber);
            //console.log('Este es el accumulator: ' + accumulator);
            //console.log(array.length - 1 - index)
            if ((array.length - 1 - index) % 2 !== 0) {
                value *= 2;
                //console.log('Este es valor de los números impares: ' + value);

                if (value > 9) {
                    value = value - 9;
                }
            }
            //console.log('Esta es la suma: ' + (accumulator + value));
            const newAccumulator = accumulator + value;
            return newAccumulator;
        });
        //console.log(finalNumber)
        //console.log(finalNumber % 10 === 0);
        return finalNumber % 10 === 0;
    })
      //console.log(invalidCards);

        return invalidCards;
};

const invalidCardsChecked = findInvalidCards(batch);
//console.log(invalidCardsChecked)

const idInvalidCardCompanies = (nestedArray) => {
  const companiesWithInvalidCards = [];
  
  const findFirstElement = nestedArray.forEach(array => {
    const copiedArray = [... array];
    const firstElement = copiedArray.shift();

    if (firstElement === 4 && companiesWithInvalidCards.some(element => element === 'Visa') !== true) {
      companiesWithInvalidCards.push('Visa');
    } else if (firstElement === 3 && companiesWithInvalidCards.some(element => element === 'Amex (American Express)') !== true) {
      companiesWithInvalidCards.push('Amex (American Express)');
    } else if (firstElement === 5 && companiesWithInvalidCards.some(element => element === 'Mastercard') !== true) {
        companiesWithInvalidCards.push('Mastercard');
    } else if (firstElement === 6 && companiesWithInvalidCards.some(element => element === 'Discover') !== true) {
       companiesWithInvalidCards.push('Discover');
    }

  });
  console.log(`This are the companies with invalid credit cards: ${companiesWithInvalidCards}`)
  return companiesWithInvalidCards;
};

//idInvalidCardCompanies(invalidCardsChecked);

//Convertion of a credit card number string into an array
const convertStringToArray = string => {
  const stringToArray = Array.from(string).map(number => parseInt(number));
 
  return stringToArray;
};

//convertStringToArray('456326532623232');

Cheers and keep pushing,
Sergio

I mean a win is a win

My solution:

Hello! I just finished the project challenge, including the last two extra challenges.

Here’s my repo with the solution, if you want to check it :wink:

Hope it’s useful and feel free to ask if any questions arise, I’ll be glad to answer.

Have a good one!
Aeon.

Hello coders!

From the solutions I’ve seen, I used more iterative methods than some. It probably took me longer to think through how these iterative methods work than if I’d used traditional loops, but I really like how iterative methods expose the data and abstract away the iteration. Of course, Luhn alg requires advanced iteration, so traditional loops are also employed. I really enjoyed this challenging learning opportunity.

// import { valid, invalid, mystery, mixed, batch } from ‘./data.js’;
// export { valid, invalid, mystery, mixed, batch };
//
// Place import statement at START of main.js
// Place export statement at END of data.js
// In project folder execute ‘npm init -y’ to create package.json
// Then edit package.json and add line: ‘“type”: “module”,’
// (observing json files want commas at line ends except last line)
// If updating, be sure to update both import and export statements

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];
const valid = [ valid1, valid2, valid3, valid4, valid5 ];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];
const invalid = [ invalid1, invalid2, invalid3, invalid4, invalid5 ];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];
const mystery = [ mystery1, mystery2, mystery3, mystery4, mystery5 ];

// Mixed – valid, invalid, valid, invalid
const mixed1 = [6, 7, 7, 1, 5, 4, 9, 4, 9, 5, 5, 8, 6, 8, 0, 2];
const mixed2 = [4, 5, 3, 2, 0, 1, 5, 1, 1, 2, 8, 3, 0, 3, 4, 2];
const mixed3 = [3, 7, 9, 3, 5, 4, 5, 0, 8, 1, 6, 2, 3, 0, 6];
const mixed4 = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 0];
const mixed = [ mixed1, mixed2, mixed3, mixed4 ];

// Array of all the above arrays
const batch = [ valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5, mixed1, mixed2, mixed3, mixed4 ];

const validateCred = (cardNumber) => {
const lastDigit = cardNumber[cardNumber.length - 1]; // keep last digit
let allExceptLastReversed = cardNumber.slice(0, -1).reverse(); // reverse array
// double odd numbered elements (1,3,5…)
for (let i = 0; i < allExceptLastReversed.length; i += 2) {
allExceptLastReversed[i] *= 2;
if (allExceptLastReversed[i] > 9) { // if over 9, subtract 9
allExceptLastReversed[i] -= 9;
}
}
const sum = allExceptLastReversed.reduce((acc, curr) => acc + curr, 0) + lastDigit;
// sum all digits
return (sum % 10 === 0); // validate modulo 10 === 0
};

const findInvalidCards = (cardsArrArr) => {
return cardsArrArr.filter(cardArr => !validateCred(cardArr));
};

const idInvalidCardCompanies = (cardsArrArr) => { // input invalid cards array
const firstDigits = cardsArrArr.map(subArray => subArray[0]); // extract first digits
const uniqueFirstDigits = […new Set(firstDigits)]; // extract unique first digits
// … spread operator expands, Set must be called with new, Set selects unique elements
const companies = uniqueFirstDigits.map(digit => lookupTable.get(digit) || ‘Company not found’);
// greedy, looks for truth, continues rightward if not found in lookupTable
return companies;
};

const lookupTable = new Map ([
[3, ‘Amex (American Express)’],
[4, ‘Visa’],
[5, ‘Mastercard’],
[6, ‘Discover’]
]);

console.log(idInvalidCardCompanies(batch));
console.log(findInvalidCards(batch));

This is my code. If someone have some suggest to improve this one I love it to listen them. Have a nice code day!

Hi folks.

Posting my code, including the 2 extra challenges.

Comments:

For the validateCred() function I used .slice() to make a copy of the original array.
I checked here that most have used reverse() and worked with the digits from left to right, but I did it vice-versa using backwards loop. It took me a while to figure out that I should target the second number from the right using .length-2, not -1.
.reduce() was helpful in summing up the numbers within the mutated array.

For the function idInvalidCardCompanies, I used for…of loop and switch to alternate between different first digits.

For the second extra task (function to convert invalid credit card numbers into valid numbers, I tinkered with ways to change the checkDigit (the card number most to the right) and it wasn’t necessary to change other numbers.

I used the Codecademy internal AI assistant 2-3 times while doing this exercise when I had been stuck for 1-2 hours, but I think in the end it was still better than getting the whole solution from here or using CodeCademy solution. Probably still used Google more than this AI helper. Overall, I don’t think it hindered my ability to learn here.

1 Like