Hooves
Hooves

Reputation: 1

Why does this set of logical operators work correctly?

So I'm doing a puzzle to evaluate Kaprekar's Routine and in the first section I need to check to make sure the 4 digit input has at least two unique digits so I did this:

let numArr = num.toString().split("");

if (numArr[0] == numArr[1] && numArr[2] && numArr[3]) {
  return 0;
}

I tried searching but I keep finding links to short-circuiting operators. I was expecting to write out numArr[0] == into every && block but to my surprise it worked. Can anyone explain why this returns 0 for 3333 but does not for 1234? I assumed numArr[2] and numArr[3] would just evaluate to true automatically.

Upvotes: 0

Views: 70

Answers (3)

user34537
user34537

Reputation:

There is a thing called operator precedence. The operator with higher precedence happens first. == happens before &&. When you have more than one operator of the same precedence it goes by 'associativity' which is generally left to right (= for example is right to left); so let's take another look at your code

if ( ((numArr[0] == numArr[1]) && numArr[2]) && numArr[3] )

Let's take just the first piece. Doing 3 == 3 is true and since none of the operators are 0, the if statement is true. But with 1234, 1 == 2 is false, so the expression short circuits to false. Generally when something (like an if statement) accepts a boolean value && a non zero/undefined/false value, the expression is considered true (I may be wrong). If you do the below you should get true

if ( numArr[0] && numArr[1] && numArr[2] && numArr[3] )

To answer your other question, generally when people work with a set of data in JS they use lodash. You can find the if there is 2 unique values easily with the line blow. uniq(array, func) returns an array with unique values in the same order. See the documentation

_.uniq("3333".toString().split(""), v=>v).length >= 2 //false
_.uniq("1224".toString().split(""), v=>v).length >= 2 //true

Upvotes: 2

Jecoms
Jecoms

Reputation: 2848

You have three expressions being evaluated

// loose-equality, so true if after type-coersion, the values are equivalent
// this is the only condition that is actually changing in your code, unless
// you have a number with less than 4 digits
numArr[0] == numArr[1] 

// is a non-empty string so it's 'truthy'
numArr[2] 

// is a non-empty string so it's 'truthy'
numArr[3] 

Anything that is not Falsy (false, 0, "", null, undefined, and NaN) is Truthy

Therefore, you need to write additional code to check for unique digits.

Upvotes: 0

Geeky
Geeky

Reputation: 7498

It is because For String 3333 num[0] is 3,num[1]=3,num[2]=3,num[3]=3

Expressions evaluate based on precedence of operators and when the operators have the same precedence they get executed from left to right

In this case == has highest precedence over && so, num[0]==num[1] ,it is 3==3 true then true && num[2] && num[3] => true&&3&&3 => true

For string 1234 num[0]=1,num[1]=2,num[2]=3,num[3]=4 num[0]==num[1] ,1==2 is false so now the expression is false && num[2] && num[3]

For && operator if the first operand is false,it ignore the rest of the expression so now it just results as false

Hope this helps

Upvotes: 0

Related Questions