weird if - else if statements but no error...why? - c++

Help me plz..
I just had my midterm exam and one of the questions was to 'make your own function with three parameters that returns the smallest value.'
I coded for this in C++ as below.
int smallest(int a, int b, int c) {
if (a == b && b == c) {
return a;
}
else if ((a==b&&b!=c)||(b==c&&a!=b)||(a==c&&a!=b)){
if (a < b) { //a=c <b or a< b=c
return a;
}
else if (a < c) { //a=b <c or a< b=c
return a;
}
else if (b < a) { //b=c <a or b< a=c
return b;
}
else if (c < a) { //b=c <a or c< a=b
return c;
}
else {
cout << "Congratz you got -1 point";
return 99999999;
}
}
else {
if (a < b&&a < c) {
return a;
}
else if (b < a&&b < c) {
return b;
}
else {
return c;
}
}
When I run this in VS 2017, it works but..
if this function is called as
int main(){
cout << smallest(2,1,1);
return 0;
}
I thought this would make an error because there are two else if statements that include this case (else if(b < a) and else if(c < a)...)
It is not allowed for computers to choose which statement to run.. BUT WHY THIS WORKS..??? :( Pretty basic codes but I have no idea..

The two else if statements you mention are mutally exclusive in the sense that if the first condition evaluates to true, the second one is ignored. Ie:
if (a < b) {
return a;
}
else if (a < c) { // if this is true then...
return a;
}
else if (b < a) { // this condition wont even be evaluated
return b;
}
Also you seem to have a misunderstanding concerning return. Consider this code:
int foo() {
return 3;
return 5;
}
there is nothing wrong about this code, it just happens that the second return will never be executed.
Last but not least you should consider to simplify your code. Two if should be more than sufficient to produce the correct result. Something along the line of
if (a is smaller than b and smaller than c) return a;
else return the smaller of b and c;

The evaluation of the if statements happens from top to bottom. Therefore they don't need to be mutually exclusive, and the order of the conditionals does matter (cf. switch).
Note you can return the smallest value with the simple
return std::min({a, b, c});

Related

What is explanation for this FOR-IF loop?

I am writing a code for GCD in C++ but I am encountering a mysterious error that I can't seem to think of its probable reason.
In the below program if both the numbers are equal to i ... it will break and return the value of i.
But it doesn't seems to work because it outputs the result as 1.
int gcd2(int a, int b) {
int i,hcf=0;
if (b > a) {
a = a + b;
b = a - b;
a = a - b;
}
for (i = 1; i <= b; ++i) {
if (a % i == 0 && b % i == 0) {
break;
}
}
return i;
}
But when I add a variable HCF in the same code :
int gcd2(int a, int b) {
int i,hcf=0;
if (b > a) {
a = a + b;
b = a - b;
a = a - b;
}
for (i = 1; i <= b; ++i) {
if (a % i == 0 && b % i == 0) {
hcf = i;
}
}
return hcf;
}
It works. Why is that? Can anyone clarify?
The variable hfc is not the cause for the difference you notice. If we keep the difference but introduce a hfc in both versions we have:
int hfc = 0;
for (i = 1; i <= b; ++i) {
if (some_condition(i)) {
hfc = i;
break; // breaks out of the loop
}
}
return hfc;
vs
int hfc = 0;
for (i = 1; i <= b; ++i) {
if (some_condition(i)) {
hfc = i; // no break !!!
}
}
return hfc;
The first returns the first value of i for which some_condition(i) is true. The second version returns the last value of i for which some_condition(i) is true. This and the fact that any number is divisible by 1 explains the different results you get.
The simple difference between your two samples is whether the loop goes through the whole interval and whether the first or last match is returned.
Using break makes it to stop when the first number fulfilling the condition is found. As commenters note, 1 is the divider of all numbers, so you should rather have started with i = 2. However, this variant still won’t find the greatest common divisor in all cases.
On the other hand, the variable assignment can be called multiple times, so your second sample returns the last, i.e. greatest number found which is most likely your desired result.

How to obtain 100% branch coverage with gcovr with `if / else if / else`

I'm using gcovr for the first time and have hit a confusing issue with this code:
for (int i = 0; i < 4; i++)
{
bool a = i & 1;
bool b = i & 2;
if (a && b)
printf("a and b\n");
else if (a && !b)
printf("a not b\n");
else
printf("the other two\n");
}
(The code works as you'd expect, so I'm not going to paste the output.)
However, gcovr decides I don't have full branch coverage:
✓✓ 5 for (int i = 0; i < 4; i++)
{
4 bool a = i & 1;
4 bool b = i & 2;
✓✓✓✓ 4 if (a && b)
1 printf("a and b\n");
✓✓✓✗ 3 else if (a && !b)
1 printf("a not b\n");
else
2 printf("the other two\n");
}
Clearly the one of the four permutations is not handled by the else if, but only because it's been handled by the first if.
I'm grumpy because the net result is less than 100% branch coverage. Is this just "the way" or have I fatally misunderstood something?
You may want to refactor:
if (a)
{
if (b)
{
std::cout << "a and b\n";
}
else
{
std::cout << "a and not b\n";
}
}
else
{
std::cout << "not a\n";
}
In your posted code, the a is evaluated in two if statements.
The above example removes the else if condition.
I found a simple alternative to wholesale refactoring:
for (int i = 0; i < 4; i++)
{
bool a = i & 1;
bool b = i & 2;
if (a && b)
printf("a and b\n");
else if (a /*&& !b*/) // <--- comment out second condition (but leave it in place)
printf("a not b\n");
else
printf("the other two\n");
}
I like this approach because it still encapsulates the logic I want, without redundant (and hence problematic) checks.

How to recursively enumerate all possible arrays where each element has an upper bound?

For example, I want to enumerate all arrays in the range [0,0,0,0] ~ [3,4,5,6].
I can access whole possible cases with loops but my brain fried when I try to implement it recursively.
I know it is a kind of useless questions myself but curious.
If you only want to visit each state once, it's just better and easier to use the loop. One way to do the recursive version would be this.
bool checkArray(int a, int b, int c, int d) {
if (d > 6) {
d = 0;
++c;
}
if (c > 5) {
c = 0;
++b;
}
if (b > 4) {
b = 0;
++a;
}
if (a > 3)
return false;
if (array[a][b][c][d] == something)
return true;
return checkArray(a,b,c,d+1);
}

Sum of two squares decomposition counting

I want to count how many pairs of natural number there are such that a2 + b2 = c2. As an input to my function I have c.
My idea was to first check whether the condition is fulfilled, than if not, I wanted to have a loop iterating desired expression up to c. If result is equal to the square of c than I wanted to have count++. Question is why this is not working?
Some corrections added.
int sum(int c) {
int b=1;
int a=1;
int count=0;
int result;
if (a*a + b*b != c*c)
{
for (int i=1; i<=c; i++)
{
b=i;
result = a*a + b*b;
if (result == c*c)
count++;
}
a++;
}
else
count++;
return count;
}
The problem is I still do not understand why this does not want to work.
My second idea was to approach it with while loop:
int sum(int c) {
int b=1;
int a=1;
int count=0;
int result;
if (a*a + b*b != c*c)
{
while(b<=c)
{
result = a*a + b*b;
if (result == c*c)
{count++;
b++;
}
else
b++;
}
a++;
}
else
count++;
return count;
}
Not working as well.
Anybody any ideas as to how to make it work? Any of those two versions? Maybe hints?
The problem is that you're using an if expecting it to work like a loop. At the bottom of the if you're incrementing a, however because it is an if and not a while or for, it doesn't jump back up to the top.
Both a and b need to change, so you need a loop to control each one.
for (a=1; a<=c; a++) {
for (b=a; b<=c; b++) {
if (a*a + b*b == c*c) {
count++;
}
}
}
Note that b starts at the current value of a instead of 1. That way, you aren't trying the same pair of numbers (just switched) twice.

GCD of Multiple Number

I know how to write a code finding a GCD of 2 number . However, I am trying to solve a problem of finding a GCD of n number and I think the algorithm is a little bit different than using an Eucledian algorithm. My code can be compiled , but it always gave me the wrong result. For example when i put n = 2 , GCD of 16 and 12 it gave the answer 8. Here is my code :
#include<iostream>
using namespace std;
int main()
{
int a,b[100],c,d,e=0;
cin>>a;
for(c=0 ; c<a ; c++)
{
cin>>b[c];
}
for(c=0 ; c<a-1 ; c++)
{
if(c < 1)
{
d = b[c];
}
if(b[c] < d)
{
d = b[c];
}
}
while(d>0)
{
for(c=0 ; c<a ; c++)
{
if(b[c] % d < 1)
{
e++;
}
}
if(e == c)
{
cout<<d;
break;
}
d--;
}
}
Can you guys please find the mistake in my code?
Your code does not compute the greatest common divisor of the input array - it counts how many of the entries are evenly divisible by the smallest element d of the array, then how many are divisible by one smaller, and so on until d is 0. This has nothing to do with the GCD at all.
One easy way - though not necessarily the fastest - would be based on the fact that the GCD of three numbers must be the same as the GCD of any one of those numbers and the GCD of the other two.
gcd(a, b, c) = gcd(gcd(a, b), c) = gcd(a, gcd(b, c)) = gcd(gcd(a, c), b)
Extension to n inputs is elementary:
int result = a[0];
for (int i = 1; i < a.Length; ++i)
result = gcd(result, a[i]);
Code for the GCD of two numbers can be found all over the 'net, for example at Rosetta Code. One of my favourites is this plain iterative version:
int gcd (int a, int b)
{
while (b)
{
int t = b;
b = a % b;
a = t;
}
return a;
}
C# allows a more succinct formulation but in other languages this probably won't work (in C++ it would invoke undefined behaviour, for example):
static int gcd (int a, int b)
{
while (b != 0)
b = a % (a = b);
return a;
}
In case some find it helpful, here is an implementation of the Euclidean algorithm in JavaScript.
function EuclideanGCD(a, b) {
// Make sure a > b, interchange values
if (a < b) {
c = a;
a = b;
b = c
}
// If A = 0 then GCD(A,B) = B and we can stop.
if (a == 0) {
return b;
// If B = 0 then GCD(A,B) = A and we can stop.
} else if (b == 0) {
return a;
} else {
let gdc = 0;
let quotient = Math.floor(a / b); // Get the divisor
let remainder = a % b; // Get the remainder
// Make a recursive call, till we hit 0
gdc = EuclideanGCD(b, remainder);
return gdc;
}
}
var gcd = EuclideanGCD(234, 357);
console.log(gcd); // Outputs: 3