How can I take the array size input from the user and pass it to the function. I tried #define inside the function, it doesn't work since the array definition needs the array bound at compile time. I tried global variable too, it says to define a integer constant which is not feasible in my case since I want to get the size from the user. How can I solve this issue?
#include <iostream>
using namespace std;
// reverse the transposed matrix as step 2
void reverseColumns(int arr[N][N])
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N / 2; j++)
{
int temp = arr[i][j];
arr[i][j] = arr[i][N - j - 1];
arr[i][N - j - 1] = temp;
}
}
}
// take the transpose of matrix as step 1
void transposeMatrix(int arr[N][N])
{
for (int i = 0; i < N; i++)
{
for (int j = i; j < N; j++)
{
int temp = arr[i][j];
arr[i][j] = arr[j][i];
arr[j][i] = temp;
}
}
}
void rotateMatrix(int mat[N][N])
{
transposeMatrix(mat);
reverseColumns(mat);
}
// printing the final result
void displayMatrix(int mat[N][N])
{
int i, j;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
cout << mat[i][j] << "\t";
cout << "\n";
}
cout << "\n";
}
int main()
{
int T, N;
cin >> T;
while (T > 0)
{
cin >> N;
int mat[N][N];
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
cin >> mat[i][j];
}
}
int res[N][N];
rotateMatrix(mat);
displayMatrix(mat);
}
return 0;
}
One way to make it work is get the input of rows and cols from user and make a one dimensional array dynamically.
for example:
Let ROWS and COLS be the values you got via cin.
Then the array can be declared as
int* arr = new int[ROWS * COLS];
Instead of writing arr[i][j] you have to write
arr[i * COLS + j]
Also you have to delete the array using
delete[] arr;
You are using C++ so you should take advantages of it. As kiner_shah commented the fast way to fix your code is just by use of std::vector<std::vector<int>>.
This is better solution but stil poor:
#include <iostream>
#include <vector>
using namespace std;
using Matrix = std::vector<std::vector<int>>;
Matrix makeSquereMatrix(size_t N)
{
return {N, std::vector<int>(N)};
}
// reverse the transposed matrix as step 2
void reverseColumns(Matrix& arr)
{
auto N = arr.size();
... // no changes here
}
// take the transpose of matrix as step 1
void transposeMatrix(Matrix& arr)
{
auto N = arr.size();
... // no changes here
}
void rotateMatrix(Matrix& mat)
{
transposeMatrix(mat);
reverseColumns(mat);
}
// printing the final result
void displayMatrix(const Matrix& mat)
{
for (auto& row : mat)
{
for (auto x : row)
cout << x << "\t";
cout << "\n";
}
cout << "\n";
}
void readMatrix(Matrix& m)
{
for (auto& row : m)
{
for (auto& x : row)
{
cin >> x;
}
}
}
int main()
{
int T, N;
cin >> T;
while (T > 0)
{
cin >> N;
auto mat = makeSquereMatrix(N);
readMatrix(mat);
rotateMatrix(mat);
displayMatrix(mat);
--T;
}
return 0;
}
Live demo
Better solution would be introducing a class containing std:::vector with methods performing required actions.
BTW some time ago I've made some matrix code for C. Here is live demo
Related
I need make Pascal Triangle matrix using vectors and then print it.
This algorithm would work with arrays, but somehow it doesn't work with matrix using vectors.
#include <iomanip>
#include <iostream>
#include <vector>
typedef std::vector<std::vector<int>> Matrix;
int NumberOfRows(Matrix m) { return m.size(); }
int NumberOfColumns(Matrix m) {
if (m.size() != 0)
return m[0].size();
return 0;
}
Matrix PascalTriangle(int n) {
Matrix mat;
int a;
for (int i = 1; i <= n; i++) {
a = 1;
for (int j = 1; j <= i; j++) {
if (j == 1)
mat.push_back(j);
else
mat.push_back(a);
a = a * (i - j) / j;
}
}
return mat;
}
void PrintMatrix(Matrix m, int width) {
for (int i = 0; i < NumberOfRows(m); i++) {
for (int j = 0; j < NumberOfColumns(m); j++)
std::cout << std::setw(width) << m[i][j];
std::cout << std::endl;
}
}
int main() {
Matrix m = PascalTriangle(7);
PrintMatrix(m, 10);
return 0;
}
I get nothing on screen, and here's the same code just without matrix using vectors program (which works fine).
Could you help me fix this code?
The main problem is that in PascalTriangle, you are starting out with an empty Matrix in both the number of rows and columns.
Since my comments mentioned push_back, here is the way to use it if you did not initialize the Matrix with the number of elements that are passed in.
The other issue is that NumberOfColumns should specify the row, not just the matrix vector.
The final issue is that you should be passing the Matrix by const reference, not by value.
Addressing all of these issues, results in this:
Matrix PascalTriangle(int n)
{
Matrix mat;
for (int i = 0; i < n; i++)
{
mat.push_back({}); // creates a new empty row
std::vector<int>& newRow = mat.back(); // get reference to this row
int a = 1;
for (int j = 0; j < i + 1; j++)
{
if (j == 0)
newRow.push_back(1);
else
newRow.push_back(a);
a = a * (i - j) / (j + 1);
}
}
return mat;
}
And then in NumberOfColumns:
int NumberOfColumns(const Matrix& m, int row)
{
if (!m.empty())
return m[row].size();
return 0;
}
And then, NumberOfRows:
int NumberOfRows(const Matrix& m) { return m.size(); }
And last, PrintMatrix:
void PrintMatrix(const Matrix& m, int width)
{
for (int i = 0; i < NumberOfRows(m); i++)
{
for (int j = 0; j < NumberOfColumns(m, i); j++)
std::cout << std::setw(width) << m[i][j];
std::cout << std::endl;
}
}
Here is a live demo
Your code won't compile because you have numerous errors in PascalTriangle.
For one, you initialize a matrix with no elements. Additionally, you use matrix indices starting at 1 rather than 0.
The following prints things for me:
Matrix PascalTriangle(int n) {
Matrix mat(n, std::vector<int>(n, 0)); // Construct Matrix Properly
int a;
for (int i = 0; i < n; i++) { // Start index at 0
a = 1;
for (int j = 0; j < i + 1; j++) { // Start index at 0
if (j == 0) // Changed 1 to 0
mat[i][j] = 1;
else
mat[i][j] = a;
a = a * (i - j) / (j+1); // Changed j to j+1 since j starts at 0
}
}
return mat;
}
I get a NxM sized matrix and I have to find the max value, the number of max values and the lines that contain it.
I tired using three for{for{}} loops, but it took too long. This method seems to work for small inputs, but when I try it with a 1000x1000 matrix, it finishes before it even takes all the input.
I realise this may be too much of a noob question, but I couldn't find anything else.
Here's my code:
#include <iostream>
using namespace std;
int main()
{
int n, m;
int crnt{-51}, cnt{0};
cin >> n >> m;
int vekt[m];
int lines[n];
int inp;
for(int i=0; i<n; i++)
{
for(int p=0; p<m; p++)
{
cin >> vekt[p];
}
for(int j=0; j<m; j++)
{
if(vekt[j] == crnt)
{
lines[cnt] = i + 1;
cnt += 1;
}
if(vekt[j] > crnt)
{
crnt = vekt[j];
lines[0] = i + 1;
cnt = 1;
}
}
}
cout << cnt;
for(int i=0; i<cnt; i++)
{
cout << " " << lines[i];
}
return 0;
}
EDIT : not using vector or [n] was just easier... I simply saved it to a variable and used a bool:
int main()
{
int n, m;
int crnt{-51}, cnt{0};
cin >> n >> m;
int vekt[m];
int lines[n];
int inp;
bool inLine;
inLine = false;
for(int i=0; i<n; i++)
{
inLine = false;
for(int j=0; j<m; j++)
{
cin >> inp;
if(inp == crnt && inLine == false)
{
lines[cnt] = i + 1;
cnt += 1;
inLine = true;
}
if(inp > crnt)
{
crnt = inp;
lines[0] = i + 1;
cnt = 1;
}
}
}
cout << cnt;
for(int i=0; i<cnt; i++)
{
cout << " " << lines[i];
}
return 0;
}
This cut the time by enough so that I went under the limit.
int vekt[m]; is not standard C++, it is a variable length array (which some compilers allow as extension). Use std::vector instead.
That would also fix the bug you currently have: If cnt >= n (i.e. if you find more maxima than the matrix has lines), you will go out of bounds of lines and your program will most likely crash (although anything could happen), which is more likely to happen with larger matrices.
You can do this instead:
Declaration and initialization:
std::vector<int> linesWithMaxima;
When you find another value equal to the current maximum:
linesWithMaxima.push_back(i+1);
When you find a new maximum (larger than current):
linesWithMaxima.clear();
linesWithMaxima.push_back(i+1);
Note that this will list a line with multiple (identical) maxima multiple times. If you want to avoid duplicates, you can either check that you have not already added the current line (linesWithMaxima.back() != i+1) or use std::sort, std::unique and std::vector::erase.
Other than that your code looks fine. I would recommend naming the loop indices better (line instead of i etc.) and possibly merging the p and j loop because separating them seems to have no purpose. And if you want the most negative integer, use std::numeric_limits<int>::lowest().
Check this realization, without STL and vectors:
void input_matrix(int **&matrix, int &lines, int &columns)
{
int m = 0, n = 0;
cout << "input lines count:";
cin >> m;
cout << "input rows count:";
cin >> n;
matrix = new int *[m];
for(int i = 0;i < m;i++)
matrix[i] = new int[n];
cout << endl << "input matrix:" << endl;
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
cin >> matrix[i][j];
lines = m;
columns = n;
}
void print_matrix(int **&matrix, int &lines, int &columns)
{
for(int i = 0; i < lines; i++)
{
for(int j = 0; j < columns; j++)
cout << matrix[i][j] << " ";
cout << endl;
}
}
int find_max(int **matrix, int lines, int columns, int &max_count)
{
int max = INT_MIN;
max_count = 0;
for(int i = 0; i < lines; i++)
for(int j = 0; j < columns; j++)
{
if(matrix[i][j] > max)
{
max = matrix[i][j];
max_count = 1;
}
else
if(matrix[i][j] == max)
++max_count;
}
return max;
}
int main()
{
int **matrix = nullptr;
int m=0, n=0, count=0;
input_matrix(matrix, n, m);
cout << endl;
print_matrix(matrix, n, m);
cout << endl;
int max = find_max(matrix, n, m, count);
cout << "max=" << max << " count=" << count << endl;
for(int i = 0; i < n; i++)
delete[]matrix[i];
delete []matrix;
}
As requested by mister Max Langhof I would also like to propose a more modern solution, based on the std::vector container, which does not need pointers and manual memory management. It's a simple class matrix:
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstdint>
using namespace std;
class matrix
{
private:
vector<vector<int>> m_data;
public:
matrix(int cols, int rows)
{
m_data.resize(cols);
for(auto &r : m_data)
r.resize(rows);
}
int max_element()
{
int max = INT_MIN;
for(auto &row: m_data)
{
auto maxinrow = *std::max_element(row.begin(), row.end());
if(maxinrow > max)
max = maxinrow;
}
return max;
}
int element_count(int elem)
{
int count = 0;
for(auto &row : m_data)
count += std::count_if(row.begin(), row.end(), [elem](int a){return a == elem;});
return count;
}
friend istream& operator>>(istream &os, matrix &matr);
friend ostream& operator<<(ostream &os, matrix &matr);
};
Input and output operators could be realized like this:
istream& operator>>(istream &os, matrix &matr)
{
for(int i = 0; i < matr.m_data.size(); i++)
{
for(int j = 0; j < matr.m_data[i].size(); j++)
cin >> matr.m_data[i][j];
cout << endl;
}
return os;
}
ostream& operator<<(ostream &os, matrix &matr)
{
for(int i = 0; i < matr.m_data.size(); i++)
{
for(int j = 0; j < matr.m_data[i].size(); j++)
cout << matr.m_data[i][j] << " ";
cout << endl;
}
return os;
}
And a sample of using of this matrix:
int main()
{
int m = 5, n = 4;
matrix matr(m, n);
cout << "input matrix:" << endl;
cin >> matr;
cout << endl << matr;
int max = matr.max_element();
cout << "max: " << max << " count:" << matr.element_count(max) << endl;
}
Checkout something like this
#include <iostream>
#include <set>
#include <vector>
int main() {
int rowsNo, columnsNo;
std::cin >> rowsNo >> columnsNo;
std::vector<int> matrix(rowsNo*columnsNo);
//Creating matrix
for(auto row = 0; row < rowsNo; ++row) {
for (auto column = 0; column < columnsNo; ++column)
std::cin >> matrix[row*columnsNo + column];
}
auto maxValue = -51;
//Finding positions of maximums
std::set<int> linesWithMaxValue;
for (auto position = 0; position < matrix.size(); ++position) {
if(matrix[position] == maxValue)
linesWithMaxValue.insert(position / columnsNo);
else if(matrix[position] > maxValue) {
linesWithMaxValue.clear();
maxValue = matrix[position];
linesWithMaxValue.insert(position / columnsNo);
}
}
//Print info
const auto numberOfMaxValues = linesWithMaxValue.size();
std::cout << "Number of maxiums: " << numberOfMaxValues << std::endl;
std::cout << "Lines that contains maximum:";
for (const auto& lineId : linesWithMaxValue)
std::cout << " " << lineId;
return 0;
}
Here is my code:
#include<iostream>
#include<cstdlib>
using namespace std;
int main() {
int** arr=NULL;
int num=0;
cin >> num;
int* big=NULL;
arr = new int*[num];
for (int i = 0; i < num; i++) {
arr[i] = new int[5];
}
big = new int[num];
for (int i = 0; i < num; i++) {
for (int j = 0; j < 5; j++) {
while (1) {
cin >> arr[i][j];
if (arr[i][j] >= 0 && arr[i][j] < 100)
break;
}
}
}
for (int i = 0; i < 5; i++) {
big[i] = 0;
}
for (int i = 0; i < num; i++) {
for (int j = 0; j < 5; j++) {
if (big[i] < arr[i][j]) {
big[i] = arr[i][j];
}
}
}
for (int i = 0; i < num; i++) {
cout << "Case #" << i + 1 << ": " << big[i] << endl;
}
delete[]big;
for (int i = num-1; i>=0; i--) {
delete[]arr[i];
}
delete[]arr;
return 0;
}
When I run this code, it says that there are heap corruption error (heap corruption detected). I think it means that there are some errors at 'new' or 'delete' parts in my codes, but I cannot find them. I hope someone to answer. Thanks.
Error is here:
big = new int[num];
...
for (int i = 0; i < 5; i++) {
big[i] = 0;
}
So when you have num less than 5 you are writing outside the array.
Anyway you are using C++ so use vector for such tasks.
#include<iostream>
#include<cstdlib>
#include<vector>
using namespace std;
int main() {
vector<vector<int>> arr;
int num=0;
cin >> num;
arr.resize(num, vector<int>(5));
for (auto &row : arr) {
for (auto &cell : row) {
while (1) {
cin >> cell ;
if (cell >= 0 && cell < 100)
break;
}
}
}
vector<int> big(arr.size());
for (int i = 0; i < arr.size(); i++) {
for (auto &cell : arr[i]) {
if (big[i] < cell) {
big[i] = cell;
}
}
}
for (int i = 0; i < num; i++) {
cout << "Case #" << i + 1 << ": " << big[i] << endl;
}
return 0;
}
In many places in your code, you're indexing your big array using indexes from 0 to 5, while the array is allocated using user input, if user input was 4 for example, your code is undefined behavior.
If you're using c++, you shouldn't be manually allocating the arrays, use std::vector instead, it will take care of managing memory for you, so you don't have to new and delete memory yourself.
With std::vector, your code would look somewhat like this.
std::vector<std::vector<int>> arr;
std::vector<int> big;
cin>>num;
arr.resize(num, std::vector<int>(5));
big.resize(5);
You will also be able to use at method to access elements while bound-checking, and size method to get the number of elements of the array.
I'm writing a program for my C++ class that takes the user input for the size of a int and char array, fills the arrays with random values (numbers 0-100, letters A-Z) then sorts, reverses, and displays both arrays.
For the most part the program works and I understand the logic I used here, but...
After running and debugging the code multiple times. I noticed that when the arrays were being filled with values, the first element, even though it was actually being given a value, it would not print the assigned value it was given in ascending order, but would in a descending order? I don't understand this at all.
NOTE: I have to use template functions for the sorting, reversing and display of the arrays.
template <class T>
void sort(T *arr, int a) {
T temp;
for (int i = 0; i < a; i++) {
for (int j = a; j > 0; j--) {
if (arr[i] > arr[j]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
template <class T>
void reverse(T *arr, int a) {
T temp;
for (int i = 0; i < a / 2; i++) {
temp = arr[i];
arr[i] = arr[a - i];
arr[a - i] = temp;
}
}
template <class T>
void display(T *arr, int a) {
for (int i = 0; i < a; i++) {
cout << arr[i] << ", ";
}
cout << endl;
}
template<class T>
void save(T *arr, int a) {
sort(arr, a);
display(arr, a);
reverse(arr, a);
display(arr, a);
}
int main() {
int x, y;
cout << "Please enter a number for an array of data type \"int\"" << endl;
cin >> x;
cout << "Please enter a number for an array of data type \"char\"" << endl;
cin >> y;
int *arr1 = new int[x];
char *arr2 = new char[y];
for (int i = 0; i < x; i++)
cout << (arr1[i] = rand() % 100 + 1);
srand(time(nullptr));
for (int i = 0; i < y; i++)
cout << (arr2[i] = rand() % 26 + 65);
system("cls");
save(arr1, x);
save(arr2, y);
delete[]arr1;
delete[]arr2;
system("pause");
return 0;
}
You are using the complete length here:
save(arr1, x);
save(arr2, y);
So in reverse
arr[i] = arr[a - i];
arr[a - i] = temp;
you need to -1 on the length or you'll get an invalid index when i == 0
arr[i] = arr[a - 1 - i];
arr[a - 1 - i] = temp;
Like R Sahu says, in sort
for (int j = a; j > 0; j--) {
you need to -1 because a is the length which will be an invalid index.
for (int j = a-1; j > 0; j--) {
As a side note, you can declare Temp t inside of the for loop in reverse and inside of the if in sort because it is only used in those scopes.
EDIT:
Also I overlooked, in sort you need to change
j>0
to
j >= 0
that way you access the first element of the array as well.
You have a off-be-one error in couple of places.
for (int j = a; j > 0; j--) {
is incorrect. a is an invalid index for the array. Change that line to use j = a-1:
for (int j = a-1; j > 0; j--) {
You have a similar, off-by-one, error in reverse. Instead of
arr[i] = arr[a - i];
arr[a - i] = temp;
you need to use:
arr[i] = arr[a - i - 1];
arr[a - i - 1] = temp;
Your implementation of sort is not correct. I don't want to get into the algorithmic details here but changing the order of the values used for j seems to fix the problem.
for (int i = 0; i < a; i++) {
for (int j = i+1 ; j < a ; j++) {
// The swapping code.
}
}
You are using bubble sort that is O(n^2) time complexity. Consider using faster algorithm. If you don't want to implement it on your own, use sort() function. It's complexity is about O(n log n), which is very good.
http://www.cplusplus.com/reference/algorithm/sort/
#include <iostream>
#include <algorithm>
using namespace std;
bool comp(int i1, int i2) { // comp function is to compare two integers
return i1 < i2;
}
int main() {
int x[30];
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x[i];
}
sort(x, x + n, comp); // if you don't provide comp function ( sort(x, x+n) ), sort() function will use '<' operator
for (int i = 0; i < n; i++) {
cout << x[i] << " ";
}
return 0;
}
I've managed to find the minimum value of every row of my 2D array with this
void findLowest(int A[][Cm], int n, int m)
{
int min = A[0][0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (A[i][j] < min)
{
min = A[i][j];
}
}
out << i << " row's lowest value " << min << endl;
}
}
I'am trying to find the maximum value of every row using the same way,but it only shows me first maximum value
void findHighest(int A[][Cm], int n, int m)
{
int max = A[0][0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (A[i][j] > max)
{
max = A[i][j];
}
}
out << i << " row's highest value " << max << endl;
}
}
I can't find what's wrong with the second function and why is it only showing me the first maximum value it finds. Any help ?
Both functions return the result (maximum or minimum) for the whole array rather than each row, because you set max once rather than once per row. You can get the result for each row as follows:
void findHighest(int A[][Cm], int n, int m)
{
for (int i = 0; i < n; i++)
{
int max = A[i][0];
for (int j = 1; j < m; j++)
{
if (A[i][j] > max)
{
max = A[i][j];
}
}
// do something with max
}
}
or, even better, use the standard library function max_element:
void findHighest(int A[][Cm], int n, int m)
{
if (m <= 0) return;
for (int i = 0; i < n; i++)
{
int max = *std::max_element(A[i], A[i] + m);
// do something with max
}
}
This should give you all values which is easy to check:
#include <algorithm>
#include <iostream>
enum { Cm = 2 };
void findHighest(int A[][Cm], int n, int m) {
if (m <= 0) return;
for (int i = 0; i < n; i++) {
int max = *std::max_element(A[i], A[i] + m);
std::cout << max << " ";
}
}
int main() {
int A[2][2] = {{1, 2}, {3, 4}};
findHighest(A, 2, 2);
}
prints 2 4.
If your compiler supports C++11, for concrete arrays you could use the following alternative, that's based on std::minmax_element:
template<typename T, std::size_t N, std::size_t M>
void
minmax_row(T const (&arr)[N][M], T (&mincol)[N], T (&maxcol)[N]) {
for(int i(0); i < N; ++i) {
auto mnmx = std::minmax_element(std::begin(arr[i]), std::end(arr[i]));
if(mnmx.first != std::end(arr[i])) mincol[i] = *(mnmx.first);
if(mnmx.second != std::end(arr[i])) maxcol[i] = *(mnmx.second);
}
}
Live Demo
Your test data is guilty for not clearly showing you the defect.
The row minima occur in decreasing values, so that they get updated on every row.
And the row maxima also occur in decreasing values, so that the first one keeps winning.
As others pointed, your function finds the global minimum/maximum, no the per-row extrema.
Move the initialization of the min/max variable inside the outer loop.
As mentioned your code only shows the maximum element in the whole array.
Here is the code which will help you.
void findHighest(int A[][Cm], int n, int m)
{
int max[n];
max[0]=A[0][0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (A[i][j] > max[i])
{
max[i] = A[i][j];
}
}
cout << i << " row's highest value " << max[i] << endl;
}
}
{
int i,j;
int arr[4][2]={(1,2),(3,4),(5,6),(7,8)};
int max;
max=arr[0][0];
for( int i=0; i<4; i++)
{
for(int j=0; j<2; j++)
{
if(max<arr[i][j])
{
max=arr[i][j];
}
}
}
int min;
min=arr[0][0];
for(int i=0; i<4; i++)
{
for(int j=0; j<2; j++)
{
if(min>arr[i][j])
{
min=arr[i][j];
}
}
}
cout<<"maximum number is:"<<max;
cout<<endl;
cout<<"Minimum Number is:"<<min;
}