Multiple Sets of Sets of ORs - javascript

I have a feeling this isn't possible? I'm trying to check sets of conditions here and my tests should be passing after I moved a couple of those sets out of 2 other methods and into this if statement below as to combine all the checks into one if statement:
if ((move.coordinates.x === 0 && move.coordinates.y === 0 ||
move.coordinates.x === 0 && move.coordinates.y === 1 ||
move.coordinates.x === 0 && move.coordinates.y === 2)
||
(move.coordinates.x === 1 && move.coordinates.y === 0 ||
move.coordinates.x === 1 && move.coordinates.y === 1 ||
move.coordinates.x === 1 && move.coordinates.y === 2)
||
(move.coordinates.x === 2 && move.coordinates.y === 0 ||
move.coordinates.x === 2 && move.coordinates.y === 1 ||
move.coordinates.x === 2 && move.coordinates.y === 2))
{
...then do something
}
Doesn't seem the parens are making a difference here in separating out the conditional sets.
I'm trying to trim down on duplicate code I had those 3 sets in different methods where the logic was mostly the same, but checked for different states.
So I pasted in the two other state sets (sets meaning the group of 3 ors that make up a given state) and trying to check these 3 rows basically in one method instead of splitting out into 3 to cut down dup code.

Simplifying the notation, you have
(x == 0 && y == 0 || x == 0 && y == 1 || x == 0 && y == 2)
||
(x == 1 && y == 0 || x == 1 && y == 1 || x == 1 && y == 2)
||
(x == 2 && y == 0 || x == 2 && y == 1 || x == 2 && y == 2)
Since the operator || is associative, you can remove the parentheses.
And then you can use the distributive property to group the x.
x == 0 && (y == 0 || y == 1 || y == 2) ||
x == 1 && (y == 0 || y == 1 || y == 2) ||
x == 2 && (y == 0 || y == 1 || y == 2)
And even use the distributive property again
(x == 0 || x == 1 || x == 2) && (y == 0 || y == 1 || y == 2)
Finally, you can store the allowed values in an array and use indexOf to avoid repeating the variables:
var values = [0, 1, 2];
values.indexOf(x) >= 0 && values.indexOf(y) >= 0;

you can use logical rules that cover all the possibilities you allow. if you look at the repeating values in your code, you see that you are trying to exhaust all combinations of x values 0,1,2 with combinations of y values 0,1,2. so if you make a rule that will encompass x values from 0 to 2 and the same with y values from 0 to 2, you can simplify your if statement like the example below.
var coordx = move.coordinates.x;
var coordy = move.coordinates.y;
if ((coordx >= 0 && coordx <= 2) && (coordy >= 0 && coordy <=2)) {
// do something
}

One issue I see with your code is the order of operations (take a look here to see the basics), consider using more brackets to be as explicit as possible. It looks like you want to do this:
if (( (move.coordinates.x === 0 && move.coordinates.y === 0) ||
(move.coordinates.x === 0 && move.coordinates.y === 1) ||
(move.coordinates.x === 0 && move.coordinates.y === 2))
||
...
But, if you want to be a little more efficient and clear, I would recommend reformatting your logic with nested if statements:
if (x==0 || x==1 || x==2)
{
if(y==0 || y==1 || y==2)
{
do something...

Related

Google Custom Script to evaluate values and assign cell value

I am having trouble getting my script to function the way I want it to. What I want it to do is take 3 values, evaluate them against several arguments then pass a value into a specific cell based on the evaluation. So far I have this;
function myFunction() {
var f = SpreadsheetApp.getActiveSheet().getRange("B$8");
var l = SpreadsheetApp.getActiveSheet().getRange("B$14");
var m = SpreadsheetApp.getActiveSheet().getRange("B$20");
if(f >= 1 && l >= 1 && m >= 1) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('0');
} else if (f >= 2) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('0');
} else if (f == 1 && l == 0 && m == 0) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('1');
} else if (f == 0 && l >=1 && m >= 1) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('2');
} else if (f == 0 && l+m <= 4) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('3');
} else if (f == 0 && l == 0 && m <=4) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('4');
} else if (f == 0 && i == 0 && m == 0) {
SpreadsheetApp.getActiveSheet().getRange('B$49').setValue('5');
} else {
SpreadsheetApp.getUi().alert('There has been an error, please rate manually');
}
}
No matter what values I have in cells B8, B14 or B20 I get the error message.
I would also like it to be able to function in multiple columns, while rows stay the same (hense the '$' in ranges). Though I am not certain I am doing this correctly.
If anyone could take a look through my code and explain what I am doing wrong and help me understand how to fix it that would be greatly appreciated.
In the lines getting data, you need to add .getValue() like this:
SpreadsheetApp.getActiveSheet().getRange("B$8").getValue()
You have a typo in:
else if (f == 0 && i == 0 && m == 0)
I believe the i should be l.
Also, check your logic for the value '3'. Like it is you will never get to '4' or '5'.

Why is the 'o' is true? Javascript(Angular)

Help me please, I'm trying to make a rule for the little game and there is the problem.
I'm creating winning combination and say if the cell && cell+1 && cell+2 == to 'X' then you win, but when between two "X"s presents "o" it also says that "X" wins. Why? Please see my code and the game example on link a the bottom.
this.rezult = function(){
this.arr2.forEach(function(arr, i, innerArr){
arr.forEach(function(val, j){
var wincomb = innerArr[i][j] && innerArr[i][j+1] && innerArr[i][j+2];
var wincomb2 = innerArr[i][j] && innerArr[i+1][j] && innerArr[i+2][j];
var wincomb3 = innerArr[i][j] && innerArr[i+1][j+1] && innerArr[i+2][j+2];
console.log(wincomb == "X" && innerArr[i][j] !== "o");
// console.log(innerArr);
// THE RULE
if(wincomb == "X"){
alert(' X wins!');
}
});
});
};
Link to JSFiddle
In JavaScript, the && operator has interesting behavior with non-boolean values.
If the left-side of && is "truthy", the result is the right-side.
If the left-side of && is "falsey", the result is the left-side.
All non-empty strings are "truthy".
So, consider these examples:
("A" && "B" && "C") === "C"
("" && "B" && "C") === ""
(0 && "B" && "C") === 0
("X" && "X" && "O") === "O"
("O" && "O" && "X") === "X"
By the looks of it, you're trying to check if all 3 values are equal. You shouldn't use && for that, you should use === for that.
At the risk of doing your homework for you ;) here's a good way to do this:
function areTheSame(a,b,c) {
return a === b && b === c;
}
var down = areTheSame(innerArr[i][j], innerArr[i][j+1], innerArr[i][j+2]);
var across = areTheSame(innerArr[i][j], innerArr[i+1][j], innerArr[i+2][j]);
var diagonal = areTheSame(innerArr[i][j], innerArr[i+1][j+1], innerArr[i+2][j+2]);
if (down || across || diagonal) {
var winner = innerArr[i][j];
alert( winner + " wins!");
}

Example of expression where the precedence of AND (&&) over OR (||) matters?

In all of the JavaScript operator precedence charts I can find (like this one and this one), the logical AND (&&) has slightly higher precedence to the logical OR (||).
I can't seem to figure out an expression where the result is different than it would be if they had the same precedence. I figure there must be some way for it to matter or they'd be listed as having the same precedence if it didn't.
For example:
0 || 2 && 0 || 3
is 3, but it doesn't matter how I slice that up, it's always going to be 3:
(0 || 2) && 0 || 3
0 || (2 && 0) || 3
(0 || 2 && 0) || 3
0 || 2 && (0 || 3)
0 || (2 && 0 || 3)
If I make that first 0 something else (like 4), the result is always 4 because the first || doesn't even look at the right-hand side. If I swap the 0 and 3 in the last || around, the result remains 3.
The closest I've come is
0 || false && "" || NaN
...which is NaN, whereas
0 || false && ("" || NaN)
...is false, but I think that's explained purely by the left-to-right semantics, not by && being higher precedence.
I must just be missing it, for what expression does it matter that && has a higher precedence than ||?
true || false && false
is true
(true || false) && false
is false
true || (false && false)
is true
If they had the same precedence and were left-associative, then e.g. the expression
1 || 0 && 2
would be
((1 || 0) && 2) // evaluates to 2
instead of the
(1 || (0 && 2)) // evaluates to 1
that we get from the "usual" precedence rules.
For your structure … || … && … || … (which would be (((… || …) && …) || …) instead of normal ((… || (… && …)) || …)), you'd get different results for values like 0 0 1 0.
Why does the logical AND have slightly higher precedence to the logical OR?
So that the canonical form of boolean expressions, the disjunctive normal form, does not need any parenthesis.
Example:
1 || 0 && 0 -> (1 || 0) && 0 -> (1) && 0 -> 0
1 || 0 && 0 -> 1 || (0 && 0) -> 1 || (0) -> 1

JavaScript if statement test for one or the other but not both

Hello fellow StackOverflowers. I'm have a brain fart right now, and I cannot seem to figure this out.
I have the following code
if ((n % 3 === 0 || n % 5 === 0) &&( n % 3 !== 0 && n % 5 !== 0))
{
return true;
}
else {
return false;
}
Basically I need to test if the number is a multiple of 3 || 5 but not a multiple of both.
However when I enter any number I enter (whether it is multiple of 3 || 5 || both) the test always fails. I would have thought this was able to be performed in one statement.
This code though does work fine.
if (n % 3 === 0 || n % 5 === 0)
{
if( n % 3 === 0 && n % 5 === 0)
{
return false;
}
else {
return true;
}
}
else {
return false;
}
But I'm wondering what I am missing in the first test. I'd like all the test to be in one like, but like I said I'm having a brain fart and cannot figure out what I'm missing.
You can use the XOR operator, alternatively
return (n % 3 === 0 ^ n % 5 === 0);
If it is divisible by both 3 and 5, it'll be divisible by 15.
Please try the following condition
if ((n % 3 === 0 || n % 5 === 0) && ( n % 15 !== 0))
change
if ((n % 3 === 0 || n % 5 === 0) &&( n % 3 !== 0 && n % 5 !== 0))
to
if ((n % 3 === 0 || n % 5 === 0) && !(n % 3 === 0 && n % 5 === 0))
The first part of your logic is to determine if the number in question is a multiple of 3 or 5 whereas the second SHOULD be about wether only one of them is. So... I changed the second part to see if both match it and then I NOT'ed that.
It should be: if ((n % 3 === 0 || n % 5 === 0) &&( n % 3 !== 0 || n % 5 !== 0))
return (n % 3 === 0 && !(n % 5 === 0)) || (n % 5 === 0 && !(n % 3 === 0));
(untested)
Your second check is wrong:
if ((n % 3 === 0 || n % 5 === 0) &&**( n % 3 !== 0 && n % 5 !== 0)**)
Change it to:
(! (n%3 === 0 && n % 5 === 0 ) )
This is a short version of XOR implementation using conditional statement in javascript
if((n % 3 === 0)? (n % 5 !== 0) : (n % 5 === 0)) {
...
}
or you can also compare in this way, checking when the two conditions, when evaluated as boolean, return different values (one is true and other is false or vice-versa)
if( (n % 3 === 0) !== (n % 5 === 0)) {
...
}
so this code can be written really short

Javascript syntax

How do you say if (A == 0) OR (B == 0)?
Just to be snarky:
if (A === 0 || B === 0)
if (A == 0 || B == 0)
or
if ((A == 0) || (B == 0))
Check out Control Structures and Operators on Wikibooks
if ( A == 0 || B == 0 ) {
}
depends if you mean exclusive or inclusive OR :)
Inclusive OR:
if(A == 0 || B == 0)
{
}
Exclusive OR:
if(A == 0 && B != 0 || A != 0 && B == 0)
{
}

Categories

Resources