-1

I am facing a problem where two 2-dimensional arrays need to merge according to the given condition, where n=5 and k=3.

1st array->

1 2 
3 4 
5 6 
7 8 
9 10

2nd array->

11 12 13 
14 15 16 
17 18 19 
20 21 22 
23 24 25

The resultant array->

 1 2 11 12 13 
 3 4 14 15 16 
 5 6 17 18 19
 7 8 20 21 22
 9 10 23 24 25

My approach to this problem is to first take an empty 2-D array of above two array dimensions, then to place two array elements into the ans array index by index. I can put the 1st array into ans array, but failed to put the 2nd array into the resultant array. It's showing a run-time error for inserting the 2nd array. I need help for that.

#include <iostream>
using namespace std;

int main()
{
    int n, k;
    cin >> n >> k;
    int p = n - k + 1, q = n - k;
    int a[n + 1][q + 1], b[n + 1][p + 1], ans[n + 1][n + 1];
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= q; ++j)
            a[i][j] = 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= p; ++j)
            b[i][j] = 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            ans[i][j] = 0;

    int x = 1;
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= q; ++j)
            a[i][j] = x++;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= p; ++j)
            b[i][j] = x++;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= q; ++j)
            ans[i][j] = a[i][j];
    }
    int I = 1, J = 0;
    for (int i = 1; i <= n; ++i)
    {
        I += 2, J++;
        for (int j = 1; j <= p; ++j)
        {
            ans[I][J] = b[i][j];
            I++;
        }
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= q; ++j)
            cout << a[i][j] << " ";
        cout << endl;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= p; ++j)
            cout << b[i][j] << " ";
        cout << endl;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= n; ++j)
            cout << ans[i][j] << " ";
        cout << endl;
    }

    return 0;
}
MrBean Bremen
  • 14,916
  • 3
  • 26
  • 46
  • 1
    Arrays in C++ are 0-based. Stop trying to pretend they're 1-based by wasting the first element. – Joseph Sible-Reinstate Monica May 24 '20 at 05:37
  • 1
    Please note that `a`, `b` and `q` are declared as variable length arrays (their sizes aren't known at compile time), a [non-standard](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) extension provided by some compilers. You should use standard containers like `std::vector` or implement a class. – Bob__ May 24 '20 at 19:29

3 Answers3

0

So you have 3 matrices each one has n rows.

First matrix has m=2 columns.

Second matrix has k=3 columns.

Third matrix (the merged one) has m+k columns.

Your code should be like that:

#include <iostream>
using namespace std;

int main()
{
  const int k=3;
  const int m=2;
  const int n=5;

  int arr1[n][m];
  int arr2[n][k];
  int arr3[n][m+k];

  for(int i=0; i<n; i++)
    for (int j=0; j<m; j++)
      arr1[i][j]=1+2*i+j;

  for(int i=0; i<n; i++)
    for (int j=0; j<k; j++)
      arr2[i][j]=11+3*i+j;

  for(int i=0; i<n; i++)
    for (int j=0; j<n; j++){
      if(j<m)
        arr3[i][j]=arr1[i][j];
      else
        arr3[i][j]=arr2[i][j-m];
    }

  for(int i=0; i<n; i++){
    for (int j=0; j<n; j++)
      cout<< arr3[i][j]<<" ";
    cout<<endl;
  }
}
NAND
  • 663
  • 8
  • 22
0

Here's a way of doing it... I've made it generic enough that it can handle arrays that are not of an equal number of rows. The unfilled spots are initialized as zero.

MATRIX.h -- Header file for the MATRIX 'object'

#ifndef _MATRIX_H_
#define _MATRIX_H_
    typedef struct matrix {
        int   rows;
        int   cols;
        int   elemSize;
        void  *data;
    } *MATRIX;

    int   MATRIX_Create( MATRIX *handlePtr, int initElemSize,
                         int initRows, int initCols );
    int   MATRIX_Close( MATRIX *handlePtr );
    int   MATRIX_Set( MATRIX handle, int row, int col, void *data );
    void  *MATRIX_GetAddr( MATRIX handle, int row, int col );
    int   MATRIX_Get( MATRIX handle, int row, int col, void *retData );
    int   MATRIX_Merge( MATRIX *newHandlePtr, MATRIX leftHandle, MATRIX rightHandle );
#endif

MATRIX.c -- Source file for the MATRIX 'object'

#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include "MATRIX.h"

#define MAX(x,y) ((x > y) ? x : y)

int  MATRIX_Create( MATRIX *handlePtr, int initElemSize, int initRows, int initCols )
{
    MATRIX  handle;

    if (handlePtr == NULL)
        return (-1);

    handle = calloc(sizeof(struct matrix), 1);
    if (handle == NULL)
        return (-2);

    handle->data = calloc(initElemSize, initRows * initCols);
    if (handle->data == NULL) {
        printf("ERROR -- Could not create MATRIX data area\n");
        free(handle);
        return (-3);
    }

    handle->rows = initRows;
    handle->cols = initCols;
    handle->elemSize = initElemSize;

    *handlePtr = handle;

    return (0);
}

int  MATRIX_Close( MATRIX *handlePtr )
{
    if (handlePtr == NULL)
        return (-1);

    free(*handlePtr);
    *handlePtr = NULL;

    return (0);
}

int  MATRIX_Set( MATRIX handle, int row, int col, void *data )
{
    unsigned char  *addr;
    int            addrOffset;

    if ((handle == NULL) || (data == NULL))
        return (-1);

    addr = handle->data;
    addrOffset = row * handle->cols * handle->elemSize + (col * handle->elemSize);
    addr += addrOffset;

    memcpy(addr, data, handle->elemSize);

    return (0);
}

void  *MATRIX_GetAddr( MATRIX handle, int row, int col )
{
    unsigned char  *addr;
    int            addrOffset;

    if (handle == NULL)
        return (NULL);

    addr = handle->data;
    addrOffset = row * handle->cols * handle->elemSize + (col * handle->elemSize);
    addr += addrOffset;

    return (addr);
}

int MATRIX_Get( MATRIX handle, int row, int col, void *retData )
{
    unsigned char  *addr;
    int            addrOffset;

    if ((handle == NULL) || (retData == NULL))
        return (-1);

    addr = MATRIX_GetAddr(handle, row, col);

    memcpy(retData, addr, handle->elemSize);

    return (0);
}

int  MATRIX_Merge( MATRIX *newHandlePtr, MATRIX leftHandle, MATRIX rightHandle )
{
    int     i;
    int     j;
    MATRIX  retHandle;
    int     retCols;
    int     retRows;
    int     result;

    if ((newHandlePtr == NULL) || (leftHandle == NULL) || (rightHandle == NULL))
        return (-1);

    /* Ensure that the element sizes for the two matrices to be merged are the same */
    if (leftHandle->elemSize != rightHandle->elemSize)
        return (-2);

    retCols = leftHandle->cols + rightHandle->cols;
    retRows = MAX(leftHandle->rows, rightHandle->rows);

    result = MATRIX_Create(&retHandle, leftHandle->elemSize, retRows, retCols);
    if (result != 0)
        return (-3);

    /* First copy the left matrix into the merged array */
    for (i = 0; i < leftHandle->rows; i++) {
        for (j = 0; j < leftHandle->cols; j++) {
            result = MATRIX_Set(retHandle, i, j, MATRIX_GetAddr(leftHandle, i, j));
            if (result != 0) {
                printf("ERROR -- MATRIX_Set() returned %d\n", result);
                free(retHandle->data);
                free(retHandle);
                return (result);
            }
        }
    }

    /* And then copy the right matrix into the merged array */
    for (i = 0; i < rightHandle->rows; i++) {
        for (j = 0; j < rightHandle->cols; j++) {
            result = MATRIX_Set(retHandle, i, j+leftHandle->cols, MATRIX_GetAddr(rightHandle, i, j));
            if (result != 0) {
                printf("ERROR -- MATRIX_Set() returned %d\n", result);
                free(retHandle->data);
                free(retHandle);
                return (result);
            }
        }
    }

    *newHandlePtr = retHandle;

    return (0);
}

matrix-test.c -- main program file for test code

#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define MAX(x,y) ((x > y) ? x : y)

int  MergeArray2D( int **retArrayPtr, int *retRowsPtr, int *retColsPtr,
                   int *leftArray, int leftRows, int leftCols,
                   int *rightArray, int rightRows, int rightCols )
{
    int  *retArray;
    int  i;
    int  j;
    int  retCols;
    int  retRows;

    if ((retArrayPtr == NULL) || (retColsPtr == NULL) || (retRowsPtr == NULL) || (leftArray == NULL))
        return (-1);

    retCols = leftCols + rightCols;
    retRows = MAX(leftRows, rightRows);

    retArray = calloc(sizeof(int), retRows * retCols);
    if (retArray == NULL)
        return (-2);

    /* First copy the left array into the merged array */
    for (i = 0; i < leftRows; i++) {
        for (j = 0; j < leftCols; j++) {
            retArray[i * retCols + j] = leftArray[i * leftCols + j];
        }
    }

    /* And then copy the right array into the merged array */
    for (i = 0; i < rightRows; i++) {
        for (j = 0; j < rightCols; j++) {
            retArray[i*retCols + j + leftCols] = rightArray[i * rightCols + j];
        }
    }

    *retArrayPtr = retArray;
    *retColsPtr = retCols;
    *retRowsPtr = retRows;

    return (0);
}

void  PrintArray2D( int *array, int numRows, int numCols )
{
    int  i;
    int  j;

    for (i = 0; i < numRows; i++) {
        for (j = 0; j < numCols; j++) {
            printf(" %5d", array[i * numCols + j]);
        }
        printf("\n");
    }
}

int  main( int argc, char **argv )
{
    int     leftRows = 5;
    int     leftCols = 2;
    int     leftArray[5][2];
    int     rightRows = 6;
    int     rightCols = 3;
    int     rightArray[6][3];
    int     i;
    int     j;
    int     count;
    int     result;
    int     *newArray;
    int     newRows;
    int     newCols;
    MATRIX  leftMatrix;
    MATRIX  rightMatrix;
    MATRIX  newMatrix;

    printf("sizeof(void *) = %d\n", sizeof(void *));
    printf("sizeof(int) = %d\n\n", sizeof(int));
    count = 0;

    /* Initialize the left array */
    for (i = 0; i < leftRows; i++) {
        for (j = 0; j < leftCols; j++) {
            count++;
            leftArray[i][j] = count;
        }
    }

    /* Initialize the right array */
    for (i = 0; i < rightRows; i++) {
        for (j = 0; j < rightCols; j++) {
            count++;
            rightArray[i][j] = count;
        }
    }

    /* Print out the left array */
    printf("Left Array:\n");
    PrintArray2D((int *) leftArray, leftRows, leftCols);

    /* Print out the right array */
    printf("\nRight Array:\n");
    PrintArray2D((int *) rightArray, rightRows, rightCols);

    /* Merge the two arrays */
    result = MergeArray2D(&newArray, &newRows, &newCols, (int *) leftArray, leftRows, leftCols, (int *) rightArray, rightRows, rightCols);
    if (result != 0) {
        printf("ERROR -- MergeArrays2D() returned %d\n", result);
    }

    /* Print out the merged array */
    printf("\nMerged Array:\n");
    PrintArray2D(newArray, newRows, newCols);

    /* Clean up the allocated merged array when through using it */
    free(newArray);

    /* And now for a way of doing the same thing with the MATRIX object */
    printf("\n\nTrying same thing using MATRIX object\n\n");
    result = MATRIX_Create(&leftMatrix, sizeof(int), leftRows, leftCols);
    if (result != 0) {
        printf("ERROR -- MATRIX_Create(leftMatrix) returned %d\n", result);
        return (result);
    }

    result = MATRIX_Create(&rightMatrix, sizeof(int), rightRows, rightCols);
    if (result != 0) {
        printf("ERROR -- MATRIX_Create(rightMatrix) returned %d\n", result);
        return (result);
    }

    /* Initialize the left matrix */
    count = 0;
    for (i = 0; i < leftMatrix->rows; i++) {
        for (j = 0; j < leftMatrix->cols; j++) {
            count++;
            result = MATRIX_Set(leftMatrix, i, j, &count);
            if (result != 0)
                printf("ERROR -- Could not set element %d,%d\n", i, j);
        }
    }

    /* Print out the left matrix */
    printf("\nLeft Matrix[rows=%d,cols=%d,elemSize=%d]:\n", leftMatrix->rows, leftMatrix->cols, leftMatrix->elemSize);
    PrintArray2D(leftMatrix->data, leftMatrix->rows, leftMatrix->cols);

    /* Initialize the right matrix */
    for (i = 0; i < rightMatrix->rows; i++) {
        for (j = 0; j < rightMatrix->cols; j++) {
            count++;
            result = MATRIX_Set(rightMatrix, i, j, &count);
        }
    }

    /* Print out the right matrix */
    printf("\nRight Matrix[rows=%d,cols=%d,elemSize=%d]:\n", rightMatrix->rows, rightMatrix->cols, rightMatrix->elemSize);
    PrintArray2D(rightMatrix->data, rightMatrix->rows, rightMatrix->cols);

    /* Merge the two matrices */
    result = MATRIX_Merge(&newMatrix, leftMatrix, rightMatrix);
    if (result != 0) {
        printf("ERROR -- MATRIX_Merge() returned %d\n", result);
        return (result);
    }

    /* Print out the new matrix */
    printf("\nMerged Matrix[rows=%d,cols=%d,elemSize=%d]:\n", newMatrix->rows, newMatrix->cols, newMatrix->elemSize);
    PrintArray2D(newMatrix->data, newMatrix->rows, newMatrix->cols);

    /* Cleanup the newMatrix when finished */
    result = MATRIX_Close(&newMatrix);
}

Output from the test program:

sizeof(void *) = 4
sizeof(int) = 4

Left Array:
     1     2
     3     4
     5     6
     7     8
     9    10

Right Array:
    11    12    13
    14    15    16
    17    18    19
    20    21    22
    23    24    25
    26    27    28

Merged Array:
     1     2    11    12    13
     3     4    14    15    16
     5     6    17    18    19
     7     8    20    21    22
     9    10    23    24    25
     0     0    26    27    28


Trying same thing using MATRIX object


Left Matrix[rows=5,cols=2,elemSize=4]:
     1     2
     3     4
     5     6
     7     8
     9    10

Right Matrix[rows=6,cols=3,elemSize=4]:
    11    12    13
    14    15    16
    17    18    19
    20    21    22
    23    24    25
    26    27    28

Merged Matrix[rows=6,cols=5,elemSize=4]:
     1     2    11    12    13
     3     4    14    15    16
     5     6    17    18    19
     7     8    20    21    22
     9    10    23    24    25
     0     0    26    27    28

To make this a generic solution, I'm treating the 2D arrays as just a 1D array since that is how they are laid out in memory anyway. If you don't want a generic solution, it should be easy for you to modify the code and you won't have as many parameters that need to be passed into the MergeArray2D function.

EDITED: I've added an even more generic solution by creating the 'C' version of a MATRIX 'object' like we used to implement 'objects' in back when I worked for NASA via one of the aerospace contractors here in Houston. I've also split the header and source files for the 'object' into separate code windows to make it easier to read. For any of the C++ folks, it will probably be a trivial matter to convert that to a C++ class, but I think straight 'C' is better from a teaching standpoint. This 'object' allows for it to be 'instantiated' with a different base element data size other than 'int' which was used in the first example. I have tested the code using gcc on a PC and it does in fact compile and run correctly. Hope this helps...

0

There are three main issues in the posted code

  • a, b and ans are declared as variable length arrays (their sizes aren't known at compile time), a non-standard extension provided by some compilers. The OP could have used a standard container like std::vector or a user-defined class.

  • All the loops start at 1, while in C++ array indices are 0-based. The writer of this code seems to know this fact, but for some reason preferred to allocate extra (unused) space in all the arrays and to accomodate the termitation conditions accordingly.

  • The nested loop which tries to copy the values from b to ans is simply wrong and causes multiple accesses out of bounds.

    int I = 1, J = 0;                     // --->  I = 0, keeping OP's convention
    for (int i = 1; i <= n; ++i)
    {
        I += 2, J++;                      // --->  ++I, J = q
        for (int j = 1; j <= p; ++j)
        {
            ans[I][J] = b[i][j];
            I++;                          // ---> ++J
        }
    }
    

In the following snippet shows an alternative implementation where the matrices are modelled using a class and the merge function performs the wanted operation.

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <stdexcept>
#include <vector>

template <class T>
class Matrix
{
    size_t rows_{};
    size_t cols_{};
    std::vector<T> m_;
public:
    Matrix() = default;
    Matrix(size_t r, size_t c)
        : rows_{r}, cols_{c}, m_(r * c)
    {}

    auto rows() const noexcept {
        return rows_;
    }
    auto columns() const noexcept {
        return cols_;
    }
    auto operator[] (size_t i) noexcept {
        return m_.begin() + cols_ * i;
    }
    auto operator[] (size_t i) const noexcept {
        return m_.cbegin() + cols_ * i;
    }
    auto begin() noexcept {
        return m_.begin();
    }
    auto end() noexcept {
        return m_.end();
    }
};

template <class T>
std::ostream& operator<< (std::ostream& os, Matrix<T> const& m)
{
    for (size_t i{}; i < m.rows(); ++i)
    {
        for (size_t j{}; j < m.columns(); ++j)
            os << m[i][j] << ' ';
        os << '\n';
    }
    return os;
}

template<class T>
auto merge(Matrix<T> const& a, Matrix<T> const& b)
{
    if (a.rows() != b.rows())
        throw std::runtime_error{"Number of rows mismatch"};

    Matrix<T> result(a.rows(), a.columns() + b.columns());

    for (size_t i{}; i < a.rows(); ++i)
    {
        auto it = std::copy(a[i], a[i] + a.columns(), result[i]);
        std::copy(b[i], b[i] + b.columns(), it);
    }

    return result;
}


int main()
{
    int n, k;
    std::cin >> n >> k;
    int p = n - k + 1, q = n - k;

    Matrix<int> a(n, q);
    std::iota(a.begin(), a.end(), 1);
    std::cout << a << '\n';

    Matrix<int> b(n, p);
    std::iota(b.begin(), b.end(), n * q + 1);
    std::cout << b << '\n';

    auto c = merge(a, b);
    std::cout << c << '\n';
}
Bob__
  • 12,361
  • 3
  • 28
  • 42