JS Logical operators - OR, AND ('||', '&&') in switch statement - javascript

The below function is working as expected except case noticed in a comment, namely, for each number:
if the number is divisible by three I want to log out the word fizz instead of that number
if the number is divisible by five I want to log out the word buzz instead of that number.
And if a number is divisible by both 3 and 5 I want to log out the word fizzbuzz instead of that number.
Example - 1
const FizzBuzz = (num) => {
for (let i = 1; i <= num; i++) {
const foo = 0;
switch (foo) {
case (i % 3 || i % 5): console.log('fizzbuzz');
// expect in this case should be work with logical operator '&&': (i % 3 && i % 5)
break;
case i % 3: console.log('fizz');
break;
case i % 5: console.log('buzz');
break;
default: console.log(i);
}
}
}
FizzBuzz(20)
This is how I know - With switch-case statement preferable use:
Example 2
switch(true) {
case (i % 3 === 0 && i % 5 === 0): console.log('fizzbuzz');
break;
// etc...
}
But with the instance of code above (Example 1: where switch(foo) doesn't have the constant value like true), it looks more flexible and readable.
And in "Example 1", as I understood, the operator || works like operator && and vice versa.
The "Example 1" works perfectly as result. But I can't understand Why. Primarily my question is - Why the logical operator OR behave as an operator AND in this example??
Thnx in advance.

The issue is that you're switching on foo, and foo is 0, so case <expression> will run when <expression> evaluates to 0.
So, case i % 3 runs when expected, because you want the i % 3 case to run when that evaluates to 0. Same for i % 5. But
case (i % 3 || i % 5)
, when i is a multiple of 15, resolves to
case (15 % 3 || 15 % 5)
->
case (0 || 0)
Because 0 is falsey, the || will mean that both 15 % 3 and 15 % 5 must be 0 for the case there to resolve to 0 (and thus match foo's 0).
If you used &&, then the && expression will evaluate to the first falsey value, rather than requiring both %s to resolve to 0, eg when i is 3:
case (3 % 3 && 3 % 5)
->
case (0 && 2)
->
case 0
which then matches foo's 0, despite the fact that only one of the conditions in the && resolved to 0.
It's extremely unintuitive. Don't use switch here. If you had to use switch, I'd highly recommend setting foo to true instead, and using === 0 tests:
const FizzBuzz = (num) => {
for (let i = 1; i <= num; i++) {
const foo = true;
switch (foo) {
case i % 3 === 0 && i % 5 === 0:
console.log('fizzbuzz');
break;
case i % 3 === 0:
console.log('fizz');
break;
case i % 5 === 0:
console.log('buzz');
break;
default:
console.log(i);
}
}
}
FizzBuzz(20)

The code in Example 1 works because you switch on the variable foo which is set to 0.
The code in the first case is evaluated to 0:
15 % 3 || 15 % 5 = 0
This value gets compared to foo which is 0 and so the JS code enters the first case.
In JavaScript logical OR operators always return the first "truthy" value.
'foo' || 'bar' = 'foo'
false || 'bar' = 'bar'

Related

Checking divisibility and converting digits into text

Check the divisibility of 2, 3, and both 2 and 3
Divisible by 2 - print x
Divisible by 3 - print y
Divisible by 2 and 3 - print xy
let num = prompt('1-1000');
if (num %2 == 0 )
{
console.log("X")
}
if (num %3 == 0 )
{
console.log("Y")
}
if (num %3 == 0 && num %2 ==0)
{
console.log("XY")
}
Example:
Input: 6
Output:
X
Y
XY
How to make it not print X, Y but XY?
What needs to be done so that several digits to be checked after the decimal point can be entered and then converted to the appropriate letters?
There are a couple of ways you could do this.
One way would be to use a ternary operator to output the values X and/or Y. This will have X logged only when divisible by 2, and Y only logged when divisible by 3. If it is divisible by both, both are shown but their conditions are independent of each other. And using template literals it is concatenated into 1 value.
let num = prompt('1-1000');
console.log(`${(num%2==0)?"X":""}${(num%3==0)?"Y":""}`);
Alternatively, you could use something like what was mentioned in the comments. If you convert the code to a function, you can move the final if statement to the top and use exit/return statements to return only 1 of the values (whichever applies).
const _Check = () => {
let num = prompt('1-1000');
if(num % 3 == 0 && num % 2 == 0) return "XY";
if(num % 2 == 0 ) return "X";
if(num % 3 == 0 ) return "Y";
return "";
}
console.log(_Check());
EDIT
In reponse to a comment by OP: checking for multiple numbers could be done by splitting the value input by the user and then looping through those values.
If the user will be inputting each number separated by a space, you can use the split() method with a space as the separator. And then use forEach() to loop through each number and apply the code/logic we have used earlier.
Example Using ternary operator and template literals:
let num = prompt('1-1000')
num.split(" ").forEach(n => {
console.log(`${(n%2==0)?"X":""}${(n%3==0)?"Y":""}`);
})
Example using a function and return statements:
let num = prompt('1-1000')
const _Check = n => {
if(n %3 == 0 && n %2 ==0) return "XY";
if(n %2 == 0 ) return "X";
if(n %3 == 0 ) return "Y";
return "";
}
num.split(" ").forEach(n => {
console.log(_Check(n));
})

usage of !(not) operator in switch case

// checking whether a number is a multiple of 3 or not
for (let number = 1; number <= 100; number++) {
switch (number % 3) {
case !0: // Here I have used !(not) but it's not helping, I only want to know why '!' is not helping
console.log(`${number} is not multiple of 3`);
break;
default:
console.log(`${number} is multiple of 3`)
}
}
Here the 1st case is not working. Code execution has no problems but the 1st case is not helping at all. The complete flow is going to the 'default:' code block only. Whenever the remainder is not equal to 0, the 1st case's code block should be executed, but it's always going to the default code block.
You can't do it in this way because !0 is always true in JavaScript so the loop always enters in the first case
Try it in this way
for (let number = 1; number <= 100 ;number++ ) {
if(number % 3){
console.log(`${number} is not multiple of 3`);
}
else{
console.log(`${number} is multiple of 3`);
}
}
The switch statement receives values on case statements, not expressions like the if. So, when js run your code, it will evaluate !0 to true (inverse of a falsy value is true).
You must replace your switch by if and elses:
for (let number = 1; number <= 100 ;number++ ) {
if ((number % 3) !== 0) {
console.log(`${number} is not multiple of 3`);
} else {
console.log(`${number} is multiple of 3`)
}
}
But you can still use a switch case statement if you invert the logic:
for (let number = 1; number <= 100 ;number++ ) {
switch (number % 3) {
case 0:
console.log(`${number} is multiple of 3`)
break;
default:
console.log(`${number} is not multiple of 3`);
}
}
But really makes no sense using a switch case in this situation since an if-else is much simpler and easier to read.
!0 evals to true, which is not equals to 1 or 2.
Consider writing it in this way:
for (let number = 1; number <= 100; number++) {
switch (number % 3) {
case 0:
console.log(`${number} is multiple of 3`)
break;
default:
console.log(`${number} is not multiple of 3`);
}
}
In JS, 0 is considered falsy that's why !0 will equals true ( not falsy ).
As for your switch, you could reverse your it and use a true as the switch values. The cases would then have the expression to check
for (let number = 1; number <= 100 ;number++ ) {
switch (true) {
case number % 3:
console.log(`${number} is not multiple of 3`);
break;
default:
console.log(`${number} is multiple of 3`)
}
}

Why do both these two solutions for printing all numbers divisible by 3 AND 5 between 5 and 50 work?

This was my solution to the problem:
var count = 5;
while (count <= 50) {
if ((count % 3 || count % 5) === 0) {
console.log(count);
}
count++;
}
This was my the instructors solution:
var count = 5;
while (count <= 50) {
if (count % 3 === 0 && count % 5 === 0) {
console.log(count);
}
count++;
}
Both of these solutions gave the proper answer, but I question why || worked in my problem, rather than &&, I tried both. && means both need to be true for it to properly run, right? So wouldn't that have been the proper use?
var count = 5;
while(count <= 50) {
console.log(`count = ${count} | (count % 3 || count % 5) = ${(count % 3 || count % 5)}`);
if((count % 3 || count % 5) === 0) {
console.log(count);
}
count++;
}
This happens because in all cases where count % 3 === 0 and count % 5 does not, the number takes precedence in the or (||) statement since it's "truthy".
eg.
count = 6, 0 || 1 // 1, since 0 is "falsy"
count = 8, 2 || 3 // 2
count = 15, 0 || 0 // 0
Therefore, it seems you stumbled on the correct solution.
It is a javascript peculiarity you encounter. If count % 3 is 0 it is considered "falsy" and the other calculation will be used. So if either modulus has a remains, that value is used in the final test against 0.
So while both works, your teachers code is more readable; thus better.
The following code
(count % 3 || count % 5) === 0
evaluates first the % operations and then the or to end with ===. If both modulo operations return 0, the or condition also evaluates as 0, that compared with 0 equals true and print the numbers. Otherwise, if any of the modulo values isn't 0, the or operation will result in these numbers, hence it won't be printed.
This is because Javascript evaluates numeric values as boolean being 0 False, and any other value True.
In your case it's a question of parenthesis
1st case of || with parenthesis like this ((count % 3 || count % 5) === 0) it like you say count has to be % by 3 and 5 so it's like &&
2nd case (count % 3 === 0 && count % 5 === 0) you've changed the parenthesis to regroup all
with && in the middle
so as i said it's question of parenthesis that makes both solution give the same result
Every value except 0 is evaluated as true. If there is a number divisible by 3 AND 5 both, then 0 || 0 is 0, which makes your if condition to run. If there is a number that is only divisible by 3 OR 5, lets say 10, then 10%3 is equal to 10 and 10%5 is equal 0. 10 || 0 will be evaluated as true (non-zero). Since non-zero value is not equal to 0 therefore if condition will not execute.
I am not sure but your instructors expression can be said as created from your expression by using Demorgans law.
The second solution is more useful than the first.
Because always "%" operator is computational, not logical

Function explanation using the ?: ( conditional operator in javascript )

I'm trying to understand this function that returns the ordinal numbers when we give it a number.
Unfortunately I couldn't figure out how this is working with the conditional operator, could someone explain it to me?
function getOrdinalNum(n) {
return n + (n > 0 ? ['th', 'st', 'nd', 'rd'][(n > 3 && n < 21) || n % 10 > 3 ? 0 : n % 10] : '');
}
The best way to explain this sort of thing is to break it down into a function with if statements. Take a look at the newFunction it does the same thing that the function getOrdinalNum does:
function getOrdinalNum(n) {
return n + (n > 0 ? ['th', 'st', 'nd', 'rd'][(n > 3 && n < 21) || n % 10 > 3 ? 0 : n % 10] : '');
}
function newFunction(n) {
if (n > 0) {
if ((n > 3 && n < 21) || n % 10 > 3) {
return n + 'th'; // essentially returning ['th', 'st', 'nd', 'rd'][0];
} else {
return n + ['th', 'st', 'nd', 'rd'][n % 10];
}
}
}
for(let i = 1; i < 9; i++) {
console.log(getOrdinalNum(i));
console.log(newFunction(i));
}
Break it down like this:
n +
(
n > 0
? ['th', 'st', 'nd', 'rd']
[
(n > 3 && n < 21) || n % 10 > 3
? 0
: n % 10
]
: ''
);
Here:
JS checks if n > 0. If yes then:
An array is created ['th', 'st', 'nd', 'rd']
The next [] tells us a property accessor will follow
Which property is determined by the ternary operation. Either 0 (which will mean (th) or the result of n & 10
And the result of accessing that property is added whatever n was.
If n is smaller or equal with 0 then whatever n was, an empty string is added to it.
It helps to know the operator precedence in JS. Give it a goooood read and practice some.
Operators (unary, binary, ternary)
The ternary conditional operator is different than most other operators in that it takes 3 operands instead of one or two.
You are used to unary operators like the negative symbol in -5 which takes one operand and makes it a negative value.
There is also the binary concatenation operator + used like 'hello ' + 'world'. Here there are two operands which produce the value 'hello world'.
The ternary conditional operator has the form
/* conditional expression */ ? /* expression if truthy */ : /* expression if not truthy*/
Where the comments are the operands for you to fill in with the more complex code from your example. // if n > 0 then the complex expression, otherwise the empty string
Simple example.
Try to run the following statements in your browser.
console.log(true ? 'true value' : 'false value');
var x = 3 > 1 ? 'true value' : 'false value';
console.log(x);
prompt('try entering a blank space, or characters') ? 'a' : 'b';
The code flows much the same as the other answers describe. The first expression is emitted if the condition is truthy otherwise the second expression is emitted.
Here are some docs on what I mean by truthy

javascript fizzbuzz switch statement

I'm currently taking the code academy course on Javascript and I'm stuck on the FizzBuzz task. I need to count from 1-20 and if the number is divisible by 3 print fizz, by 5 print buzz, by both print fizzbuzz, else just print the number. I was able to do it with if/ else if statements, but I wanted to try it with switch statements, and cannot get it. My console just logs the default and prints 1-20. Any suggestions?
for (var x = 0; x<=20; x++){
switch(x){
case x%3==0:
console.log("Fizz");
break;
case x%5===0:
console.log("Buzz");
break;
case x%5===0 && x%3==0:
console.log("FizzBuzz");
break;
default:
console.log(x);
break;
};
};
Switch matches the x in switch(x){ to the result of evaluating the case expressions. since all your cases will result in true /false there is no match and hence default is executed always.
now using switch for your problem is not recommended because in case of too many expressions there may be multiple true outputs thus giving us unexpected results. But if you are hell bent on it :
for (var x = 0; x <= 20; x++) {
switch (true) {
case (x % 5 === 0 && x % 3 === 0):
console.log("FizzBuzz");
break;
case x % 3 === 0:
console.log("Fizz");
break;
case x % 5 === 0:
console.log("Buzz");
break;
default:
console.log(x);
break;
}
}
I thought switch too,but no need.
for (var n = 1; n <= 100; n++) {
var output = "";
if (n % 3 == 0)
output = "Fizz";
if (n % 5 == 0)
output += "Buzz";
console.log(output || n);
}
Switch statement checks if the situation given in the cases matches the switch expression. What your code does is to compare whether x divided by 3 or 5 is equal to x which is always false and therefore the default is always executed. If you really want to use a switch statement here is one way you can do.
for (var i=1; i<=30; i++){
switch(0){
case (i % 15):
console.log("fizzbuzz");
break;
case (i % 3):
console.log("fizz");
break;
case (i % 5):
console.log("buzz");
break;
default:
console.log(i);
}
}
Not to too my own horn but this is much cleaner:
var numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
for (var i = 1; i <= numbers.length; i++) {
if (i % 15 === 0) {
console.log("FizzBuzz");
} else if (i % 5 === 0) {
console.log("Buzz");
} else if (i % 3 === 0) {
console.log("Fizz");
} else {
console.log(i);
}
};
The switch(true) part of this statement helped me. I was trying to do a switch statement for fizzbuzz. My solution incorporates the coding style of Rosettacodes - general solution. Most significantly the use of force typing to shorten the primary conditionals. I thought, it was valuable enough to post:
var fizzBuzzSwitch = function() {
for (var i =0; i < 101; i++){
switch(true) {
case ( !(i % 3) && !(i % 5) ):
console.log('FizzBuzz');
break;
case ( !(i % 3) ):
console.log('Fizz');
break;
case ( !(i % 5) ):
console.log('Buzz');
break;
default:
console.log(i);
}
}
}
Here's what made it clear for me, might help :
It's a misinterpretation of what switch (x){} means.
It doesn't mean : "whenever whatever I put inbetween those brackets is true, when the value of x changes."
It means : "whenever x EQUALS what I put between those brackets"
So, in our case, x NEVER equals x%3===0 or any of the other cases, that doesn't even mean anything. x just equals x all the time. That's why the machine just ignores the instruction. You are not redefining x with the switch function. And what you put inbetween the brackets describes x and x only, not anything related to x.
In short :
With if/else you can describe any condition.
With switch you can only describe the different values taken by the variable x.
Here's a solution incorporating #CarLuvr88's answer and a switch on 0:
let fizzBuzz = function(min, max){
for(let i = min; i <= max; i++){
switch(0){
case i % 15 : console.log('FizzBuzz'); break;
case i % 3 : console.log('Fizz'); break;
case i % 5 : console.log('Buzz'); break;
default : console.log(i); break;
}
}
}
fizzBuzz(1,20)
We can use a function to find a multiple of any number and declare two variables to identify these multiples so that if you want to change the multiples you only need to change at max 2 lines of code
function isMultiple(num, mod) {
return num % mod === 0;
}
let a = 3;
let b = 5;
for(i=0;i<=100;i++){
switch(true){
case isMultiple(i,a) && isMultiple(i,b):
console.log("FizzBuzz")
case isMultiple(i,a):
console.log("Fizz");
case isMultiple(i,b):
console.log("Buzz");
default:
console.log(i);
}
}

Categories

Resources