Home > Mobile >  Regex validate PIN Codewars
Regex validate PIN Codewars

Time:04-26

For this Codewars challenge, I cannot understand why the logic is not working. I've found other solutions, but would like to understand why this is not working:

ATM machines allow 4 or 6 digit PIN codes and PIN codes cannot contain anything but exactly 4 digits or exactly 6 digits.

If the function is passed a valid PIN string, return true, else return false.

function validatePIN (pin) {
  
  const splitPin = pin.toString().split('')
  const finalArr = [];
  
for (let i = 0; i < splitPin.length; i  ){
  
  if (!Number.isInteger(pin[i])){
    return false;
  } else if (Number.isInteger(pin[i])){
    finalArr.push(pin[i]);
  }
}
  if(finalArr.length === 4 || finalArr.length === 6){
    console.log(finalArr.length)
    return true;
  } 
  
}

CodePudding user response:

There are some double checks that you don't need to do but you are doing because you're not sure what you're expecting.

Like the type for pin.

const splitPin = pin.toString().split('') works either way for a string or number value, because you are expecting a string, the call to .toString is unneccesary

But also that you're using Number.isInteger - this function will only return true if the function is of type integer.

But since pin is a string and splitting it returns an array of strings, the Number.isInteger call will always return false.

Try using parseInt instead. Then check for parseInt(pin[0]) !== NaN.

You can streamline the function from:

function validatePIN (pin) {
  
  const splitPin = pin.toString().split('')
  const finalArr = [];
  
for (let i = 0; i < splitPin.length; i  ){
  
  if (!Number.isInteger(pin[i])){
    return false;
  } else if (Number.isInteger(pin[i])){
    finalArr.push(pin[i]);
  }
}
  if(finalArr.length === 4 || finalArr.length === 6){
    console.log(finalArr.length)
    return true;
  } 
  
}

to something cleaner:

function validatePIN (pin) {
  const acceptedLengths = [4, 6]
  const splitPin = pin.toString().split('')
  const finalArr = [];
  
  for (let i = 0; i < splitPin.length; i  ){
    // You don't need to do an else, since you're only
    // checking for one condition.
    // just return directly
    if (parseInt(pin[i]) !== NaN){
      finalArr.push(pin[i]);
    }

    return
  }
  
  return acceptedLengths.includes(finalArr.length)
}

or even something like this:

function validatePIN(pin) {
  // Set a variable for the accepted length
  const acceptedPINLength = [4, 6];

  // If we have to check if a value in pin is an integer or not
  // then the pin variable is a string and can't be a number.
  // So skip the .toString and just split it directly.
  const numbersArray = pin.split('')
    .filter((entry) => parseInt(entry) !== NaN)
    .join('');

  // if strength is 4 or 6, return true, else false
  return acceptedPINLength.includes(numbersArray.length)
}

CodePudding user response:

I would say: no loop required at all, you don't have to filter any characters:

function validatePIN2(pin) {
  const acceptedPINLength = [4, 6];
  return acceptedPINLength.includes(pin.length()) && !isNaN(pin);
}

(Thanks to @Amats for the elegant solution with the acceptedPINLength.)

  • Related