0

I am trying to find min (by row) and max (by column) element in two-dimensional (4,4) array and then store them in new array (5,5).

That is how it should look for new array (5,5):

1 2 3 4 min
5 6 7 8 min
4 4 4 5 min
3 5 5 6 min
m m m m  0

*m - max

Here it is the entire code:

#include <iostream>
using namespace std;
int main() {
    int A[4][4];/*First array*/
    int i, j;


    for (i = 0; i < 4; i++)
        for (j = 0; j < 4; j++) {
            cout << "\n A[" << i + 1 << "][" << j + 1 << "]=";
            cin >> A[i][j];
        }

    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++)
            cout << A[i][j] << "\t";

        cout << "\n";
    }
    {
        int min[4];/* find min on each row*/
        for (i = 0; i < 4; i++) {
            min[i] = A[0][i];
            for (j = 1; j < 4; j++) {
                if (min[i] > A[i][j])
                    min[i] = A[i][j];
            }
        }
        int newarr[5][5];/* here i create the new array 5,5)*/
        int max[5] = { 1,2,3,4,5 };
        for (i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++) {
                newarr[i][j] = A[i][j];
                newarr[i][5] = max[i];
            }
        }

        for (j = 0; j < 4; j++)
            newarr[5][j] = min[j];
        cout << newarr[5][j] << "\t";
        cout << "\n";
}

}

I put random elements to max. Because so far I only test. But once I started my program it show correct only the first array. And where should be the new array it shows zero. Here it is the outcome of the debugging:

5   4   3   1   
5   6   7   9   
4   2   3   9   
4   8   4   6   
0   

How to fix it? And how to put zero in the last element (as you can see in the first table for the new array).

aspaar321
  • 75
  • 1
  • 1
  • 9
  • You say that you want "max(by row) and min(by column)" but your example shows that you want the min(by row) and max(by column) so to speak?? Which are you trying to acheive?? – silvergasp Dec 14 '15 at 07:09
  • Yes I made a mistake. I fixed it now. – aspaar321 Dec 14 '15 at 07:13
  • 1
    Your `newarray` variable is a 5x5 array, the index in arrays starts at zero so the fifth element in the array would be accessed by the index 4 instead of 5. e.g. change this `newarr[i][5]` to this `newarr[i][4]`. – silvergasp Dec 14 '15 at 07:24
  • You have `newarr[i][5] = max[i];` but the elements in `newarr` only go up to dimension 4, so you're accessing the array out of bounds (or at least unintended elements of the array). You get the zero at `newarr[4][4] = 0;`, probably. – Jonathan Leffler Dec 14 '15 at 07:26
  • Nathaniel Brough I change it but it shows again zero for the new array. – aspaar321 Dec 14 '15 at 07:38
  • And now it shows number 6295552. I guess I'll never be able to fix this code. – aspaar321 Dec 14 '15 at 07:42
  • @aspaar321 It shows "6295552" because you are accessing memory outside the bounds of the array, to further understand this to access the first element in an array you would use `arr[0]` to access the second you would use `arr[1]` etc. So be using `newarr[5][i]` you are trying to access memory that is not defined within the array itself, and is simply leftover memory that was used somewhere else. That is you are trying to access the 6th row of a 5x5 array, this is called overflow and should be avoided at all costs. Does that make more sense? – silvergasp Dec 14 '15 at 07:51
  • I changed the loops and put 5 instead of 4 but now again shows zero. – aspaar321 Dec 14 '15 at 07:58

2 Answers2

2

You can do it in a single pass over all the elements:

// returns a (rows+1, cols+1) matrix
int* make_min_max_vectors(const int* arr, size_t rows, size_t cols) {
    size_t out_size = (rows+1) * (cols+1);
    int* res = malloc(out_size * sizeof(int));

    // set up initial values in the right/bottom vectors
    res[out_size - 1] = 0;

    for (size_t col = 0; col < cols; ++col)
        res[rows*(cols+1) + col] = INT_MIN;

    for (size_t row = 0; row < rows; ++row)
        res[row*(cols+1) + cols] = INT_MAX;

    for (size_t row = 0; row < rows; ++row)
        for (size_t col = 0; col < cols; ++col) {
            const int* cell = &arr[row*cols + col];

            res[row*(cols+1) + col] = *cell; // copy
            if (*cell < res[row*(cols+1) + cols]) // min
                res[row*(cols+1) + cols] = *cell;
            if (*cell < res[rows*(cols+1) + col]) // max
                res[rows*(cols+1) + col] = *cell;
        }
    }
    return res;
}

That is, you simply run over all the input elements once, copying each one to the output plus checking if each one is less than its row minimum or greater than its column maximum. You don't need temporary vectors for min and max, and you don't need to run over the entire input twice.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 1
    I'm a beginner and this method seems to me quite incomprehensible. – aspaar321 Dec 14 '15 at 07:47
  • @aspaar321: Perhaps the most non-obvious part is that I use a simple "array" as a 2D "matrix" by fancy indexing like `res[rows*(cols+1) + col]`. This is pretty typical in C and to some extent in C++ when you write functions to handle multi-dimensional arrays, because when you pass arrays to functions their size is not transmitted as part of their type (unless you write function templates which are probably beyond your current understanding, so I didn't try that). – John Zwinck Dec 14 '15 at 07:49
0

John Swincks answer is awesome (+1'd) and I would definitely recommend his answer simply for future proofing your code. I am relatively new to programming myself and understand how intimidating the above code can seem (especially malloc). Because of this I have written the a version of your code that is very similar however gets rid of the need to have the original 4x4 matrix and instead uses a 5x5. The code is shown below, let me know if you have any issue with it. The code can be compiled as is and will demonstrate what you are trying to acheive.

#include <iostream>

int main()
{
    // Initialised inline to simplify example.
    int A[5][5] = {0};

    // Only uses 4x4 of the 5x5 array meaning that you don't need to use two arrays.
    for (int x = 0; x < 4; ++x)
    {
        for (int y = 0; y < 4; ++y)
        {
            std::cout << "Enter in value for row " << x << ", column " << y << ".\n";
            std::cin >>  A[x][y];
        }
    }

    std::cout << "Input:" << std::endl;
    for (int x = 0; x < 4; ++x)
    {
        for (int y = 0; y < 4; ++y)
        {
            std::cout << A[x][y] << "\t";
        }
        std::cout << "\n";
    }

    // Finds the max down each column in the array
    for (int x = 0; x < 4; ++x)
    {
        for (int y = 0; y < 4; ++y)
        {
            if (A[x][4] < A[x][y])
                A[x][4] = A[x][y];
        }
    }

    // Finds the min across the array (along row) 
    for (int y = 0; y < 4; ++y)
    {
        for (int x = 0; x < 4; ++x)
        {
            // Assign the min to a value in that row.
            A[4][y] = A[1][y];
            if (A[4][y] > A[x][y])
                A[4][y] = A[x][y];
        }
    }

    std::cout << "Output:" << std::endl;
    for (int x = 0; x < 5; ++x)
    {
        for (int y = 0; y < 5; ++y)
        {
            std::cout << A[x][y] << "\t";
        }
        std::cout << "\n";
    }

    std::cin.get();
    std::cin.get();
    return 0;
}

Edit: Sample input and output for clarification.

Input:
1       2       3       4
5       62      4       6
8       9       1       2
4       6       8       9
Output:
1       2       3       4       1
5       62      4       6       4
8       9       1       2       1
4       6       8       9       4
8       62      8       9       0
silvergasp
  • 1,517
  • 12
  • 23
  • Thank you Nathaniel! In your code instead of min in output showing me 629555, 4196464 and so on. And can you explain to me for what is std::. – aspaar321 Dec 14 '15 at 09:10
  • And one more thing about my task. I need a new array because then i have to work with him (5.5). – aspaar321 Dec 14 '15 at 09:28
  • @aspaar321 I have used a `5x5` array to begin with and just entered values into a `4x4` subset. Then once this is done I output the min and max values into the remaining columns and rows as per your description. I have tested a few times and will post my input and output. Perhaps you could tell me which values are incorrect?? – silvergasp Dec 14 '15 at 09:42
  • @aspaar321 `std::` is the identifier for functions in the c++ standard namespace e.g. `std::cout << "hello world" << std::endl` prints 'hello world' followed by adding a newline. It is simply a more explicit way of using functions instead of using `using namespace std;`. I do this as a personal preference to stop name clashes. See this question for an explanation of the issues `using namespace std;` is considered bad practice. http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice – silvergasp Dec 14 '15 at 09:49
  • Maybe it is by the compiler. I use cpp.sh because all of my IDE(Including visual studio, dev++, codeblocsk) are not working. It's strange I start the program and nothing happens just crash. – aspaar321 Dec 14 '15 at 10:00
  • @aspaar321 I am doubtful that it is an issue with the compiler, also I have a feeling that cpp.sh is causing you issues ( i have never heard of it??)... Do you have access to a gnu compiler like g++??? Perhaps take a look at mingw :-) – silvergasp Dec 14 '15 at 10:04
  • Sorry that i do not replied so far. I tryed your code on visual studio and the result is again wrong. With mingw - the same. Here's picture http://oi65.tinypic.com/n8llz.jpg. I dont know what is the problem. – aspaar321 Dec 14 '15 at 18:21
  • Thank you Nathaniel Brough. I don't know why but the values are still incorrec: http://oi63.tinypic.com/2hqqcyb.jpg – aspaar321 Dec 15 '15 at 06:10