# Credit Card Validation Problem

Hello guys! i´m stuck on this exercise to validate credit card numbers. It basically has to pass an array which has to start being iterated from right to left.
Then, every other digit, multiplied * 2 nad if it is greater than 9, substract 9 from it.
Finally, do the sum of all the items in the array.

This is my code atm, im a very begginer on this so please feel free to provide feedback!

``````let validateCred = cardArr => {
cardArr.reverse();
let sum = cardArr.reduce((a, b) => a + b);

for (i = 0; i <= cardArr.length; i++) {
if (i % 2 != 0) {
let double = cardArr[i] * 2;
if (double > 9) {
return sum += double - 9;
} else {
return sum += double;
}
} else {
return sum += cardArr[i];
}
}
}
``````

So basically i wanted to iterate from index 0 on the reversed array, iterating 1 at the time .
My logic is that if i % 2 != 0, the funtion should multiplicate cardArray[i] * 2.
Then check if the result is greater than 9 or not and add the correspondent result to sum.
if i % 2 === 0 then add the result to sum.

For some reason i cant get it to work and i cant understand why.
Some help would be much appreciated!

remember that as soon as a return statement is met, the function stops and return a value
it doesn’t seem you want your function to stop so early so maybe remove the `return` keyword from inside the loop

1 Like

Thanks for the correction and feedback.

I´ve removed the returns in the function and now it seems to run completely but there is something wrong. Basically if i passed the next array, the result should be 80. But instead is “undefined”.

``````// This is the array to check, and the result should be 80

const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];

// This is my code atm:

let validateCred = cardArr => {
cardArr.reverse();
let sum = cardArr.reduce((a, b) => a + b);

for (i = 0; i <= cardArr.length; i++) {
if (i % 2 != 0) {
let double = cardArr[i] * 2;
if (double > 9) {
sum += double - 9;
} else {
sum += double;
}
} else {
sum += cardArr[i];
}
}
}
``````

what do you think is the value at `cardArr[cardArr.length]`?

1 Like

I´m not sure of what you mean… isn´t it cardArr[16]??

``````const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]

valid1.length
// 16

valid1[15]
// 8

valid1[16]
// undefined
``````

It’s the Luhn Formula/algorithm correct?

1. Don’t you need the last digit?

2. Shouldn’t you only do the sum one time?

3. Shouldn’t you be checking `i % 2 === 0` and not `i % 2 != 0`

4. Where is the validation code at the end (the mod 10 part)?

1 Like

I think it should 72 and not 80

And one last thing, this is the first time i´m posting something on the forum so i do not really know how to copy/paste code in here for it to appear properly… If you could tell me how to, would be of great help too!

When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

Please use the “preformatted text” tool in the editor (`</>`) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks are not single quotes.

1 Like

Found some mistakes and correct them as it wasn´t working properly.

Again, i would appreciate feedback on the code´s efficiency.

``````let validateCred = cardArr => {
//1st- Removing the last digit and reversing array
let newArr = cardArr.slice(0, -1).reverse();

//2nd- Iterating trough the array, multiplying the numbers in (now) even indexes and substracting 9 if neccesary
for (i = 0; i < newArr.length; i++) {
if (i % 2 === 0 || i === 0) {
newArr[i] *= 2;
if (newArr[i] > 9) {
newArr[i] -= 9;
} else {
newArr[i];
}
} else {
newArr[i];
}
}

//3rd- Sum all the items in the array
let sum = newArr.reduce((a, b) => a + b);

//4th- Finding out the check digit
let checkDig = cardArr[cardArr.length-1];

//5th- Card validation
if ((checkDig + sum) % 10 === 0) {
return true;
} else {
return false;
}
};
``````

Now I´m having trouble on the 3rd step.

The function should return all te names of the companies issuers of INVALID card numbers but it returns the VALID ones as well…

Can someone find the mistake on the 3rd step??

Here´s my code :

``````// 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];

// For this exercise I´m using the 'Luhn algorithm'

//(STEP 1) ---> Card´s number validation
let validateCred = cardArr => {

//1st- Creating a copy of the array passed (without the last digit) and reversing it
let newArr = cardArr.slice(0, -1).reverse();

//2nd- Iterating through the array, multiplying the numbers in (now) even indexes and substracting 9 if neccesary
for (i = 0; i < newArr.length; i++) {
if (i % 2 === 0 || i === 0) {
newArr[i] *= 2;
if (newArr[i] > 9) {
newArr[i] -= 9;
} else {
newArr[i];
};
} else {
newArr[i];
};
};

//3rd- Sum all the items in newArr
let sum = newArr.reduce((a, b) => a + b);

//4th- Finding out the check digit (last digit of the original card number)
let checkDig = cardArr[cardArr.length-1];

//5th- Final card validation
if ((checkDig + sum) % 10 === 0) {
return true;
} else {
return false;
};
};

//(STEP 2) ---> Creating a function which returns all the invalid card numbers
let findInvalidCards = invCardsArr => {

//1st- Creating the array containing all the invalid card numbers
let invalidCardsArray = [];

//2nd- Iterating through the array passed to find the invalid card numbers and .push() them into the invalidCardsArray
for (y = 0; y < invCardsArr.length; y++) {
let validation = validateCred(invCardsArr[y]);

if (validation === false) {
invalidCardsArray.push(invCardsArr[y]);
};
};

//3rd- Returning the final array
return invalidCardsArray;
};

//(STEP 3) ---  Finding out the issuers of invalid card numbers
let idInvalidCardCompanies = invalidsArray => {

//1st- Finding the invalid cards in the array passed !!!!!(THIS IS THE PART WHERE I´M HAVING TROUBLE)!!!!!!
findInvalidCards(invalidsArray); // <-- It doesn´t seem to work???

//2nd- Setting variables for each issuer´s id
let amx = 0;
let visa = 0;
let mc = 0;
let dscv = 0;
let notFound = 0;

//3rd- Iterating through invalidsArray to find out the issuer id of each card number
for (x = 0; x < invalidsArray.length; x++) {
let checkDig = invalidsArray[x] [0];

if (checkDig === 3) {
amx++;
} else if (checkDig === 4) {
visa++;
} else if (checkDig === 5) {
mc++;
} else if (checkDig === 6) {
dscv++;
} else if (checkDig != 3 && checkDig != 4 && checkDig != 5 && checkDig != 6){
notFound++;
};
};

//4th- Final list of invalid cards issuers
let invalidCardIssuers= [];

if (amx > 0) {
invalidCardIssuers.push('Amex');
} if (visa > 0) {
invalidCardIssuers.push('Visa');
} if (mc > 0) {
invalidCardIssuers.push('Mastercard');
} if (dscv > 0) {
invalidCardIssuers.push('Discover');
} if (notFound > 0) {
};

//4th- Returning the final list
return invalidCardIssuers;
};

``````

What is the final output supposed to look like? Is it just an array of strings with the names of all the card companies with invalid card numbers, or do you need a count of how many invalid card numbers each card company has?

Because (as far as I can tell) all the card companies you are checking for have an invalid card number in one of the arrays.

1. You need to call `idInvalidCardCompanies` and pass it the `batch` array. That is the function that sets off all the other function calls.

2. You need to capture (put in a variable) the array the `findInvalidCards` function returns when you call it inside the `idInvalidCardCompanies` function. Then loop that array (that was returned) inside the `idInvalidCardCompanies` function.

1 Like

That was of great help!!

Now, on the last step of my exercise, I’m trying to convert an INVALID card number into a VALID one.

So first i apply the Luhn algorithm to the array passed and then, on the last step, when I’m getting the remainder of mod 10 i follow the next logic:

1. If the remainder is greater than the check digit of the original passed array, I add the check digit plus the difference between 10 and the remainder.

2. If the remainder is lesser than the check digit, i substract the remainder to the check digit.

Like that i get the new check digit which converts the initial INVALID card number to a VALID one.

The result appears to be correct but I’ve got a small issue:

[ 3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4, NaN: 6 ]

Why the program is declaring the NaN: before the new check digit?

Here is my code:

``````let convToValid = invCard => {

let newInv = invCard.slice(0, -1).reverse();

for (i = 0; i < newInv.length; i++) {
if (i % 2 === 0 || i === 0) {
newInv[i] *= 2;
if (newInv[i] > 9) {
newInv[i] -= 9;
} else {
newInv[i];
}
} else {
newInv[i];
}
}

let sum = newInv.reduce((a, b) => a + b);

let checkDig = invCard[invCard.length-1];

let total = checkDig + sum;

if (total % 10 > checkDig) {
invCard[invCard.lenght - 1] = checkDig + (10 - total % 10);
} else {
invCard[invCard.lenght - 1] = checkDig - total % 10;
}
return invCard;
};

const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];

console.log(convToValid(invalid3))
``````

there is something wrong when you are saying what index to change, that calculation results in `NaN`, and then you have `invCard[NaN]` that is being assigned a value

search for typos would be my suggestion

use console.log statements to find out when the `NaN` appear for the first time in your code

1 Like

Hint:

lenght != length

Well i don’t know what to say…

Guys i greatly appreciate your help on this project!! It is the first real project im doing with javascript as i started almost a month ago to learn it for the first time.

Tbh I believe I wrote a code that could work quite efficiently but I’d appreciate feedback on what to improve, it would really make a difference.

As I said, thank you both for your great help!

``````//(STEP 1) ---> Card´s number validation
let validateCred = cardArr => {

//1st- Creating a copy of the array passed (without the last digit) and reversing it
let newArr = cardArr.slice(0, -1).reverse();

//2nd- Iterating through the array, multiplying the numbers in (now) even indexes and substracting 9 if neccesary
for (i = 0; i < newArr.length; i++) {
if (i % 2 === 0 || i === 0) {
newArr[i] *= 2;
if (newArr[i] > 9) {
newArr[i] -= 9;
} else {
newArr[i];
};
} else {
newArr[i];
};
};

//3rd- Sum all the items in newArr
let sum = newArr.reduce((a, b) => a + b);

//4th- Finding out the check digit (last digit of the original card number)
let checkDig = cardArr[cardArr.length-1];

//5th- Final card validation
if ((checkDig + sum) % 10 === 0) {
return true;
} else {
return false;
};
};

//(STEP 2) ---> Creating a function which returns all the invalid card numbers
let findInvalidCards = invCardsArr => {

//1st- Creating the array containing all the invalid card numbers
let invalidCardsArray = [];

//2nd- Iterating through the array passed to find the invalid card numbers and .push() them into the invalidCardsArray
for (y = 0; y < invCardsArr.length; y++) {
let validation = validateCred(invCardsArr[y]);

if (validation === false) {
invalidCardsArray.push(invCardsArr[y]);
}
};

//3rd- Returning the final array
return invalidCardsArray;
};

//(STEP 3) --->  Finding out the issuers of invalid card numbers
let idInvalidCardCompanies = invalidsArr => {

//1st- Finding the invalid cards in the array passed
let invalidCardsList = findInvalidCards(invalidsArr);

//2nd- Setting variables for each issuer´s id
let amx = 0;
let visa = 0;
let mc = 0;
let dscv = 0;
let notFound = 0;

//3rd- Iterating through invalidsArray to find out the issuer id of each card number
for (x = 0; x < invalidCardsList.length; x++) {
let checkDig = invalidCardsList[x] [0];

if (checkDig === 3) {
amx++;
} else if (checkDig === 4) {
visa++;
} else if (checkDig === 5) {
mc++;
} else if (checkDig === 6) {
dscv++;
} else {
notFound++;
}
}

//4th- Final list of invalid cards issuers
let invalidCardIssuers= [];

if (amx > 0) {
invalidCardIssuers.push('Amex');
} if (visa > 0) {
invalidCardIssuers.push('Visa');
} if (mc > 0) {
invalidCardIssuers.push('Mastercard');
} if (dscv > 0) {
invalidCardIssuers.push('Discover');
} if (notFound > 0) {
}

//4th- Returning the final list
return invalidCardIssuers;
};

/*console.log(validateCred(valid1));
console.log(validateCred(invalid1));
console.log(findInvalidCards(batch));
console.log(idInvalidCardCompanies(batch));*/

//(STEP4) ---> Converting INVALID card number to VALID ones
let convToValid = invCard => {

let newInv = invCard.slice(0, -1).reverse();

for (i = 0; i < newInv.length; i++) {
if (i % 2 === 0 || i === 0) {
newInv[i] *= 2;
if (newInv[i] > 9) {
newInv[i] -= 9;
} else {
newInv[i];
}
} else {
newInv[i];
}
}

let sum = newInv.reduce((a, b) => a + b);
let checkDig = invCard[invCard.length-1];
let total = checkDig + sum;

if (total % 10 > checkDig) {
invCard[invCard.length-1] = checkDig + (10 - total % 10);
} else {
invCard[invCard.length-1] = checkDig - total % 10;
}
return invCard;
};
``````

I wouldn’t worry too much about efficiency at this point.

What I would suggest you do is go through the code and make sure all variable names and function names are as descriptive as possible and switch to non-abbreviated names. Better to have an identifier that is long but descriptive than short and something you have to think about. Even if it’s just for a second or two, it adds up.

Decrees the total mental energy needed to read and understand the code as much as possible. Imagine yourself reading this code for the first time, or in 6 months.

2 Likes

Great! Done it!