Convert while-loop to mathematical formula - c++

I have following loop as a inner loop and try to get rid of it by transforming it into a mathematical formula:
while(!(((aux = a * b) <= c) && (c >= aux + d))) --a;
a, b, c, d and aux are all of type size_t, i.e. unsigned int's
NOTE: a is decremented in every iteration within the loop's body!
I'm totally stuck at this problem. I tried to simplify the loop condition, but failed because of the unsignedness constraint.
As result I just want to get the value of a depending on b, c, d.

Replace aux with a*b at every point, and you get:
!(a * b <= c && c - a * b >= d)
<=> !(a * b <= c && c >= d + a * b)
<=> !(a * b <= c && d + a * b <= c)
If d is greater than c, the second condition will be false and therefore the loop will never terminate. So we can consider only d <= c. The second condition is stricter, so we can focus on that solely:
<=> !(d + a * b <= c)
<=> !( a * b <= c - d)
<=> !( a <= (c - d)/b) // if integer division is used
<=> ( a > (c - d)/b)
Given that you only decrement a, it either needs to fulfil the condition (a <= (c - d)/b) right from the beginning or be less than or equal to (c - d)/b. Overall we get:
a = std::min(a, (c - d)/b);

Let's simplify:
while(!(((aux = a * b) <= c) && (c - aux >= d))) --a;
Drop aux in favor of just a*b:
while(!((a*b <= c) && (c - a*b >= d))) --a;
Rewrite the !(x && y) into !x || !y:
while ((a*b > c) || (c - a*b < d)) --a;
Flip the sign on the second expression:
while ((a*b > c) || (a*b > c - d)) --a;
Which is just:
while (a*b > min(c, c-d)) --a;
Which is to say, find the smallest a such that a*b <= min(c, c-d). Unless it's already smaller than that. So:
a = min(a, min(c, c-d) / b);
Er, given that all the variables are unsigned, obviously min(c, c-d) == c - d, so:
a = min(a, (c-d)/b);

Related

How does c++ evaluate assignment operators (if statement)

Consider the following
int main() {
int a = 8;
int b = 10;
while (true) {
if (a /= 2 && b < 12) {
b++;
std::cout << b << std::endl;
}
else break;
}
return 0;
}
Now c++ is not my main language, but how does c++ evaluate this if statement?
In this case, when b>=12, the compiler throws the "division by zero" exception, but why?
Now if i wrap the states in parentheses i do not get the exception.
if( (a /= 2) && (b < 12))
Does this have something to do with how c++ evaluates the statements?
If evaluation is not the problem:
I am aware of that
a = (a/2 && b<12)
would not hold either.
P Λ Q does not hold for P Λ ¬Q but the state of P should not be affected? Why is it P gets blamed instead of ¬Q?
if (a /= 2 && b < 12)
is the same as:
if (a /= (2 && b < 12))
so:
2 is evaluated, which is converted to true in the context of an operand to &&. This does not trigger short-circuit evaluation so we continue...
b < 12, which in the case you're talking about is false
So 2 && b < 12 evaluates to false overall
a /= 2 && b < 12 is therefore equivalent to a /= false here, which is equivalent to a /= 0.

Is there a better approach at rewriting this code snippet?

Consider the following:
if ((a || b) && (c || d))
{
if (a && c) {...}
else if (b && d) {...}
else {...}
}
else {...}
where a, b, c and d are expressions that result in a bool.
As is clear from the code, few of these expressions are being recalculated. Is there a better approach in terms of a) clarity? b) Efficiency?
Surprise: I don't think you really need the outer if statement. Appreciate that using the laws of logic the outer if can be rewritten from:
if ((a || b) && (c || d))
to
if ( ((a && c) || (a && d)) || ((b && c) || (b && d)) )
In other words, if (a && c) or (b && d) be true, then the outer if will always evaluate to true, so it can be dropped. Instead, you could write this:
if (a && c) {...}
else if (b && d) {...}
else if ((a && d) || (b && c)) {...} // your original 'inner' else
else {...} // your original 'outer' else
Trivial answer: You can store the expressions in bool variables before the if statements.
If the expressions do not involve function calls (and thus it is clear that they may not change in between the statements), I would expect the compiler to optimise it like this anyway.

what is wrong in this code in c++

this is the problem https://www.urionlinejudge.com.br/judge/en/problems/view/1042
and the code
#include <iostream>
using namespace std;
int A,B,C
int main ()
{
cin >> A >> B >> C;
if (A > B > C)
cout <<C<<"\n"<<B<<"\n"<<A<<"\n\n";
else if (B > A > C)
cout <<C<<"\n"<<A<<"\n"<<B<<"\n\n";
else if (C > A > B)
cout <<B<<"\n"<<A<<"\n"<<C<<"\n\n";
else if (A > C > B)
cout <<B<<"\n"<<C<<"\n"<<A<<"\n\n";
else if (C > B > A)
cout <<A<<"\n"<<B<<"\n"<<C<<"\n\n";
else {
(B > C > A);
cout <<A<<"\n"<<C<<"\n"<<B<<"\n\n";}
cout <<A<<"\n"<<B<<"\n"<<C<<endl;
return 0;
}
Your main problem is that if(A > B > C) becomes if (A > (B > C)) - in other words, you're comparing A to the true or false result of B > C, which will be true for all values where A of 2 or greater, regardless of the values of B and C.
The fix is to compare A > B separately from B > C, so use if (A > B && B > C) or some similar construct.
You have to trnasform things like:
(A > B > C)
into:
(A>B && B>C)
Conditions in the if statements are wrong. For example condition
if (A > B > C)
is equivalent to
if ( ( A > B ) > C)
In this case condition ( A > B ) is evaluated to either true or false and the condition is equivalent to either to
if ( true > C)
or
if ( false > C)
It is obvious that it is not what you want to get.
So the original condition has to be rewritten like
if (A > B && B > C )
But even in this case the program will be wrong because it does not consider cases when the variables could be equal each other. So the valid condition will look like
if (A >= B && B >= C )
And the program will not compile because at least here there is a typo
int A,B,C
^^^
You forgot to place a semicolon
int A,B,C;
Also there is no sense to declare variables A, B, C as global
int A,B,C;
int main ()
{
//...
It is better to declare them as local variables of function main
int main ()
{
int A, B, C;
//...
And this code snippet is wrong
else {
(B > C > A);
cout <<A<<"\n"<<C<<"\n"<<B<<"\n\n";}
cout <<A<<"\n"<<B<<"\n"<<C<<endl;
I think you mean simply
else cout <<A<<"\n"<<C<<"\n"<<B<<endl;

How to do equal comparison in C or C++?

I am just wondering in C or C++, for the expression:
b == c || b == d
Can I do something like:
b == (c || d)
and get the same behavior?
The first expression
b == c || b == d will give you true if b is equal to either c or d.
The second expression
b == (c || d) will check only if b is either equal to 0 or 1 because the output of c || d is binary.
Consider this code:
#include <iostream>
using namespace std;
int main() {
int b=10,c=9,d=10;
cout << (b ==c || b ==d )<<endl;
cout<< ( b == ( c || d)) <<endl;
d=11;
cout << (b ==c || b ==d )<<endl;
cout<< ( b == ( c || d)) <<endl;
return 0;
}
The output is
1
0
0
0
Now you can clearly see that both expressions are not same.
No, operators in C and C++ don't implicitly distribute over subexpressions like that. Evaluation is defined strictly in terms of the direct association of operators with operands. There are no "shortcuts" as you might have in mathematics or English.
If you write code that incorrectly assume such implicit distribution, you're likely to end up with an expression that's syntactically and semantically valid, but that doesn't do what you expect.
The || operator yields a value of 1 or true if either operand is true (non-zero) or a value of 0 or false if both operands are false (equal to zero). And the operands needn't be boolean; they can be of any scalar type. (In C the result is of type int; in C++ it's of type bool.) The expression
b == c || b == d
is equivalent to
(b == c) || (b == d)
and yields a true result if b is equal to c or if b is equal to d. But this expression:
b == (c || d)
computes the value of (c || d), and the tests whether b is equal to the result of that subexpression.
A similar possible source of confusion is that
x < y < z
is not equivalent to
(x < y) && (y < z)
Rather, it's equivalent to
(x < y) < z
where the false or true (in C++) or 0 or 1 (in C) result of x < y is compared to the value of z.

Finding MAX of numbers without conditional IF statements c++ [duplicate]

This question already has answers here:
Mathematically Find Max Value without Conditional Comparison
(18 answers)
Closed 9 years ago.
So i have too get two numbers from user input, and find the max of the two numbers without using if statements.
The class is a beginner class, and we have too use what we already know. I kinda worked something out, but it only works if the numbers are inputted with the max number first.
#include <iostream>
using namespace std;
int main()
{
int x = 0, y = 0, max = 0;
int smallest, largest;
cout << "Please enter 2 integer numbers, and i will show you which one is larger: ";
cin >> x >> y;
smallest = (x < y == 1) + (x - 1);
smallest = (y < x == 1) + (y - 1);
largest = (x < y == 1) + (y - 1);
largest = (y > x == 1) + (x + 1 - 1);
cout << "Smallest: " << smallest << endl;
cout << "Largest: " << largest << endl;
return 0;
}
Thats what i have so far, but after putting different test data in, i found out it only works for numbers such as 4,5 or 6,7. But numbers with more then 2 spaces between eachother they dont such as, 4,8 or 5, 7. Any help would be appreciated.
I saw this question in Cracking the Coding interview book.
Let’s try to solve this by “re-wording” the problem We will re-word the problem until we get something that has removed all if statements
Rewording 1: If a > b, return a; else, return b
Rewording 2: If (a - b) is negative, return b; else, return a
Rewording 3: If (a - b) is negative, let k = 1; else, let k = 0 Return a - k * (a - b)
Rewording 4: Let c = a - b Let k = the most significant bit of c Return a - k * c
int getMax(int a, int b) {
int c = a - b;
int k = (c >> ((sizeof(int) * CHAR_BIT) - 1)) & 0x1;
int max = a - k * c;
return max;
}
Source: http://www.amazon.com/Cracking-Coding-Interview-Programming-Questions/dp/098478280X
Edit: This code works even when a-b overflows.
Let k equal the sign of a-b such that if a-b >=0, then k is 1, else k=0.Let q be the inverse of k. Above code overflows when a is positive or b is negative, or the other way around. If a and b have different signs, then we want the k to equal sign(a).
/* Flips 1 to 0 and vice-versa */
public static int flip(int bit){
return 1^bit;
}
/* returns 1 if a is positive, and 0 if a is negative */
public static int sign(int a){
return flip((a >> ((sizeof(int) * CHAR_BIT) - 1)) & 0x1);
}
public static int getMax(int a, int b){
int c = a - b;
int sa = sign(a-b); // if a>=0, then 1 else 0
int sb = sign(a-b); // if b>=1, then 1 else 0
int sc = sign(c); // depends on whether or not a-b overflows
/* If a and b have different signs, then k = sign(a) */
int use_sign_of_a = sa ^ sb;
/* If a and b have the same sign, then k = sign(a - b) */
int use_sign_of_c = flip(sa ^ sb);
int k = use_sign_of_a * sa + use_sign_of_c * sc;
int q = flip(k); //opposite of k
return a * k + b * q;
}
Here is a funny solution:
int max_num = (x>y)*x + (y>=x)*y;
Assuming that you have covered bitwise operators already you can do this:
max = a-((a-b)&((a-b)>>(sizeof(int)*8-1)));
This is based off of the solution from Mathematically Find Max Value without Conditional Comparison that #user93353 pointed out in the comments above.
This may be overkill if you really are just trying to avoid if statements, not comparisons in general.
You can try this code to find max and min for two input variables.
((a > b) && (max = a)) || (max=b);
((a < b) && (min = a)) || (min=b);
For three input variables you can use similar method like this:
int main()
{
int a = 10, b = 9 , c = 8;
cin >> a >> b >> c;
int max = a, min = a;
// For Max
((a > b) && (a > c) && (max=a)) ||
((b > c) && (b > a) && (max=b)) ||
(max=c) ;
// For min
((a < b) && (a < c) && (min=a)) ||
((b < c) && (b < a) && (min=b)) ||
(min=c) ;
cout << "max = " << max;
cout << "and min = " << min;
return 1;
}
One run is:
:~$ ./a.out
1
2
3
max = 3 and min = 1
Edit
Thanks to #Tony D: This code will fail for negative numbers.
One may try this for negative numbers for two inputs to find max(not sure for this):
((a > b) && ( a > 0 && (max = a))) || ((b > a) && (max = b)) || (max = a);