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];
    }
  }  
}

Thanks for your time!!

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]?? :sweat_smile:

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!

Thanks for your help!! :smiley:

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.

markdown_Forums

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) {
    invalidCardIssuers.push('Company not found');
  };

  //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… :rofl:

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) {
    invalidCardIssuers.push('Company not found');
  }

  //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!

Thanks for your help!!