How to write else if as logical statement? - c++

I want to write an if-else statement as a logical statement. I know that:
if (statement1){
b=c
}
else{
b=d
}
can be written as:
b=(statement1 && c)||(!statement1 && d)
But how do I write the following if-else statements as logical?:
if (statement1){
b=c
}
else if (statement2){
b=d
}
else{
b=e
}
I have thought of something like:
b=(statement1 && c)||(statement2 && d)||((!statement1&&!statement2) && e)
I'm sorry if there is already a post about this. I have tried, but couldn't find anything similar to my problem.

As with all logical statement building, it'll be easiest to create a truth table here. You'll end up with:
+--+--+--------+
|s2|s1| result |
+--+--+--------+
| 0| 0| e |
+--+--+--------+
| 0| 1| c |
+--+--+--------+
| 1| 0| d |
+--+--+--------+
| 1| 1| c |
+--+--+--------+
So un-simplified, that'll be
(!s1 & !s2 & e) || (!s2 & s1 & c) || (s2 & !s1 & d) || (s1 & s2 & c)
This can be simplified by combining the two c results and removing the s2:
(!s1 & !s2 & e) || (s2 & !s1 & d) || (s1 & c)
(note that this will be faster in C++ and match the if statements closer with s1 & c as the first term. This will especially make a difference if evaluating any of these values will cause outside effects)
Note that what you built,
(statement1 && c)||(statement2 && d)||((!statement1&&!statement2) && e)
will function incorrectly if statement1 is true, c is false, and both statement2 and d are true (you'll get a result of true when you should have false).

Related

IF statements program

I'm having an issue. I have to write a program for my calculator but I'm not sure how to do it. It uses a form of QBASIC language.
My statement is:
IF (y>0 and x>0) then it should calculate n:=ATAN(y/x);
IF (y<0 and x<0) then it should calculate n:=ATAN(y/x)+180;
IF (y>0 and x<0) then it should calculate n:=ATAN(y/x)+180;
IF (y<0 and x>0) then it should calculate n:=ATAN(y/x)+360;
I think I could only use (IF, ELSE, THEN)
your code is
cls
input x
input y
if y>0 and x>0 then
n=ATAN(y/x)
else if y<0 and x<0 then
n= ATAN(y/x)+ 180
else if y>0 and x<0 then
n=ATAN(y/x)+180
else if y<0 and x>0 then
n= ATAN(y/x)+360
endif
end
If IF, THEN, and ELSE are all you have then the following applies:
The rule for a statement containing several IFs and ELSEs is that the first ELSE is associated with the closest preceding IF, and each subsequent ELSE with the closest unassigned preceding IF.
first ELSE subsequent ELSE first ELSE
| | |
v v v
IF y<0 THEN IF x<0 THEN n:=ATAN(y/x)+180 ELSE n:=ATAN(y/x)+360 ELSE IF x<0 THEN n:=ATAN(y/x)+180 ELSE n:=ATAN(y/x)
^ ^ | | ^ |
| \--- closest preceding IF ---/ | \--- closest preceding IF ---/
\---unassigned closest preceding IF ---------------------------/
If possible, use the somewhat less complex:
n:=ATAN(y/x): IF y<0 THEN IF x<0 THEN n:=n+180 ELSE n:=n+360 ELSE IF x<0 THEN n:=n+180

strfmt range in x++

what's wrong with this range?
rangeTransDate = strFmt('(("%1.%2" <= "%3" && "%3" == "%5") || ("%1.%4" > "%3"))',tableStr(CustomTable),fieldStr(CustomTable,TransDate), date2str(dateTo,321,2,0,2,0,4),fieldStr(CustomTable,SettlementDate),SysQuery::valueEmptyString());
i'm getting this error:
Query extended range error: Right parenthesis expected next to position 72.
This page of AX 2012 documentation is still relevant (I cannot find a AX365 version). Highlighting the important bit gives:
The rules for creating query range value expressions are:
Enclose the whole expression in parentheses.
Enclose all subexpressions in parentheses.
Use the relational and logical operators available in X++.
Only use field names from the range's data source.
Use the dataSource.field notation for fields from other data sources in the query.
This means that X++ expects curly brackets around every comparison operator (a.k.a. "subexpression" in the documentation). You are missing some...
Also, use the date2strxpp() function to properly handle all date to string conversions. This function can handle empty date values (dateNull()) by translating these to 1900-01-01. I doubt that putting an empty string (SysQuery::valueEmptyString()) in there will work.
So try this, the commented subexpression levels show the bracket groupings:
// subexpressions lvl 2: 4 4
// subexpressions lvl 1: |1 1 2 2 3 3|
// || | | | | ||
rangeTransDate = strFmt('(("%1.%2" <= "%3") && ("%3" == "%5") || ("%1.%4" > "%3"))',
tableStr(CustomTable),
fieldStr(CustomTable,TransDate),
date2strxpp(dateTo),
fieldStr(CustomTable,SettlementDate),
date2strxpp(dateNull()));
If you still get a similar error at runtime, add even more brackets to group every subexpression in pairs:
// subexpressions lvl 3: 5 5
// subexpressions lvl 2: |4 4 3 3|
// subexpressions lvl 1: ||1 1 2 2| 3 3|
// ||| | | || | ||
rangeTransDate = strFmt('((("%1.%2" <= "%3") && ("%3" == "%5")) || ("%1.%4" > "%3"))',
tableStr(CustomTable),
fieldStr(CustomTable,TransDate),
date2strxpp(dateTo),
fieldStr(CustomTable,SettlementDate),
date2strxpp(dateNull()));

Replacing regex pattern with another string works, but replacing with NONE replaces all values

I am trying to replace all strings in a column that start with 'DEL_' with a NULL value.
I have tried this:
customer_details = customer_details.withColumn("phone_number", F.regexp_replace("phone_number", "DEL_.*", ""))
Which works as expected and the new column now looks like this:
+--------------+
| phone_number|
+--------------+
|00971585059437|
|00971559274811|
|00971559274811|
| |
|00918472847271|
| |
+--------------+
However, if I change the code to:
customer_details = customer_details.withColumn("phone_number", F.regexp_replace("phone_number", "DEL_.*", None))
This now replaces all values in the column:
+------------+
|phone_number|
+------------+
| null|
| null|
| null|
| null|
| null|
| null|
+------------+
Try this-
scala
df.withColumn("phone_number", when(col("phone_number").rlike("^DEL_.*"), null)
.otherwise(col("phone_number"))
)
python
df.withColumn("phone_number", when(col("phone_number").rlike("^DEL_.*"), None)
.otherwise(col("phone_number"))
)
Update
Query-
Can you explain why my original solution doesn't work? customer_details.withColumn("phone_number", F.regexp_replace("phone_number", "DEL_.*", None))
Ans- All the ternary expressions(functions taking 3 arguments) are all null-safe. That means if spark finds any of the arguments null, it will indeed return null without any actual processing (eg. pattern matching for regexp_replace).
you may wanted to look at this piece of spark repo
override def eval(input: InternalRow): Any = {
val exprs = children
val value1 = exprs(0).eval(input)
if (value1 != null) {
val value2 = exprs(1).eval(input)
if (value2 != null) {
val value3 = exprs(2).eval(input)
if (value3 != null) {
return nullSafeEval(value1, value2, value3)
}
}
}
null
}

From natural language to C++ expression

Assignment:
Translate the following natural language expressions to C++ expressions. Assume that all the variables are non-negative numbers or boolean (of value true or false).
Natural Language:
Either a and b are both false or c is true, but not both.
My solution:
(a==0 && b==0)xor(c==1)
Professors solution:
(!a && !b) != c
Questions:
I think I slightly understand the first bracket, by saying "not-a" and "not-b" I think that a and b must then be wrong, provided a b are assumed to be non-zero in the beginning. Right?
But what about the part that says "unequal to c"?
I don't understand the Professors solution, can anyone break it down for me?
Thank you for the help!
I'll assume that a, b and c are bool.
Let's draw some truth tables:
| a | !a | a==1 | a==0 |
| 0 | 1 | 0 | 1 |
| 1 | 0 | 1 | 0 |
As you can see, a and a==1 are equivalent, and !a and a==0 are also equivalent, so we can rewrite (a==0 && b==0)xor(c==1) as (!a && !b) xor c.
Now some more truth tables:
| a | b | a xor b | a != b |
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 1 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 0 |
So a!=b is equivalent to a xor b, so we can rewrite (!a && !b) xor c to (!a && !b)!=c. As you see, your solutions are fully equivalent, just written with different 'signs'.
UPD: Forgot to mention. There are reasons why professor's solution looks exactly in that way.
The professor's solution is more idiomatic. While your solution is technically correct, it's not an idiomatic C++ code.
First little issue is usage of types. Your solution relies on conversion between int and bool when you compare boolean value to a number or use xor, which is a 'bit-wise exclusive or' operator acting on ints too. In a modern C++ it is much more appreciated to use values of correct types and not to rely on such conversions as they're sometimes not so clear and hard to reason about. For bool such values are true and false instead of 1 and 0 respectively. Also != is more appropriate than xor because while technically bools are stored as numbers, but sematically you haven't any numbers, just logical values.
Second issue is about idiomacy too. It lies here: a == 0. It is not considered a good practice to compare boolean expressions to boolean constants. As you already know, a == true is fully equivalent to just a, and a == false is just !a or not a (I prefer the latter). To understand the reason why that comparing isn't good just compare two code snippets and decide, which is clearer:
if (str.empty() == false) { ... }
vs
if (not str.empty()) { ... }
Think booleans, not bits
In summary, your professor's solution is better (but still wrong, strictly speaking, see further down) because it uses boolean operators instead of bitwise operators and treating booleans as integers. The expression c==1 to represent "c is true" is incorrect because if c may be a number (according to the stated assignment) then any non-zero value of c is to be regarded as representing true.
See this question on why it's better not to compare booleans with 0 or 1, even when it's safe to do so.
One very good reason not to use xor is that this is the bit-wise exclusive or operation. It happens to work in your example because both the left hand side and right hand side are boolean expressions that convert to 1 or 0 (see again 1).
The boolean exclusive-or is in fact !=.
Breaking down the expression
To understand your professor's solution better, it's easiest to replace the boolean operators with their "alternative token" equivalents, which turns it into better redable (imho) and completely equivalent C++ code:
Using 'not' for '!' and 'and' for '&&' you get
(not a and not b) != c
Unfortunately, there is no logical exclusive_or operator other than not_eq, which isn't helpful in this case.
If we break down the natural language expression:
Either a and b are both false or c is true, but not both.
first into a sentence about boolean propositions A and B:
Either A or B, but not both.
this translates into A != B (only for booleans, not for any type A and B).
Then proposition A was
a and b are both false
which can be stated as
a is false and b is false
which translates into (not a and not b), and finally
c is true
Which simply translates into c.
Combining them you get again (not a and not b) != c.
For further explanation how this expression then works, I defer to the truth tables that others have given in their answers.
You're both wrong
And if I may nitpick: The original assignment stated that a, b and c can be non-negative numbers, but did not unambiguously state that if they were numbers, they should be limited to the values 0 and 1. If any number that is not 0 represents true, as is customary, then the following code would yield a surprising answer:
auto c = 2; // "true" in some way
auto a = 0; // "false"
auto b = 0; // "false"
std::cout << ((!a && !b) != c);
// this will output: 1 (!)
// fix by making sure that != compares booleans:
std::cout << ((!a && !b) != (bool)c);
I will tryto explain with some more words: Numbers can be implicitly converted to boolean values:
The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false. All other values become true.
Source on cppreference
This leads to the following conclusions:
a == 0 is the same as !a, because a is converted to a boolean and then inverted, which equals !(a != 0). The same goes for b.
c==1 will become only true when c equals 1. Using the conversion (bool)c would yield true when c != 0 not just if c == 1. So it can work, because one usually uses the value 1 to represent true, but it's not garantued.
a != b is the same as a xor b when a and b ar boolean expressions. It's true, when one value or the other is true, but not both. In this case the left hand side (a==0 && b==0) is boolean, so the right hand side c is converted to boolean too, thus, both sides are interpreted as boolean expressions, thus != is the same as xor in this case.
You can check all of this yourself with the truthtables that the other answers provided.
As we can see from the truth tables:
!(not) and ==0 give the same results.
!= and xor give the same results.
c==1 is the same as just c
So one under the other, shows why these 2 expressions give the same result:
(a==0 && b==0) xor (c==1)
(!a && !b) != c
Truth tables :
Not
| | ! |
| 0 | 1 |
| 1 | 0 |
==0
| |==0|
| 0 | 1 |
| 1 | 0 |
==1
| |==1|
| 0 | 0 |
| 1 | 1 |
And
| a | b | && |
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
Not equal
| a | b | != |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
XOR
| a | b |xor|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |

Basic Collision problems

I have a sprite class which I am working on making a function for collision. I want the function to return true if two sprites collide. When I call the function I pass the moving objects desired X and Y position along with it's height and width. The invoking sprite is the object I that I would like to check. For example if I wanted to check if player 1's move will intersect player 2's sprite I would say Player2.Collide(p1X, p1Y, p1H, p1W).
bool Sprite::Collides(int x, int y, unsigned short w, unsigned short h) const
{
if ((x == this->GetWidth() + this->GetLeft()) &&
(y >= this->GetTop() && y <= this->GetTop() + this->GetHeight()) ||
((x + w) == this->GetLeft()) &&
(y >= this->GetTop() && y <= this->GetTop() + this->GetHeight()))
return true;
else if ( (y == this->GetHeight() + this->GetTop()) &&
((x >= this->GetLeft() && x <= this->GetLeft() + this->GetWidth()) ||
((y + h) == this->GetTop() && (x >= this->GetLeft() && x <= this->GetLeft() + this->GetWidth()))))
return true;
return false;
}
The sprites are always rectangles. It seems I am forgetting to check some conditions for my collision. If the rectanges collide perfectly then everything works, however if I shift one up then try to butt against the other, it will glide right through. It seems each direction I approach has a similar behavior where it will work only for certain sections. Can you guys help me find what I'm forgetting to check?
I think you need to check the logic of your actual conditions again, shouldn't
(x == this->GetWidth() + this->GetLeft())
just that part of your if statement create a collision? right after that you have an &&. So in this case it needs to be touching on the top AND right, not just the right OR the top???
I also think the above line should really be:
(x <= this->GetWidth() + this->GetLeft())
Also, depending on your actual movement conditions (i.e. velocity, etc...) the above condition could really be
(x <= this->GetWidth() + this->GetLeft() - 1)
Lets explain the minus 1:
If you have two objects, one moving directly upward, and another moving directly downward, i.e. vertically and parallel to one another, then GetWidth + GetLeft creates a "went by" each other condition not a collision condition.
Example Sprites each 4 x 4 moving VERTICALLY with respect to each other:
Sprite A # (0, 2) Sprite B # (4, 2)
0 1 2 3 0 1 2 3
------------------------- -------------------------
| | | | | | | | | |
------------------------- -------------------------
| | | | | | | | | |
------------------------- -------------------------
| | | | | | | | | |
------------------------- -------------------------
| | | | | | | | | |
------------------------- -------------------------
Sprite A # (0, 1) Sprite B # (4, 3)
0 1 2 3
-------------------------
| | | | |
-------------------------
| | | | | 0 1 2 3
------------------------- -------------------------
| | | | | | | | | |
------------------------- -------------------------
| | | | | | | | | |
------------------------- -------------------------
| | | | |
-------------------------
| | | | |
-------------------------
Sprite A # (0, 0) Sprite B # (4, 4)
0 1 2 3
-------------------------
| | | | |
-------------------------
| | | | |
-------------------------
| | | | |
-------------------------
| | | | | 0 1 2 3
------------------------- -------------------------
| | | | |
-------------------------
| | | | |
-------------------------
| | | | |
-------------------------
| | | | |
-------------------------
When sprite a is at location (0, 0), then GetWidth + GetLeft = (0 + 4) which is RIGHT of the actual end of the sprite. IF another sprite is moving completely vertically downward with x position 4, then you algorithm would flag that as a collision, when in reality they are simply moving VERY CLOSELY by one another. This is where the - 1 comes in.
Also, you really want to make sure to be careful with your screen geometry. What I mean by this is many screens move from top-left being pixel (0, 0) to bottom right being pixel (positive X, positive y). Your second condition:
(y >= this->GetTop() && y <= this->GetTop() + this->GetHeight())
MIGHT need to be:
( (y + h - 1) >= this->GetTop() || y <= (this->GetTop() + this->GetHeight() - 1) )
The first portion needs to change because originally you were testing for the TOP of your input object colliding with the TOP of your object to be tested against. What you really want is the BOTTOM of your input to be tested with the TOP of your object to be tested against.
One thing I have always found extremely useful when trying to perform this type of coding, is to actually draw out very simple sketches with actual pixel based example numerics so that I can visualize it prior to coding it.
I hope all of this helps :-)