-2

My task is to let user enter number n and then the matrix forms with dimensions n*n. Program then, makes diagonal have zeros, number above diagonal have to be positive numbers (1,2,...,n), and numbers below diagonal have to be negative numbers (-1,-2,...,-n). I successfully made the matrix after 8 hours of thinking, but the numbers below diagonal which must be negative, are positive. I cannot find where the problem is.

Input sample:

Enter n: 5
Matrix:
 0   1   2   3   4
-1   0   1   2   3
-2  -1   0   1   2
-3  -2  -1   0   1
-4  -3  -2  -1   0

My output:

Enter n: 5
Matrix:
 0   1   2   3   4
 1   0   1   2   3
 2   1   0   1   2
 3   2   1   0   1
 4   3   2   1   0

My code:

#include <bits/stdc++.h>
using namespace std;
void solve(long long n)
{
    long long array1[n - 1][n - 1], array2[n][n];
 
    for (long long i = 0; i < n - 1; ++i)
        array1[0][i] = i + 1;
 
    for (long long i = 1; i < n - 1; ++i)
        for (long long j = 0; j < n - 1; ++j)
            array1[i][j]
                = array1[i - 1][(j + 1) % (n - 1)];
 
    for (long long i = 0; i < n - 1; ++i)
        for (long long j = 0; j < n - 1; ++j)
            array2[i][j] = array1[i][j];
    for (long long i = 0; i < n; ++i)
        array2[i][n - 1] = array2[n - 1][i] = 0;
        for (long long i = 0; i < n; ++i) {
        long long t0 = array2[i][i];
        long long t1 = array2[i][n - 1];
 
        swap(array2[i][i], array2[i][n - 1]);
 
        array2[n - 1][i] = t0;
    }
    for (long long i = 0; i < n; ++i) {
        for (long long j = 0; j < n; ++j)
            cout << array2[i][j] << " ";
        cout << endl;
    }
}
 
int main()
{
    long long n = 5;
    solve(n);
 
    return 0;
}
casual
  • 39
  • 6
  • 1
    I'm sure if you look at the indices of the diagonal values and the values you need to change, you'll spot a pattern. – sweenish Oct 20 '21 at 20:03
  • 1
    Unrelated: `long long array1[n - 1][n - 1], array2[n][n];` could be a fatal use of the non-standard Variable Length Array extension. An `n` as low as a few hundred could overflow the stack. Have fun debugging the wildly inconsistent Behaviour you can get at that point. You should probably [use something like this instead](https://stackoverflow.com/a/2076697/4581301) to get this data out of Automatic storage. – user4581301 Oct 20 '21 at 20:10
  • In this case it definitely is as the variable in `main()` that determines the size is not a constant, nor is it passed as a constant to the function where the array is created. – sweenish Oct 20 '21 at 20:17
  • Used wrong link above. [Use this instead](https://stackoverflow.com/a/2076668/4581301) – user4581301 Oct 20 '21 at 20:21
  • Do you need to memorize the values in a "matrix" object or you just need to print those out in a tabular format? – Bob__ Oct 20 '21 at 20:53
  • The layout of the code implies a "code golf" site submission. Typically results are just printed. – sweenish Oct 21 '21 at 15:01

2 Answers2

2

Per my comment, the key is to find a pattern that you can exploit. We're also going to stray away from C-arrays, not just because of the SO meme about recommending vectors even when it's not pertinent, but because they're actually the better data structure for this use-case.

You end up using VLAs, or Variable-Length Arrays. They are not a part of C++, but are an optional part of C. Support for VLAs can disappear at any time, and on top of that, they're not safe for the stack as was mentioned in a different comment.

Before we get into a solution, I should address your first two lines of code. Each line has been linked to an answer telling you why they're bad:

#include <bits/stdc++.h>
using namespace std;

So, what's this magical pattern? I chose to look at a row individually. In a typical nested for loop iteration through a square 2D array, the diagonal occurs when the row number is equal to the column number. Diagonals fall on matrix[i][i] if i is the variable used to iterate the rows.

The pattern comes in examining the values of of a row. Values to the left should be negative and values to the right should be positive. Not just that, but the values should be the distance from the diagonal element.

Well, if I use j as my column counter, the value is as simple as j - i. Consider the second row, i = 1.

-1 0 1 2 3

This is row 1, so [1][1] is the zero element. At [1][0], j - i == -1, and so on. Finding the pattern greatly simplifies the code you need to write. Here's an implementation:

#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <vector>

void solve(const long long n) {
  // Declare and zero-initialize
  std::vector<std::vector<int>> v(n, std::vector<int>(n, 0));

  // Fill array
  for (std::size_t i = 0; i < v.size(); ++i) {
    for (std::size_t j = 0; j < v[i].size(); ++j) {
      v[i][j] = static_cast<int>(j) - static_cast<int>(i);
    }
  }

  // Find length of biggest number, v[0][n - 1]; for printing purposes
  int largest = v[0][n - 1];
  int numLength = 0;
  while (largest != 0) {
    ++numLength;
    largest /= 10;
  }

  // Print array
  for (auto i : v) {
    for (auto j : i) {
      std::cout << std::setw(numLength + 2) << j << ' ';
    }
    std::cout << '\n';
  }
}

int main(int argc, char* argv[]) {
  if (argc != 2) return 1;

  long long n = std::atoi(argv[1]);
  solve(n);
}

Sample outputs:

❯ ./a.out 5
  0   1   2   3   4 
 -1   0   1   2   3 
 -2  -1   0   1   2 
 -3  -2  -1   0   1 
 -4  -3  -2  -1   0 

❯ ./a.out 15
   0    1    2    3    4    5    6    7    8    9   10   11   12   13   14 
  -1    0    1    2    3    4    5    6    7    8    9   10   11   12   13 
  -2   -1    0    1    2    3    4    5    6    7    8    9   10   11   12 
  -3   -2   -1    0    1    2    3    4    5    6    7    8    9   10   11 
  -4   -3   -2   -1    0    1    2    3    4    5    6    7    8    9   10 
  -5   -4   -3   -2   -1    0    1    2    3    4    5    6    7    8    9 
  -6   -5   -4   -3   -2   -1    0    1    2    3    4    5    6    7    8 
  -7   -6   -5   -4   -3   -2   -1    0    1    2    3    4    5    6    7 
  -8   -7   -6   -5   -4   -3   -2   -1    0    1    2    3    4    5    6 
  -9   -8   -7   -6   -5   -4   -3   -2   -1    0    1    2    3    4    5 
 -10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0    1    2    3    4 
 -11  -10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0    1    2    3 
 -12  -11  -10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0    1    2 
 -13  -12  -11  -10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0    1 
 -14  -13  -12  -11  -10   -9   -8   -7   -6   -5   -4   -3   -2   -1    0 

It is hopefully very apparent how much simpler the solve() function becomes when we are able to take advantage of a pattern as opposed to brute-forcing it.

sweenish
  • 4,793
  • 3
  • 12
  • 23
1

Just put a condition in nested for loop to check for the elements having index_of_row greater than index_of_column and make them negative.