AztekTR
AztekTR

Reputation: 45

C++ Find the sum of elements between minimum and maximum element of matrix

So, My program works as it should, but only if minimum and maximum element are in opposite corners. So my question is how to iterate two-dimensional array from one certain element to another(and perhaps get rid of some nested loops). Shall I convert this array to one-dimensional?

Here's the correct work of the code:

Here's correct work of the code

And here's when something went wrong. The elements {0}{1} and {1}{1} got lost.

enter image description here

And here's the shortened varian of the code:

#include <iostream>

using namespace std;

void matrix_count(int a[5][5],int min, int max, int min_i, int min_j, int max_i, int max_j) {
    int suma = 0;
    int counter = 0;
    if (min_i <= max_i && min_j <= max_j) { 
        for (int i = 0; i < 5; i++) {       //iterating all matrix
            for (int j = 0; j < 5; j++) {
                if (a[i][j] == min) {       //start a new cycle when find min
                    for (int i = min_i; i < 5; i++) {
                        for (int j = min_j; j < 5; j++) {
                            if (a[i][j] == max) { i = 5; break; }
                            else if (a[i][j] != min) {
                                counter++;
                                suma += a[i][j];
                                cout << a[i][j] << " ";
                            }
                        }
                    }
                }
            }
        }
    }
    else if (min_i >= max_i && min_j <= max_j) {} // min[i]<max[i] min[j]<max[j]
    else if (min_i <= max_i && min_j >= max_j) {} // min[i]<max[i] min[j]>max[j]
    else if (min_i >= max_i && min_j >= max_j) {} // min[i]>max[i] min[j]>max[j]
    cout << endl;
    cout << suma << endl;
    cout << counter << endl;
}

int main()
{
    int a[5][5] = { 
        {0,4,6,3,5},
        {7,1,5,6,2},
        {6,8,8,5,2},
        {4,1,5,2,2},
        {4,3,6,5,9} };
    int min = a[0][0];
    int max = a[0][0];
    int max_i = 0;
    int min_i = 0;
    int max_j = 0;
    int min_j = 0;

// finding the max
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            if (a[i][j] > max) {
                max = a[i][j];
                max_i = i;
                max_j = j;
            }
        }
    }

// finding the min
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            if (a[i][j] < min) {
                min = a[i][j];
                min_i = i;
                min_j = j;
            }
        }
    }

    matrix_count(a, min, max, min_i, min_j, max_i, max_j);

    return 0;
}

Upvotes: 2

Views: 811

Answers (3)

AztekTR
AztekTR

Reputation: 45

Even though the answer has already been given, I will share my personal solution, where I'm using conversion array to the one-dimensional.

#include <iostream>

using namespace std;

const int N = 5;
const int M = 5;

void matrix_count(int a[N * M], int min , int max, int min_i, int max_i) {
    int counter = 0;
    int sum = 0;
    printf("\n\n");
    if (min_i <= max_i) {
        for (int i = min_i + 1; i < N * M; i++) {
            if (a[i] == max) { break; }
            counter++;
            sum += a[i];
            cout << a[i] << " ";
        }
    }
    else if (min_i >= max_i) {
        for (int i = max_i + 1; i < N * M; i++) {
            if (a[i] == min) { break; }
            counter++;
            sum += a[i];
            cout << a[i] << " ";
        }
    }
    printf("\n\n");
    cout <<"sum = "<< sum << endl;
    cout << "number of elements = " <<counter << endl;
    printf("\n");
    for (int i = 0; i < N*M ; i++) a[i] = 0;
}

void find_min(int a_one[N * M], int &min, int &min_i) {
    for (int i = 0; i < N * M; i++) {
        if (a_one[i] < min) {
            min = a_one[i];
            min_i = i;
        }
    }
    printf("\nMin_i = %d", min_i);
    printf("\nMin = %d", min);
}

void find_max(int a_one[N * M], int& max, int& max_i) {
    for (int i = 0; i < N * M; i++) {
        if (a_one[i] > max) {
            max = a_one[i];
            max_i = i;
        }
    }
    printf("\nMax_i = %d", max_i);
    printf("\nMax = %d", max);
}
void convert_arr(int a1[N][M],int a_one[N*M], int &i_one) {
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++)
        {
            a_one[i_one] = a1[i][j];
            i_one++;
            cout << a1[i][j] << " ";
        }
        printf("\n");
    }
}

int main()
{
    setlocale(0, "");
    int max_i = 0;
    int min_i = 0;
    int a1[N][M] = {
        {6,4,6,3,9},
        {7,1,5,6,2},
        {0,8,8,5,2},
        {4,1,5,2,2},
        {4,3,6,5,7} };
    int a_one[N * M] = {};
    int i_one = 0;

    convert_arr(a1, a_one, i_one);

    int min_1 = a_one[0];
    find_min(a_one, min_1, min_i);

    int max_1 = a_one[0];
    find_max(a_one, max_1, max_i);

    matrix_count(a_one, min_1, max_1, min_i, max_i);

    return 0;
}

Upvotes: 0

PaulMcKenzie
PaulMcKenzie

Reputation: 35454

As my comment stated, one solution is to realize that the two-dimensional array has a layout of its data in contiguous memory. Thus getting the minimum, maximum, and sum become simple, since you would traverse the two-dimensional array in the same way as a one-dimensional array.

Here is a solution using C++ algorithm functions.

#include <algorithm>
#include <iostream>
#include <numeric>

int main()
{
    int a[5][5] = {
        {0,4,6,3,5},
        {7,1,5,6,2},
        {6,8,8,5,2},
        {4,1,5,2,2},
        {4,3,6,5,9} };

    // Get both the position of the minimum and maximum element in the array  
    auto pr = std::minmax_element(&a[0][0], &a[4][5]);

    // add up all elements between the min and max elements 
    int answer = std::accumulate(std::next(pr.first), pr.second, 0);

    // output results
    std::cout << answer;
}

Output:

100

Yes, that is the entire code.

So what was done?

First, we use std::minmax_element to traverse the array starting from a pointer to the first element (&a[0][0]) to one passed the last element (&a[4][5]). Note the arguments to the function -- the reason why this works is that a two-dimensional array has that contiguous layout I mentioned earlier. So it's just a matter of figuring out the starting and ending positions.

The return value of std::minmax_element is a std::pair<int*, int*> that point to the minimum element (the first) and maximum element (the second). That is what the pr denotes.

Once that's done, we can quickly add up the items between the minimum and maximum elements by using std::accumulate with the pointers we have from pr.

Note that the first argument to std::accumulate is the next value after the minimum value found. That is the reason for the std::next in the first argument -- it takes us to the next value.

Upvotes: 3

The problem is that you are only iterating from min_i to 5. In this for statement:
for (int i = min_i; i < 5; i++)
This means that every line will start at min_i.

One easy way to solve this is to iterate first for the rest of the line, like so:

for(int i = min_i+1; i < 5; i++) {
    if (a[i][j] == max) { i = 5; break; }
    counter++;
    suma += a[i][min_j];
}

And then iterate over what remains with the following loop:

for (int i = 0; i < 5; i++) {
    for (int j = min_j+1; j <= max_j; j++) {
        if (a[i][j] == max) { i = 5; break; }
        counter++;
        suma += a[i][j];
        cout << a[i][j] << " ";
    }
}

But in general I would really suggest you think a bit more about your code, as all of what you are doing could be done by iterating just once over the entire matrix. Also, the first two loops that go until arriving at minimum are not only confusing (you are reusing j and i), but also unnecessary. You can directly start at min_i+1 like in the code I showed above.

Upvotes: 1

Related Questions