Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the second minimum number without using arrays or loops

Tags:

c++

I tried to write a program that receive from the user 5 integers and print the second minimum number.
Here is a sample of what I've tried:

#include <iostream>
using namespace std;
int main () {
int a,b,c,d,e;
cin>>a>>b>>c>>d>>e;
if (a>b && a<c && a<d && a<e)
    cout<<a<<endl;
if (b>a && b<c && b<d && b<e)
    cout<<b<<endl;
if (c>a && c<b && c<d && c<e)
    cout<<c<<endl;
if (d>a && d<b && d<c && d<e)
    cout <<d<<endl;
if (e>a && e<b && e<c && e<d)
cout <<e<<endl;
return 0;

}

When I enter 1 2 3 4 5 it prints the second minimum, but when I enter
5 4 3 2 1 Nothing will print on the screen. What am I doing wrong with this? Is there any other way to write my program?

like image 490
Adam Hussein Avatar asked Dec 14 '22 19:12

Adam Hussein


2 Answers

The problem you have with your logic is that you do not enforce yourself to print only 1 item, and at least one item. By using the 'else' part of the if/else syntax, you will ensure that only one branch can ever be hit. You can then follow this up with just an else at the end, as you know all other conditions are false.

Once you've done this, you'll see that you print the last value, (1) rather than the expected (4). This is because your logic regarding how to find the 2nd lowest is wrong. b>a is false for the case 5,4...

Note: Every employed engineer, ever, would make this a loop in a std::vector / std::array, and I would suggest you point your teacher to this post because encouraging loops is a good thing rather than bad.

Something like

vector<int> data;
for (int i=0; i<5; ++i) {
    int t;
    cin >> t;
    data.push_back(t);
}
std::nth_element(data.begin(), data.begin()+1, data.end(), std::greater<int>());
cout << data[1];
like image 135
UKMonkey Avatar answered May 20 '23 16:05

UKMonkey


There are 120 possible permutations on 5 elements. Your code should output the correct number for all of them. So a fool-proof code would use 120 repetitions of a check, like the following:

if (a > b && b > c && c > d && d > e) // the order is a>b>c>d>e
    cout << d;
else if (a > b && b > c && c > e && e > d) // the order is a>b>c>e>d
    cout << e;
...
else if (e > d && d > c && c > a && e > b) // the order is e>d>c>a>b
    cout << a;
else // the order is e>d>c>b>a
    cout << b;

This is very long, inefficient and tricky code. If you do a typo in just one variable, it will output a wrong answer in some rare cases. Also, it doesn't handle the possibility of some inputs being equal.


If the number of inputs to a sorting algorithm is a known small constant, you can use an approach called sorting networks. This is a well-defined computer science problem, which has well-known optimal solutions for small numbers of inputs, and 5 certainly is small. An optimal sorting network for 5 inputs contains 9 comparators, and is described e.g. here.

Since you don't need to sort the numbers, but only to know the second smallest input, you can reduce the size of the network further, to 7 comparators.

The full sorting network (without the reduction from 9 to 7) translated to C++:

if (b < c)
    swap(b, c);
if (d < e)
    swap(d, e);
if (b < d)
    swap(b, d);
if (a < c)
    swap(a, c);
if (c < e)
    swap(c, e);
if (a < d)
    swap(a, d);
if (a < b)
    swap(a, b);
if (c < d)
    swap(c, d);
if (b < c)
    swap(b, c);
// now the order is a ≥ b ≥ c ≥ d ≥ e
cout << d;

This code is also obscure - not obvious at all how and why it works - but at least it is small and in a sense optimal. Also, it's clear that it always prints something (so it fixes the original problem) and supports the case of partially equal inputs.

If you ever use such code in a larger project, you should document where you took it from, and test it. Fortunately, there are exactly 120 different possibilities (or 32, if you use the zero-one principle), so there is a way to prove that this code has no bugs.

like image 20
anatolyg Avatar answered May 20 '23 14:05

anatolyg