This might be easy but I just cant find a solution. I created a 2D vector like this:
vector<vector<int> > matrix;
vector<int> row;
for (int i = 0; i < x;i++) {
row.push_back(i);
}
for (int i = 0; i < x; i++) {
matrix.push_back(row);
}
The problem I have is that I now wanna add rows and columns as I need them because I might run out of matrix space over time but I don't know how to do it. The rows are easy I can just .push_back another row to the bottom end of the matrix...but I have no Idea how to add another column.
I'm sorry if this question is super stupid but I'm not that experienced in programming yet and I couldn't find anything on the particular problem of adding columns to a 2D vector.
Adding to your code, the idea is to loop over each row in the matrix and push a new element onto each vector. Together, all of these elements are a new column.
#include <iostream>
#include <vector>
using namespace std;
int main() {
// Initialize a 3x3 matrix
vector<vector<int>> matrix;
vector<int> row;
int x = 3;
for (int i = 0; i < x; i++) {
row.push_back(i);
}
for (int i = 0; i < x; i++) {
matrix.push_back(row);
}
// Add a column; the matrix is now 3x4
int newElement = 3;
for (auto &row : matrix) {
row.push_back(newElement);
}
// Print the matrix
for (auto &row : matrix) {
for (auto &cell : row) {
cout << cell << ' ';
}
cout << endl;
}
return 0;
}
You'll likely want to separate this code into functions.
vector<vector<T>> is a BAD way to implement a matrix. Well - it may not be a bad backend implementation, but its a bad public API.
I'd suggest using some library designed to support a Matrix. A few come to mind:
https://github.com/SophistSolutions/Stroika/blob/V2.1-Release/Library/Sources/Stroika/Foundation/Math/LinearAlgebra/Matrix.h
https://docs.opencv.org/3.4/d3/d63/classcv_1_1Mat.html
http://arma.sourceforge.net/docs.html#part_classes
or write your own and implement the basic functions directly.
Here is a simple function that will add a column to your matrix at a specified position:
void add_column(std::vector<std::vector<int>>& matrix,
const std::vector<int>& column, std::size_t position)
{
if(matrix.size() < position || position < 0) return; // check for position correctness
std::size_t index = 0;
for(auto& row : matrix){
row.insert(row.begin() + position, column[index++]);
}
}
For example, given a matrix:
std::vector<std::vector<int>> matrix;
and initializing it like so:
std::vector<int> column;
for (int i = 0; i < 3; i++) {
column.push_back(3);
}
for (int i = 0; i < 3; i++) {
matrix.push_back(column);
}
you end with with 3x3 matrix of 3s. Now, adding a column in between the first and the second one:
add_column(matrix, std::vector<int>({9, 9, 9}), 1);
and printing it:
for (auto& row : matrix) {
for (const auto x : row) {
std::cout << x << ' ';
}
std::cout << std::endl;
}
You end up with:
3 9 3 3
3 9 3 3
3 9 3 3
Related
Is there a simple way to sort matrix in c++ according to eg. first row, so that all elements rearrange accordingly?
Example:
int matrix[3][3] = { {5,2,4},
{1,7,8},
{9,2,6} };
After sorting by first row it would look like this:
{2,4,5},
{7,8,1},
{2,6,9}
Preferably, I'd like to use sort() function, and I don't mind using vectors if it would make the task easier.
As the comments said, it's easier to sort a matrix by a column than by a row, since std::sort with the use of a lambda function will do the job for the former.
My recommendation is to sort the column indices by the row, then use the sorted indices to rebuild the matrix:
#include <algorithm>
using namespace std;
const int n = 3; // size of matrix
int sort_by_row = 0; // row to sort by
int original[n][n] = { {5,2,4},
{1,7,8},
{9,2,6} };
int main() {
int col_indices[n];
for (int i = 0; i < n; i++) col_indices[i] = i; // create column indices 0...n-1
sort(col_indices, col_indices + n, [] (const int &a, const int &b) { // sort indices by row
return original[sort_by_row][a] < original[sort_by_row][b];
});
int sorted[n][n]; // rebuild matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
sorted[i][j] = original[i][col_indices[j]];
}
}
}
In this method, you iterate over the matrix once only, whereas if you transpose the matrix, sort, then transpose it back, you iterate over the matrix twice (during transposition).
I need to sort negative elements of matrix by scheme below. I've tried to sort from another corner, but it is not working too. I think, that I need to put elems of matrix in 1d array. It should be sorted in Cocktail sort, but sort's type not my main problem.
My code:
int main() {
const int n = 4, m = 4;
int t, v[n*m], arr[n][m], i, j, tmp, lt, rt;
lt = 0;
rt = t;
srand(time(NULL));
for (i = 0; i < n; i++) {
for(j=0; j < m; j++) {
arr[i][j] = rand() % 100 - 50;
}
cout << endl;
}
t = 0;
for (i = 0; i < n; i++) {
for(j = 0; j < m; j++) {
if (arr[i][j] < 0) {
v[t] = arr[i][j];
t++;
}
}
}
while(lt <= rt) {
for (i = rt; i >= lt; i--) {
if(v[i] > v[i-1]) {
swap(v[i], v[i-1]);
}
}
lt++;
for (i = lt; i <=rt; i++) {
if(v[i] > v[i-1]) {
swap(v[i], v[i-1]);
}
}
rt--;
}
for (i = 0; i < t; i++) {
cout << v[i] << " ";
}
int r = 0;
for (i = 0; i < n; i++) {
for(j = 0; j < m; j++) {
if(arr[i][j] < 0) {
arr[i][j] = v[r];
r++;
}
}
}
}
The question sounds easy, but it is not. There is a lot of “indirection” in it, where you need to work with indices instead of values.
I shortly checked you code. It is mostly C–Code (not C++) and buggy.
Example:
int t;
rt = t;
With that you have an uninitialized variable, used as an array index. That is a fatal bug. You are also using VLA’s (Variable Length Array). This is not allowed in C++. And you are using plain C-Style arrays. This you should not do. Use std::vector, which can grow dynamically or at least std::array instead. And please give your variable more meaningful names.
I will show you one (out of the many possible) solutions, but I will use C++.
The core of the problem at hand is to find the row and column indices of the elements in the given matrix. That is not easy.
But ok, let’s start with that. If you draw a picture with the matrix and then add dotted lines over the diagonals, then you see the indices.
If the dimension of the matrix is dim then there are always dim + dim – 1 diagonals. The diagonals have first a rising number of elements and after hitting the main, longest diagonal in the middle, decreasing number of elements. So we iterate over the number of all diagonals, split by the middle diagonal, and calculate the corresponding row and column indices. This is a bit tricky, but after some time you will find out.
The resulting row and column indices will be stored in a struct. All diagonals with all row and column indices will be stored in a vector of struct. Additionally, we add the values of the original matrix cells.
Regarding the sorting. It is obviously your task to develop an own sorting algorithm. For that purpose, I created a function yourSort where you can put in your own algorithm. I simply use standard algorithms (std::sort). You may replace std::sort by your own function.
In main I put some driver code. First, we create a matrix and fill it with random values. Then we calculate the row and column indices. The entries with the negative values will be extracted and sorted. Then we copy the result back to the original matrix.
As said above, not so easy, because of the indirection with the indices and the constraint to use only negative numbers.
But anyway. Please see:
#include <iostream>
#include <vector>
#include <utility>
#include <random>
#include <algorithm>
#include <iterator>
#include <iomanip>
// Create types that are easy to understand
using RowIndex = size_t;
using ColumnIndex = size_t;
// Here we store the position (row and column) and the value of one cell in the matrix
struct PositionAndValue {
// Constructors
PositionAndValue() {};
PositionAndValue(const RowIndex r, const ColumnIndex c, const int v) : rowIndex(r), columnIndex(c), value(v) {};
// Data
RowIndex rowIndex{};
ColumnIndex columnIndex{};
int value{};
};
// Main data types
using Columns = std::vector<int>;
using Matrix = std::vector<Columns>;
using Diagonal = std::vector<PositionAndValue>;
// Fill matrix with random values. Standard function
void fillMatrixRandom(Matrix& m) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(-50, 50);
std::for_each(m.begin(), m.end(), [&](Columns &c) {std::for_each(c.begin(), c.end(), [&](int &j) { j = dis(gen);}); });
}
// Calculate the indices for all diagonals
Diagonal calculateDiagonalIndices(const Matrix& matrix) {
// The return value
Diagonal diagonalIndices{};
// Matrix dimension
const size_t MatrixDimension{ matrix.size() };
// Overall number of diagonals for this matrix
const size_t NumberOfDiagonals{ MatrixDimension + MatrixDimension - 1 };
// index of middle (longest) diagonal
const size_t MiddleDiagonal { NumberOfDiagonals / 2 + 1 };
// Counter for element index in one specific diagonal
size_t elementInDiagonal{ 0 };
for (size_t diagonalIndex = 1; diagonalIndex <= NumberOfDiagonals; ++diagonalIndex) {
// If we are above the middle diagonal
if (diagonalIndex <= MiddleDiagonal) {
// Number of elements in diagonal will increase
++elementInDiagonal;
for (size_t j = 0; j < elementInDiagonal; ++j) {
// Calculate row and column and add to result
const RowIndex row{ j };
const ColumnIndex col{ diagonalIndex - j - 1 };
diagonalIndices.emplace_back(PositionAndValue(row, col, matrix[row][col]));
}
}
else {
// We are below the middle diagonal
// Number of elements in diagonal will decrease
--elementInDiagonal;
for (size_t j = 0; j < elementInDiagonal; ++j) {
// Calculate row and column and add to result
const RowIndex row{ diagonalIndex + j - MatrixDimension };
const ColumnIndex col{ MatrixDimension - j - 1 };
diagonalIndices.emplace_back(PositionAndValue(row, col, matrix[row][col]));
}
}
}
return diagonalIndices;
}
// Simple sorting function using std algorithms
template <typename T, typename ValueType>
void yourSort(std::vector<T>& vec, ValueType T::* mPtr) {
// We will extract the negative values
std::vector<ValueType> vt{};
// Extract
std::transform(vec.begin(), vec.end(), std::back_inserter(vt), [&](const T & s) {return s.*mPtr; });
// Sort. ***** Please put here your sorting function
std::sort(vt.begin(), vt.end());
// Put back
std::for_each(vec.begin(), vec.end(), [&, i = 0U](T& s) mutable{s.*mPtr = vt[i++]; });
}
// Driver code
int main() {
// Lets use a matrix of this size
constexpr size_t MatrixDimension = 4U;
// Small lambda for printing a matrix
auto printMatrix = [](const Matrix & m) {std::for_each(m.begin(), m.end(), [](const Columns & c) {
for (int i : c) std::cout << std::setw(4) << i; std::cout << "\n"; }); std::cout << "\n"; };
// Define a matrix and fill it with random values
Matrix matrix(MatrixDimension, Columns(MatrixDimension));
fillMatrixRandom(matrix);
printMatrix(matrix);
// Calulate the indices on the diagonals
Diagonal diagonal{ calculateDiagonalIndices(matrix) };
// Extract the negatives
Diagonal negativesOnDiagonal{};
std::copy_if(diagonal.begin(), diagonal.end(), std::back_inserter(negativesOnDiagonal),
[](const PositionAndValue & pv) { return pv.value < 0; });
// Sort
yourSort(negativesOnDiagonal, &PositionAndValue::value);
// Copy back
std::for_each(negativesOnDiagonal.begin(), negativesOnDiagonal.end(),
[&matrix](const PositionAndValue & pv) { matrix[pv.rowIndex][pv.columnIndex] = pv.value; });
printMatrix(matrix);
return 0;
}
I have a map of a room that I have put into a vector of vectors of characters (vector>). The map will look something like this:
# * #
* * D
S * #
where # are walls, * are path areas, S is the start and D is the end. I will not know what the map looks like ahead of time so I want my program to be able to read any map with similar characteristics to the one above.
Thus, I would like to be able to search my vector of vectors to find the coordinates/location of S, so I know where the starting point of the maze is. I have only been able to find examples for just a single vector (one-dimension). Is this possible to do with a vector of vectors (two-dimensions)? If so, how can I do it?
Here is the code I used to create the matrix:
vector<vector<char>> GetMap(int& M, int& N) //function to get the map of a room
{
vector<vector<char>> matrix{}; //give a matrix
char char_buf;
for (int rows = 0; rows < M; rows++)
{
matrix.push_back(vector<char>()); //Put a new empty row in your matrix
for (int cols = 0; cols < N; cols++)
{
cin >> char_buf; //Here we get a char from cin
matrix.back().push_back(char_buf); //That you push back in your sub-vector
}
}
return matrix;
}
First of all, your GetMap function is constantly pushing back new elements. That's a big no no when you already have the size of the matrix available to you (M and N). Also, there is really no need for the size parameters to be of type int&. A simple int is fine and, in most cases, even more efficient.
Rule of thumb: Only use references for non-basic types like vector, string and pretty much all classes.
Also, the fact that you use int& and not const int& doesn't allow you to call the function by passing rvalues (variables without names). For example GetMap(5, 5).
Now, to finally answer your question. Since you already have an idea on how to parse the whole matrix in your GetMap function. I really don't see the problem in creating a similar function that would get the position of a desired character.
The full working code with some enhancements:
#include <iostream>
#include <vector>
using namespace std;
struct Pos{
Pos() : x(0), y(0) {}
Pos(int x, int y) : x(x), y(y) {}
int x;
int y;
};
vector<vector<char>> GetMap(const int height, const int width) //function to get the map of a room
{
//Create the matrix with the constructor (much more efficent than constantly push_back'ing elements)
vector<vector<char>> matrix(height, vector<char>(width));
//Go through every single char in the matrix
for (int rows = 0; rows < height; rows++)
{
for (int cols = 0; cols < width; cols++)
{
cin >> matrix[rows][cols];
}
}
return matrix;
}
Pos getElementPos(const vector<vector<char>>& matrix, const char toFind)
{
int height = matrix.size();
int width = matrix[0].size();
//Go through every single char in the matrix
for (int rows = 0; rows < height; rows++)
{
for (int cols = 0; cols < width; cols++)
{
if(matrix[rows][cols] == toFind){
return Pos(cols, rows);
}
}
}
// In the event that we couldn't find the element
return Pos(-1, -1);
}
int main(){
vector<vector<char>> map = GetMap(5, 5);
Pos dPos = getElementPos(map, 'D');
cout << "\nThe coordinates of D are " << dPos.x << " and " << dPos.y << '\n';
return 0;
}
I'm trying to fill 2D vector in C++ with characters, but when I run this code it ends with one line characters (*..).
How can I fill 2D vector like this:
*.*
.**
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<char> > vec2D;
std::vector<char> rowV;
unsigned int row=2;
unsigned int col=3;
char c;
unsigned int temp=0;
while(temp!=col)
{
while(rowV.size()!=row)
{
std::cin>>c;
rowV.push_back(c);
}
vec2D.push_back(rowV);
++temp;
}
return 0;
}
You should clear rowV after each insertion, otherwise it will be full and no other characters will be added. Also, row should be swapped by col and vice-versa, otherwise you will get a 3x2 (and not 2x3) 2D vector.
while(temp!=row)
{
while(rowV.size()!=col)
{
std::cin>>c;
rowV.push_back(c);
}
vec2D.push_back(rowV);
rowV.clear(); // clear after inserting
++temp;
}
It helps to know what [pushing back a 2DVector with an empty 1D vector] looks like.
See the example below.
#include <algorithm>
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;
//-v-----A FUNCTION TO PRINT 2D VECTORS
template<typename T> //We don't know what type the elements are yet, so we use a template
void printVec2D(vector<vector<T>> a) // a is the name of our input 2Dvector of type (T)
{
for (int i = 0; i < a.size(); i++) {// a.size() will equal the number of rows (i suppose rows/columns can depend on how you look at it)
for (int j = 0; j < a[i].size(); j++) {// a[i].size() is the size of the i'th row (which equals the number of columns, foro a square array)
std::cout << a[i][j] << "\t";
}
std::cout << "\n";
}
return;
}
//-^--------
int main()
{
int X = 3; int Y = 3;
int VectorAsArray[3][3] = {{1,2,3},
{14,15,16},
{107,108,109}};
vector<vector<int>> T;
for (int i = 0; i < X; i++)
{
T.push_back({});// We insert a blank row until there are X rows
for (int j = 0; j < Y; j++)
{
T[i].push_back(VectorAsArray[i][j]); //Within the j'th row, we insert the element corresponding to the i'th column
}
}
printVec2D(T);
//system("pause"); //<- I know that this command works on Windows, but unsure otherwise( it is just a way to pause the program)
return 0;
}
I'm having trouble creating a Matrix using Vectors. The rows and columns will all be random doubles and I am trying to fill it in.
I have tried to initialize the size of the vector before hand, I believe it initializes correctly, however, when I try to push onto the rows and columns I get very odd output. Here is my Header File:
#ifndef MATRIX_NORM_HPP
#define MATRIX_NORM_HPP
#include <vector>
class MatrixNorm
{
public:
void initProgram();
void printResults();
double randNumber();
private:
std::vector<std::vector<double>> M;
double mNorm1 = 0.0;
double mNormInf = 0.0;
};
#endif
Here is my CPP File:
#include "matrixNorm.hpp"
#include <iostream>
#include <random>
void initProgram()
{
double ranNum = 0.0;
int size = 0;
std::cout << "Please enter a size of an n by n Matrix: ";
std::cin >> size;
std::vector<std::vector<double>> temp(size, std::vector<double>(size));
for(int i = 0; i < size; ++i)
{
for(int j = 0; j < size; ++j)
{
ranNum = randNumber();
temp[i].push_back(ranNum);
temp[j].push_back(ranNum);
}
}
M = temp;
printResults();
}
void MatrixNorm::printResults()
{
for(auto &&e: M)
{
for(auto && f: e)
{
std::cout << f << " ";
}
std::cout << std::endl;
}
}
double MatrixNorm::randNumber()
{
double ranDouble = 0.0;
std::random_device rd;
std::default_random_engine generator(rd());
std::uniform_real_distribution<double> unif(-1000.0,1000.0);
ranDouble = unif(generator);
return ranDouble;
}
The output I receive when I run the program from main.cpp is:
Please enter a size of an n by n Matrix: 3
0 0 0 792.208 792.208 -361.248 -776.871 742.521 116.732
0 0 0 -361.248 742.521 411.965 411.965 909.313 -50.0048
0 0 0 -776.871 909.313 116.732 -50.0048 79.6189 79.6189
As you can see, it seems to get the column size correctly, but it does not get the row size correctly, and if you look very closely. Some of the numbers are duplicates, I wish I knew how to format it more clearly but if you start at the top left you see 792.208 792.208 then go down a row and you see 411.965 411.965 and last it finishes off at 79.6189 79.6189 in the lower right.
What am I doing wrong? How do I do this correctly? Any help would be appreciated.
Seems to me that the correct way to initialize your matrix is:
(...)
std::vector<std::vector<double>> temp;
for(int i = 0; i < size; ++i)
{
std::vector<double> k;
for(int j = 0; j < size; ++j)
{
ranNum = randNumber();
k.emplace_back(ranNum);
}
temp.emplace_back(k);
}
(...)
Explanation:
with this constructor:
std::vector<std::vector<double>> temp(size, std::vector<double>(size));
you are creating size copies of default vector constructed of size elements (std::vector<double>(size)). In other words, you have a size x size matrix.
So, instead of pushing new values in your code, you should be changing it. In the code I proposed, it is just simpler to populated this matrix when you are creating it.