Simple PIN validation - javascript

Task:
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.
My solution:
function validatePIN (pin) {
//return true or false
if (!isNaN(pin) && Number.isInteger(pin) && pin.toString().length == 4 || pin.toString().length == 6) {
return true
} else {
return false
}
}
The only bug I get is when I pass 4 digits as a string ("1234") - it equals false.

function validatePIN (pin) {
return typeof pin === 'string' && // verify that the pin is a string
Number.isInteger(+pin) && // make sure that the string is an integer when converted into a number
[4, 6].includes(pin.length) // only accepts 4 and 6 character pins
}

function validatePIN(pin) {
var isNumber = /^\d+$/.test(pin) && (pin.length == 4 || pin.length == 6)
return isNumber
}
validatePIN('0193')
//returns true

You can use Array.prototype.every(), Array.prototype.some(), String.prototype.match()
<input type="text" />
<button>validate pin</button>
<script>
var validatePIN = (args) => {[...args] = args;
return args.every(v => v.match(/\d/)) &&
[4, 6].some(n => args.length === n)};
document.querySelector("button")
.addEventListener("click", (e) =>
alert(validatePIN(e.target.previousElementSibling.value))
)
</script>

function validatePIN (pin) {
//return true or false
return /^\d+$/.test(pin) && (pin.length === 4 || pin.length === 6)
}

function validatePIN (pin) {
if (pin.length !== 4 && pin.length !== 6) {
return false;
}
for (let i = 0; i < pin.length; i++) {
if (pin[i] > '9' || pin[i] < '0') {
return false;
}
}
return true;
}

Here is another way to solve using regular expression.
function validatePIN(pin) {
return /^(\d{4}|\d{6})$/.test(pin)
}
validatePIN('2345')
//returns true
validatePIN('2.45')
//reutrns false

function validatePIN (pin) {
if (pin.length == 4 || pin.length == 6)
{
for (let i = 0; i < pin.length; i++)
{
if (pin[i] == "0" ||
pin[i] == "1" ||
pin[i] == "2" ||
pin[i] == "3" ||
pin[i] == "4" ||
pin[i] == "5" ||
pin[i] == "6" ||
pin[i] == "7" ||
pin[i] == "8" ||
pin[i] == "9") ;
else return false;
}
return true;
}
else return false;
}
this code checks the PIN-length and passes all test tasks with numbers and not numbers...

public static boolean validatePin(String pin) {
return pin.matches("\\d{4}|\\d{6}");
}

Related

How to efficiently refactor if...if statement in typescript

as an exercise, I am trying to find the most efficient way to refactor this if...if statement.
This is the original code:
interface Validatable {
value: string | number;
required?: boolean;
minLength?: number;
maxLength?: number;
min?: number;
max?: number;
}
function validate(validatableInput: Validatable) {
let isValid = true;
if (validatableInput.required) {
isValid = isValid && validatableInput.value.toString().trim().length !== 0;
}
if (
validatableInput.minLength != null &&
typeof validatableInput.value === 'string'
) {
isValid =
isValid && validatableInput.value.length >= validatableInput.minLength;
}
if (
validatableInput.maxLength != null &&
typeof validatableInput.value === 'string'
) {
isValid =
isValid && validatableInput.value.length <= validatableInput.maxLength;
}
if (
validatableInput.min != null &&
typeof validatableInput.value === 'number'
) {
isValid = isValid && validatableInput.value >= validatableInput.min;
}
if (
validatableInput.max != null &&
typeof validatableInput.value === 'number'
) {
isValid = isValid && validatableInput.value <= validatableInput.max;
}
return isValid;
}
and this is what I achieved so far:
function validate(validatableInput: Validatable) {
const { required, minLength, maxLength, min, max } = validatableInput; // This methos extracts the properties from the object
const validatableInputValue = validatableInput.value;
let isValid = true;
if (required) {
isValid = isValid && validatableInputValue.toString().trim().length !== 0;
}
if (minLength != null && typeof validatableInputValue === "string") {
isValid = isValid && validatableInputValue.length >= minLength;
}
if (maxLength != null && typeof validatableInputValue === "string") {
isValid = isValid && validatableInputValue.length <= maxLength;
}
if (min != null && typeof validatableInputValue === "number") {
isValid = isValid && validatableInputValue >= min;
}
if (max != null && typeof validatableInputValue === "number") {
isValid = isValid && validatableInputValue <= max;
}
return isValid;
}
Is there anything else I could do? Like use a switch statement instead, or something else? Thank you!
All of the conditions follow a pattern: if a particular prerequisite is fulfilled, then validate the input value against something. You can exploit this by creating an array of such conditions: each item can have a prerequisite (eg required) and a test (eg value.toString().trim().length !== 0). Then iterate over the array with something like .every to check that each truthy prerequisite has its corresponding condition fulfilled.
function validate(validatableInput: Validatable) {
const { required, minLength, maxLength, min, max, value } = validatableInput;
const isStr = typeof value === "string";
const isNum = typeof value === "number";
const conditions = [
[required, value.toString().trim().length !== 0],
[minLength != null && isStr, value.length >= minLength],
[maxLength != null && isStr, value.length <= maxLength],
[min != null && isNum, value >= min],
[max != null && isNum, value <= max],
];
return conditions.every(([prereq, result]) => result || !prereq);
}
As another approach that keeps the existing structure:
function validate(validatableInput: Validatable) {
const { value, required, minLength, maxLength, min, max } = validatableInput;
if (required && value.toString().trim().length === 0) {
return false;
}
if (typeof value !== "string" || typeof value !== "number") {
return true
}
if (typeof value === "string") {
if (minLength && value.length < minLength) {
return false;
}
if (maxLength && value.length > maxLength) {
return false;
}
}
if (min && value < min) {
return false;
}
if (max && value > max) {
return false;
}
return true;
}
A few things of note:
Some people have problems with early returns; I don't--it's immediately clear while reading what happens without having to continue reading the function.
It's not as elegant as the every option, but it allows for easier modification, logging, etc. because it's very explicit and blocked out.
Since Validatable is a type I'm not sure why this functionality wants to be pulled out of it, particularly since decisions are being made based on type information of a Validatable property.

How to implement this test on prototype of String object?

How to implement this valid function?
I want to implement a test function that returns true or false,
example : 'any-string-1'.valid('!empty'):
this is my valid.js file
function valid(str) {
if (
typeof str == "undefined" ||
!str ||
str === "" ||
str.length < 10 ||
!/[^\s]/.test(str) ||
/^.*-s/i.test(str)
) {
return true;
} else if (str.length > 30) {
return false;
}
}
module.exports = valid;
Assuming you are using Jest, you can use toBe:
const emptyStr = '';
const str = 'some-str';
expect(Boolean(emptyStr.length)).toBe(false); // it's empty, it's false because length is 0;
expect(str.length > 30).toBe(false); // it's false because length is not greather than 30;
expect(str.length < 10).toBe(true); // it's true because length is lower than 10;

Abbreviate check function

I'm just starting to learn javascript and i'm trying to figure out how to make this code shorter.
Right now, the check function evaluates if a = "admin" and after that if a = "manager".
Is it possible to do this evaluation in one line?
Kind of "if (a = "admin" or "manager") ..."
const valid = "User name valid";
const invalid = "User name invalid";
function check(a, b) {
if (a === "admin") {
return valid;
} else if (a === "manager") {
return valid;
} else if (b[0].toUpperCase() == b[0] && b.length > 4 && b.length < 10) {
return valid;
} else {
return invalid;
}
}
console.log(check("manager", "ikey"));
console.log(check("admin", "root"));
console.log(check("user", "ikey"));
console.log(check("user", "Mikey"));
Thanks!!
You can use the logical or operator to handle all valid cases together.
function check(a, b) {
if (a === "admin" || a === "manager" || b[0].toUpperCase() == b[0] && b.length > 4 && b.length < 10) {
return valid;
} else {
return invalid;
}
}
You can also simplify this to one statement using the ternary operator.
function check(a, b) {
return a === "admin" || a === "manager" || b[0].toUpperCase() == b[0] && b.length > 4 && b.length < 10 ? valid : invalid;
}
You should do it with or operator || like so:
if (a === "admin" || a === "manager" || (b[0].toUpperCase() == b[0] && b.length > 4 && b.length < 10))
return valid;
else
return invalid;

Valid Braces - CodeWars Challenge

There is a challenge on codewars that asks you to check whether a string of parentheses, brackets, and curly braces is valid.
A string of braces is considered valid if all braces are matched with the correct brace.
I.e. "()" is valid and "[(])" is not.
"(){}[]" is valid and "[({})](]" is not. Etc.
I've been able to create some logic to check for whether or not there are the right number of opening and closing braces.
ATTEMPT:
function validBraces(braces) {
let parenCount = 0;
let squareBracketCount = 0;
let curlyBraceCount = 0;
for (let i =0; i < braces.length; i++) {
let character = braces[i];
if (character === "(") {
parenCount -= 1;
}
if (character === ")") {
parenCount += 1;
}
if (character === "[") {
squareBracketCount -= 1;
}
if (character === "]") {
squareBracketCount += 1;
}
if (character === "{") {
curlyBraceCount -= 1;
}
if (character === "}") {
curlyBraceCount += 1;
}
}
if (parenCount === 0 && squareBracketCount === 0 && curlyBraceCount === 0) {
return true;
}
else {
return false;
}
}
But I've not been able to come up with a way to check for whether or not the opening brace "closes" before the next type of brace opens.
Maybe something like this?
if (
(firstChar === "(" && lastChar === ")") ||
(firstChar === "{" && lastChar === "}") ||
(firstChar === "[" && lastChar === "]")
) {
return true;
} else {
return false;
}
But then this would have to be checked in accordance with my other if-statement...(?)
EDIT: Key to understanding this challenge is that the closing brace must either come directly after the opening brace or it must be "parallel" - in symmetry with the other.
You don't really need to use arrays here, you can just use regex and recursion:
const regex = /\(\)|\[\]|\{\}/;
const validBraces = braces => regex.test(braces)
? validBraces(braces.replace(regex, ''))
: '' === braces
console.log(validBraces('{{}}')) // true
console.log(validBraces('{{[]}}')) // true
console.log(validBraces('{[{}]}')) // true
console.log(validBraces('({{}})')) // true
console.log(validBraces('{[()]}')) // true
console.log(validBraces('{{}[}')) // false
console.log(validBraces('{{]}}')) // false
console.log(validBraces('{}}')) // false
console.log(validBraces('{({}}')) // false
console.log(validBraces('((}}')) // false
console.log(validBraces('}[)}')) // false
You can use array to keep track of previously appeared opening braces and once any closing tag appears you need to match it with the last value of array if it's matching pop the last value out of else else return false, in the end if you're left with empty array return true else return false
function validBraces(braces){
let tracer = []
for(let i=0;i < braces.length; i++){
if ( braces[i] === "(" || braces[i] === "{" || braces[i] === "["){
tracer.push(braces[i])
} else{
if(tracer.length === 0) return false
let lastValue = tracer[tracer.length-1]
if( (braces[i] === ']' && lastValue === '[') || (braces[i] === '}' && lastValue === '{') || (braces[i] === ')' && lastValue === '('))
{
tracer.pop()
} else {
break;
}
}
}
return tracer.length === 0
}
console.log(validBraces( "()" )) // true
console.log(validBraces( "[]" )) // true
console.log(validBraces( "{}" )) // true
console.log(validBraces( "(){}[]" )) // true
console.log(validBraces( "([{}])" )) // true
console.log(validBraces( "(}" )) // false
console.log(validBraces( "[(])" )) // false
console.log(validBraces( "({})[({})]" )) // true
console.log(validBraces( "(})" )) // false
console.log(validBraces( "(({{[[]]}}))" )) //true
console.log(validBraces( "{}({})[]" )) // true
console.log(validBraces( ")(}{][" )) // false
console.log(validBraces( "())({}}{()][][" )) // false
console.log(validBraces( "(((({{" )) // false
console.log(validBraces( "}}]]))}])" )) // false
In scala you can do this
object Kata {
def validBraces(s: String): Boolean =
s.replace("()", "").replace("[]", "").replace("{}", "") match { case "" => true; case `s` => false; case x => validBraces(x) }
}
function validBraces(braces){
while(/\(\)|\[\]|\{\}/g.test(braces)){braces = braces.replace(/\(\)|\[\]|\{\}/g,"")}
return !braces.length;
}
// double regex
My JavaScript solution of this kata is simple to understand and passes all tests. Yet im aware its optimization isn't top-notch. It simply eliminates elements step by step:
Start: ( { [] } ) || ( { [] } }
Then: ( {} ) || ( {} }
Then: () || (}
Finish: clear || leftovers
When length = 0 it passes, and when length > 0 it wont
function validBraces(braces){
while(braces.indexOf("{}") !== -1 || braces.indexOf("()") !== -1 || braces.indexOf("[]") !== -1){
braces = braces.replace("{}", "").replace("()", "").replace("[]", "");
}
return braces.length === 0 ? true: false;
console.log(validBraces("(({{[[]]}}))"));
I have done it in Scala with some tests and it works. In case the string's length is 2 if dont need to enter the recursive call because in the match you have already checked if it correct or not :
object Kata1{
def validBraces(s: String): Boolean ={
var valid: Boolean = true
if(s.length > 1){
s(0) match{
case '(' => if( s(1) == ')' || s(s.length-1) == ')'){
if(s.length != 2){
if(s(1) == ')'){
valid = validBraces(s.substring(2, s.length))
}else{
valid = validBraces(s.substring(1, s.length-1))
}
}
} else {
if(s.lastIndexOf(')') != -1){
var newS = s.substring(0, s.indexOf(')')).concat(s.substring(s.indexOf(')')+1, s.length))
valid = validBraces(newS.substring(1, s.length-1))
}else valid = false
}
case '[' => if( s(1) == ']' || s(s.length-1) == ']') {
if(s.length != 2){
if(s(1) == ']'){
valid = validBraces(s.substring(2, s.length))
}else{
valid = validBraces(s.substring(1, s.length-1))
}
}
} else {
if(s.lastIndexOf(']') != -1){
var newS = s.substring(0, s.indexOf(']')).concat(s.substring(s.indexOf(']')+1, s.length))
valid = validBraces(newS.substring(1, s.length-1))
}else valid = false
}
case '{' => if( s(1) == '}' || s(s.length-1) == '}') {
if(s.length != 2){
if(s(1) == '}'){
valid = validBraces(s.substring(2, s.length))
}else{
valid = validBraces(s.substring(1, s.length-1))
}
}
} else {
if(s.lastIndexOf('}') != -1){
var newS = s.substring(0, s.indexOf('}')).concat(s.substring(s.indexOf('}')+1, s.length))
valid = validBraces(newS.substring(1, s.length-1))
}else valid = false
}
case _ => valid = false
}
/*if(s.length != 2 && valid){
if(s(1) == ')' || s(1) == '}' || s(1) == ']' ){
valid = validBraces(s.substring(2, s.length))
}else{
valid = validBraces(s.substring(1, s.length-1))
}
}*/
}else{
valid = false
}
if(s.length == 0){
valid = true
}
valid
}
}
Kata1.validBraces("()") //true
Kata1.validBraces("[()]") //true
Kata1.validBraces("[(])") //false
Kata1.validBraces("([{}])") //true
Kata1.validBraces("([{]})") //false
Kata1.validBraces("{({{()}({}())})}")//true
Kata1.validBraces("({]}{")//false

some() function is not working with && operator

I´m triying to use the some() function with && operator, but always return false, even if both conditions are inside in the array.
For example:
if (acciones.some(a => a.accionID == 7 && a.accionID == 8)) {
return true;
} else {
return false;
}
You're checking one specific accionID on each call to the some callback. That one accionID cannot be both == 7 and == 8 at the same time. Any given accionID will be 7 or 8.
If you want to see if all of the acciones have accionID of 7 or 8, use every with ||:
if (acciones.every(a => a.accionID == 7 || a.accionID == 8)) {
// ----------^--------------------------^
If you want to see if any of the acciones has an accionID of 7 or 8, use some with ||:
if (acciones.some(a => a.accionID == 7 || a.accionID == 8)) {
// ----------^-------------------------^
If acciones has at least one entry in it where accionID is (say) 6, the every check will be false, and the some check will be true.
Since some and every already return a boolean, there's no need for:
if (acciones.every(a => a.accionID == 7 || a.accionID == 8)) {
return true;
} else {
return false;
}
Just use
return acciones.every(a => a.accionID == 7 || a.accionID == 8);
In general, if you find yourself writing:
if (x) {
return true;
} else {
return false;
}
then:
If x is already a boolean, you can do just
return x;
If x is not necessarily boolean (and it matters that you return a boolean, specifically), you can use the !! idiom to make it a boolean:
return !!x;
Similarly, if you find yourself writing:
if (x) {
return false;
} else {
return true;
}
you can always write that as
return !x;
instead.

Categories

Resources