More realistic C++: find minimum and maximum among several numbers by xinta

View this thread on steempeak.com
· @xinta ·
$0.05
More realistic C++: find minimum and maximum among several numbers
In a [previous post](https://steemit.com/programming/@xinta/more-realistic-c-how-to-sum-two-or-more-numbers) I've given an idea about how to sum two or more numbers in modern C++.

Now the problem is again the same from [Coding Practice: Write a program in C++ to find out maximum and minimum number from given integer numbers using conditional statement if](https://steemit.com/hive-185836/@rme/coding-practice-write-a-program-in-c-to-find-out-maximum-and-minimum-number-from-given-integer-numbers-using-conditional), but let's generalise it.

# Problem: Write a program in C++ to find the maximum and the minimum among a list of numbers

In the [previous remake](https://steemit.com/programming/@xinta/more-realistic-c-how-to-sum-two-or-more-numbers) we've already seen how to get a list (as array, vector or via function arguments) and do something with it. In particular, we iterated over its elements to sum them.

Now, we can use the same idea. But let's start with a basic tool: a function that, given two numbers, returns the bigger one. But which type of numbers? Let's generalize it: anything that can be compared and has an ordering

```c++
template<class T>
T gmax(T&& a, T&& b) {
    return a >= b ? a : b;
}
```

This is the basic building block.

The original “problem” imposed the use of an `if` statement. As an assignment to learn to program, it doesn't make sense (again, tell me who's your teacher and I'll complain with her/him, because she's not pushing her students to think about the problem and solve it with the tools they should already know).

But anyway, do not forget that the ternary operator `?:` is just an “expression if”, that is, an expression with the value of `a` **if** `a >= b` is true, and `b` otherwise (**else**).


With this function at hand, if we had four numbers, we could display the biggest by nesting `gmax` like this:

```
std::cout << gmax(6530, gmax(590, gmax(28640, 32))) << "\n";
```

But this doesn't scale well, at least when we do it by hand. We could do it automatically noticing the “structure” of the expression. We can consider `gmax` as a binary operator. Let's think about it as a `+` and let's write the expression

```
6530 + 590 + 28640 + 32
```

If our `+` were really a `+`, we know how we could compute the expression: we would sum the first two:

```
7120 + 28640 + 32
```

Then we would go on with the result (7120) + the next number in the list (28640),

```
35760 + 32
```

and I leave you the last step. You can see there's a structure, and we can apply an algorithm. And what if we interpret `+` as “get the greater among the two operand”? Then `6530 + 590` would have 6530 as result; then we were left with:

```
6530 + 28640 + 32
```

We would compute `6530 + 28640`, where `+` is our “get the greater” operator, and the result would be `28640`. And I left the last step to you again…

In the [previous article](https://steemit.com/programming/@xinta/more-realistic-c-how-to-sum-two-or-more-numbers) we used [accumulate](https://en.cppreference.com/w/cpp/algorithm/accumulate), which does something like this: it applies the binary operator `+` almost like we did above (it's called [left folding](https://en.wikipedia.org/wiki/Fold_(higher-order_function)), until it produces a final result. But indeed you can give your own binary operator to the function! We could give it our `gmax`!

Like this:

```c++
  std::vector<int> v{6530, 590, 28640, 32};
  std::cout << std::accumulate(v.cbegin(), v.cend(), v[0], 
      [](auto a, auto b) {return gmax(a,b); }) << "\n";
```

Here I've used a **lambda** because `gmax()` is a template and we need to “push” a little bit the type inference. Had we a simple function like this:

```
int hmax(int a, int b)
{
    return a >= b ? a : b;
}
```

we could have written:

```
std::cout << std::accumulate(v.cbegin(), v.cend(), v[0], hmax) << "\n";
```

I've already explained what `accumulate` does; we also did a little bit of its work by hand with those four numbers. Also in the previous article about the sum, you should have asked yourself: why `(T)0`? Well, because 0 is the “neuter” value of the addition, that is `a + 0 == a`. And accumulate needs a starting value (guess why as an exercise).

Now, if our operator is `gmax` which returns the greater of two numbers, what should be the “init” for `accumulate`? It can't be 0. If it were 0, the gmax of `-10, -20` would be 0, which is wrong.

That's why I used the first value: `max between A and A` is always A, hence we are safe!

If we replace `gmax` with a similar function `gmin`, we have the minimum we wanted.

Ok, now let's suppose we can't use `accumulate`. Let's do it “by hand”, iterating. We want a function, a piece of code we can reuse: avoid writing your code with pieces just put there. Try to think about functions that you use to “compose” other functions and then you put together to give your solution. 

If generalized, we are indeed searching for an implementation of accumulate… But let's think of another idea: we want both minimum and maximum: we can iterate once, and compute both values as we go!

```
template<class T>
void minmax(const std::vector<T>& v, T& rmin, T& rmax)
{
        rmin = v[0];
        rmax = v[0];
        for (auto val : v) {
                if (rmax < val) rmax = val;
                if (rmin > val) rmin = val;
        }
}
```

Unless we use tuples, we can't return two values from a function, hence I've used arguments (by reference, so that we can modify the caller's variable).

And you use this function like this:

```
    std::vector<int> v{6530, 590, 28640, 32};
//...
    int rmin, rmax;
    minmax(v, rmin, rmax);
    std::cout << "min " << rmin << "\nmax " << rmax << "\n"; 
```


You should be able to put altogether in a single source file. Here it is:


```
#include <iostream>
#include <vector>
#include <numeric>

template<class T>
T gmax(T&& a, T&& b)
{
    return a >= b ? a : b;
}

int hmax(int a, int b)
{
    return gmax(a, b);
}


template<class T>
void minmax(const std::vector<T>& v, T& rmin, T& rmax)
{
   rmin = v[0];
   rmax = v[0];
   for (auto val : v) {
           if (rmax < val) rmax = val;
           if (rmin > val) rmin = val;
   }
}

int main()
{
   std::cout << gmax(6530, gmax(590, gmax(28640, 32))) << "\n";
   std::vector<int> v{6530, 590, 28640, 32};
   std::cout << std::accumulate(v.cbegin(), v.cend(), v[0],
                           [](auto a, auto b) {return gmax(a,b); }) << "\n";
   std::cout << std::accumulate(v.cbegin(), v.cend(), v[0], hmax) << " **\n";
   int rmin, rmax;
   minmax(v, rmin, rmax);
   std::cout << "min " << rmin << "\nmax " << rmax << "\n";
   return 0;
}
```

There can be something unexplained here (like the `&&`, which is not the logical *AND*…), but you got the idea… I hope! Or at least, you see there's a lot to learn and try harder to grasp the basic first things that will make you master modern C++.

**Note:** since we've used `template` (except in hmax…), you can use those functions also for `double`, or `long`, or for any type which can be compared and has an ordering.


<center>

![image.png](https://cdn.steemitimages.com/DQmcTN1fpZfAv95MJ6Tn2EHZnJjcukqm9GJDTFEUzeyjfqm/image.png)

</center>
👍  , , , , ,
properties (23)
post_id91,783,983
authorxinta
permlinkmore-realistic-c-find-minimum-and-maximum-among-several-numbers
categoryprogramming
json_metadata{"tags":["programming","cpp","lambda"],"image":["https:\/\/cdn.steemitimages.com\/DQmcTN1fpZfAv95MJ6Tn2EHZnJjcukqm9GJDTFEUzeyjfqm\/image.png"],"links":["https:\/\/steemit.com\/programming\/@xinta\/more-realistic-c-how-to-sum-two-or-more-numbers","https:\/\/steemit.com\/hive-185836\/@rme\/coding-practice-write-a-program-in-c-to-find-out-maximum-and-minimum-number-from-given-integer-numbers-using-conditional","https:\/\/en.cppreference.com\/w\/cpp\/algorithm\/accumulate","https:\/\/en.wikipedia.org\/wiki\/Fold_(higher-order_function)"],"app":"steemit\/0.2","format":"markdown"}
created2021-06-07 22:52:24
last_update2021-06-07 22:52:24
depth0
children0
net_rshares114,732,824,416
last_payout2021-06-14 22:52:24
cashout_time1969-12-31 23:59:59
total_payout_value0.024 SBD
curator_payout_value0.023 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length7,205
author_reputation2,154,434,690,031
root_title"More realistic C++: find minimum and maximum among several numbers"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000
author_curate_reward""
vote details (6)