How to rewrite a negated line? - javascript

Negating takes me hours of trial and error until nothing breaks, any method of negating other than intuitively? For example:
//x and y are whole numbers
!((x<9) && (y<=(8-x)))
((x>8) || (y>(8-x)))

The simplest thing is to ignore questions about the domain of values, and treat this as an entirely logical problem. Then we can break it down into cases such as:
!(A || B) ~= !A && !B
!(A && B) ~= !A || !B
!(!A) ~= A
!(x > y) ~= x <= y
!(x >= y) ~= x < y
The first two can easily be extended:
!(A || B || C || D || ...) ~= !A && !B && !C && !D && ...
!(A && B && C && D && ...) ~= !A || !B || !C || !D || ...
So, for one of your examples, we have:
!((x < 9) && (y <= (8-x)))
!(x < 9) || !(y<=(8 - x)
(x >=9) || (y > (8 - x))
We could leave it as this, but as you had additional domain information, ("x and y are whole numbers"), you might incorporate it to return a slightly less specific, but accurate enough in context answer, such as
(x > 8) || (y > (8 - x))
You would have to decide on a case-by-case basis whether this is worth the additional steps. What it might gain is a somewhat reduced codebase, it can also lose in a less transparent link to the original format.

Related

Generic rules to build numeric multipliers from truth tables

I have some truth tables, mostly AND, based on 0, 1, -1 which I am using for Math operations:
Example 1:
var a,b,c;
if(a == 1 && b == 1) c = 0;
if(a == 1 && b == 0) c = 0;
if(a == -1 && b == 1) c = 0;
if(a == -1 && b == 0) c = 1;
Example 2:
var a,b,c;
if(a === 1 && b === 1) c = 1;
if(a === 1 && b === 0) c = 1;
if(a === -1 && b === 1) c = 1;
if(a === -1 && b === 0) c = -1;
For instance, the first one could be expressed as follows:
c = (a>>1)*(b-1);
I would like to convert also the second truth table using only Math or Bitwise Operators, how can it be done?
Is there any generic rule to easily create such kind of one-line expression?
You can use a generic superoptimizer such as this one I wrote (unfortunately not very user friendly): https://github.com/falk-hueffner/sematrope
This will give you (a + b) >>> 31 for your first example and ((a + b) | b) & a for the second.
For a more systematic approach, you can convert -1/1 to 0/1 by (x >> 1) + 1, do regular logic operations with |&^, and then (if needed) convert 0/1 to -1/1 by x ^ (x - 1).
If a is always 1 or -1 and b is always 1 or 0, and you're OK to use a boolean operator (||), then
c = b || a
should do it...
const c = (a, b) => b || a
console.log(c( 1, 1)) // 1
console.log(c( 1, 0)) // 1
console.log(c(-1, 1)) // 1
console.log(c(-1, 0)) //-1

What is the difference between && and || in JavaScript term?

My classmate used "||" instead of "&&" for an if statement, but the result is the same. I tried to understand the differences by reading the article but I can't seem to understand them. I would appreciate if anyone can explain in an easy way...Thank you!
&& is and operator and || is or operator
&& work as
1 && 1= 1
1 && 0 = 0
0 && 1 = 0
0 && 0 = 0
|| work as
1 || 1= 1
1 || 0 = 1
0 || 1 = 1
0 || 0 = 0
where 1 , 0 are true and false
we can understand it by the following example
suppose we have a code
if(1==1 && 2==2){}
so 1==1 is true means 1 and 2==2 is true means 1, so && operator work like this
1 && 1 =1 hence the result will be true and execute if statement
You could replace logical OR || with logical AND && and vice versa, by using De Morgan's laws:
!(a && b) = !a || !b
!(a || b) = !a && !b
If you have
if (a || b)
you could use this without OR
if (!(!a && !b))

Multiple Sets of Sets of ORs

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...

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

Reverse the logic of two "or" statements in JavaScript if query

I have an if test in JavaScript which achieves what I want but not as elegantly as possible. It goes like this:
if (x > y || p < q) {
// don't do anything
} else {
doSomeFunction();
}
If there any way to flip the logic of this so there's only a single if statement without having to have a dummy if-condition as well as the else condition?
You can use the ! operator to invert the condition:
if (!(x > y || p < q)) {
doSomeFunction();
}
Or simply rewrite the condition like this:
if (x <= y && p >= q) {
doSomeFunction();
}
Note: See De Morgan's laws for an explanation about why these two conditions are equivalent.
You can simply invert the comparisons and the logical OR.
if (x <= y && p >= q) {
doSomeFunction();
}
Along with the other answer, the last option (less readable) is :
(x > y || p < q) || doSomeFunction();
If the left bracket is true, it will NOT execute the function.

Categories

Resources