Image Editor and Vector dimensions C++ - c++

I'm working on a basic image editor using vectors and I'm trying to get a matrix like the one shown below, a 4 by 4 but with each slot containing 3 values (RGB values)
0 0 0 100 0 0 0 0 0 255 0 255
0 0 0 0 255 175 0 0 0 0 0 0
0 0 0 0 0 0 0 15 175 0 0 0
255 0 255 0 0 0 0 0 0 255 255 255
So far I've been able to get a matrix put in with this code (I think..)
int rows;
int columns;
fin >> rows;
fin >> columns;
vector<vector<int> > image_dimensions(rows);
for (int i = 0; i < rows; i++)
image_dimensions[i].resize(columns);
This is only to create a matrix full of 0s. How can I make each slot contain three RGB values like the example showed? Finally, what complicated loop would I have to use to be able to change the individual values in each slot, like turning 0 0 0 into 155 0 255 for example?

At the moment you use the primitive integer type. Consider to store some more complex like a RGB class:
class RGB {
private:
std::unit8_t r, g, b;
public:
RGB() {}
RGB(int r, int g, int b) : r(r), g(g), b(b){ }
}
You can simple construct objects with:
rgb = RGB(255,255,255);
After that you can store the objects in your vector.
int rows;
int columns;
fin >> rows;
fin >> columns;
vector<vector<RGB> > image_dimensions(rows);
for (int i = 0; i < rows; i++)
image_dimensions[i].resize(columns);
The difference to your example is, that the vector can store objects from the class RGB. If you like you can now iterate through the vector:
for (int i = 0; i < columns; i++)
for (int i = 0; i < rows; i++)
image_dimensions[i][j] = RGB(0,0,0);
edit:
based on the comment, it is probably better to not waste space and use the the uint8 type. So there is no more need for the verification.
And you could use a flat vector and calculate the 2d index. If you work with big matrices this will be generate a more efficient solution.
edit2:
A second possible solution without creating a new class is to use the std tuple class:
std::tuple<std::unit8_t, std::unit8_t, std::unit8_t > rgb(0,0,0);
In this case your vector have to store this kind of tuple.
More tuple informations: klick
By the way: creating a little class or structure should not disturb you. ;-)

Related

How to resize 2d vector

#include <iostream>
#include <vector>
using namespace std;
int main(void)
{
vector<vector<int> > matrix;
matrix.resize(3, vector<int>(4, 1));
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 4; j++)
{
cout << matrix[i][j];
}
cout << endl;
}
matrix.resize(5, vector<int>(7, 0));
for (size_t i = 0; i < 5; i++)
{
for (size_t j = 0; j < 7; j++)
{
cout << matrix[i][j];
}
cout << endl;
}
return 0;
}
'''
As far as I know, when we are resizing a vector using "resize()" over than original capacity, values in original space will remain and new values are assigned to new space.
In the line matrix.resize(5, vector(7, 0)); If we execute that line I thought matrix would be like
1111000
1111000
1111000
0000000
0000000
something like this.
But the programs stops,
I want to know why it won't working.
matrix.resize(5, vector<int>(7, 0));
only add new vector of size 7 not modifying actual vector.
Just resize actual vectors to 7 with:
for (auto &row: matrix) row.resize(7);
so now is working:
1111000
1111000
1111000
0000000
0000000
i tested your codes using an online compiler https://onlinegdb.com/BkwcGuAAD
your columns are not resized (only the rows are resized). running your current code yields
1 1 1 1 0 0 33
1 1 1 1 0 0 33
1 1 1 1 0 0 49 << notice some columns have random numbers?
0 0 0 0 0 0 0
0 0 0 0 0 0 0
try resizing the columns too
matrix[0].resize(7,0);
matrix[1].resize(7,0);
matrix[2].resize(7,0);
matrix.resize(5, vector<int>(7, 0));
you should get something like the following
1 1 1 1 0 0 0
1 1 1 1 0 0 0
1 1 1 1 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
By the C++ Reference
(http://www.cplusplus.com/reference/vector/vector/resize/)
void resize (size_type n);
void resize (size_type n, const value_type& val);
Resizes the container so that it contains n elements.
If n is smaller than the current container size, the content is reduced to its first n elements, removing those beyond (and destroying them).
If n is greater than the current container size, the content is expanded by inserting at the end as many elements as needed to reach a size of n. If val is specified, the new elements are initialized as copies of val, otherwise, they are value-initialized.
If n is also greater than the current container capacity, an automatic reallocation of the allocated storage space takes place.
Notice that this function changes the actual content of the container by inserting or erasing elements from it.
I thought Compiler will understand if I put more longer vector inside of "val".
That is, I thought it would understand this kind of increased "n".
But Compiler will only watch whether "n" parameter itself is changed or not.
Because of this reason, my code wouldn't work properly.
if you want to increase size of vector using size() function, note that you should resize original row values on your hand.

Creating 2-D Boolean Vector with False value

i want too create a 2-D vector of Boolean type with Size n x n . but i don't want to use two for loop to assign false to every index instead of assign directly while creating this vector.
syntax is:- vector<vector<bool>> V(n,false)
but it gives me error
There is a constructor that takes a count and an element, but false is not a std::vector<bool>. You want
std::vector<std::vector<bool>> V(n, std::vector<bool>(n,false) );
// |---- inner vectors ----|
Two disclaimer:
Use std::vector<bool> with caution. It is not like other std::vectors (see eg Alternative to vector<bool>).
A vector of vectors is rarely the best data structure. The power of a std::vector is its data locality, however a std::vector<std::vector<T>> does not have this feature (only elements of the inner vectors are contiguous).
vector<vector> V(n,false) this gives an error because you are not declaring size of each v[i] thus, it can not assign each of v[i][j] to false.
you can use vector<vector> v(n, vector (n, false));
Code:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
vector<vector<bool>> v(n, vector<bool> (n, false));
for(int i=0;i<n;i++)
{
for(int j=0;j<v[i].size();j++)
{
cout<<v[i][j]<<" ";
}
cout<<'\n';
}
}
Ans:
n=5
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

Finding boundaries of figure in 2d array

There is a figure that is represented by 1 values that are “connected” vertically, horizontally or diagonally in a 2 dementional array.
I need to save the index of the boundary of the figure (the row and column of the 0's that are connected to the figure, in any type of c++ container.
For instance, in the following 2d array, I should get the following indexes:
(0,2), (0,3), (0,4), (1,2), (1,4), (1,5), (2,2), (2,3), (2,5), (2,6)... etc.
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 1 1 1 0 0
0 0 0 0 1 1 0 0
0 0 0 1 1 1 0 0
0 0 0 1 1 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
What is the most efficient way to do so, on both space and time complexity?
void dfs(vector<vector<int>>& matrix, vector<vector<int>>& boundary, int rows, int cols, int i, int j){
if(!isValidCoordinate(i, j))
return;
if(isAnyNeighborOne(i, j)){
boundary.push_back({i, j});
matrix[i][j] = 2;
}
else
matrix[i][j] = 3;
//Explore eight directions
/* I didn't bother about x = 0 and y = 0.
* You can, if you want.
* Doesn't make a difference though.
*/
for(int x = -1; x < 2; x++){
for(int y = -1; y < 2; y++){
dfs(matrix, boundary, rows, cols, i + x, i + y);
}
}
}
vector<vector<int>> getBoundary(vector<vector<int>>& matrix){
vector<vector<int>> boundary;
int rows = matrix.size();
if(!rows)
return boundary;
int cols = matrix[0].size();
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
if(matrix[i][j] == 0){
dfs(matrix, boundary, rows, cols, i, j);
}
}
}
return boundary;
}
If you print the matrix at the end, you'll see the boundary with 2.
Whatever you see as 3, if you want, you can set it back to 0.
isValidCoordinate() and isAnyNeighborOne() is left to you as an exercise.
I use vector<vector<int>> for boundary. You can try using vector<pair<int,int>> as well.
With the above solution you'll get inner boundary as well as outer boundary. As an exercise, you can try only inner boundary or only outer boundary.
You can solve the same problem with BFS as well. If the matrix is of large size, stack might overflow due to recursive calls. Better to prefer BFS in such cases.
Time and space complexity of the above solution is O(rows * cols).

How to generate this matrix with armadillo in c++?

I would like to generate a matrix in C ++ using armadillo that behaves like a "truth table", for example:
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
I was thinking of a cycle of this kind, but I'm not very practical with armadillo and its data structures.
imat A = zeros<imat>(8, 3);
/* fill each row */
for(int i=0; i < 8; i++)
{
A.row(i) = (i/(pow(2, i)))%2 * ones<ivec>(3).t(); //
}
cout << "A = \n" << A << endl;
Any ideas?
If you need a large size truth table matrix (~2^30 x 30) as you said here, from the memory point of view, you should implement a function which quickly calculates the values you want rather than storing them on a matrix.
This is easily done using std::bitset as follows.
Note that N must be determined at compile-time in this method.
Then you can get the value of your A(i,j) by matrix<3>(i,j):
DEMO
#include <bitset>
template <std::size_t N>
std::size_t matrix(std::size_t i, std::size_t j)
{
return std::bitset<N>(i)[N-j-1];
}

How to create undirected graph out of adjancency matrix?

Hello everywhere there is an explanation by drawings hot to create graph out of adj. matrix. However, i need simple pseudo code or algorithym for that .... I know how to draw it out of adj. matrix and dont know why nobody no where explains how to actually put it in code. I dont mean actual code but at least algorithm ... Many say .. 1 is if there is an edge i know that.. I have created the adj. matrix and dont know how to transfer it to graph. My vertices dont have names they are just indexes of the matrix. for example 1-9 are the "names of my matrix"
1 2 3 4 5 6 7 8 9
1 0 1 0 0 1 0 0 0 0
2 1 0 1 0 0 0 0 0 0
3 0 1 0 1 0 0 0 0 0
4 0 0 1 0 0 1 0 0 0
5 1 0 0 0 0 0 1 0 0
6 0 0 0 1 0 0 0 0 1
7 0 0 0 0 1 0 0 1 0
8 0 0 0 0 0 0 1 0 0
9 0 0 0 0 0 1 0 0 0
that was originaly a maze ... have to mark row1 col4 as start and row7 col8 end ...
Nobody ever told me how to implement graph out of matrix (without pen) :Pp
thanks
Nature of symmetry
Adjancency matrix is a representation of a graph. For undirected graph, its matrix is symmetrical. For instance, if there is an edge from vertex i to vertex j, there must also be an edge from vertex j to vertex i. That is the same edge actually.
*
*
* A'
A *
*
*
Algorithm
Noticing this nature, you can implement your algorithm as simple as:
void drawGraph(vertices[nRows][nCols])
{
for (unsigned int i = 0; i < nRows; ++i)
{
for (unsigned int j = i; j < nCols; ++j)
{
drawLine(i, j);
}
}
}
You can convert a graph from an adjacency matrix representation to a node-based representation like this:
#include <iostream>
#include <vector>
using namespace std;
const int adjmatrix[9][9] = {
{0,1,0,0,1,0,0,0,0},
{1,0,1,0,0,0,0,0,0},
{0,1,0,1,0,0,0,0,0},
{0,0,1,0,0,1,0,0,0},
{1,0,0,0,0,0,1,0,0},
{0,0,0,1,0,0,0,0,1},
{0,0,0,0,1,0,0,1,0},
{0,0,0,0,0,0,1,0,0},
{0,0,0,0,0,1,0,0,0}
};
struct Node {
vector<Node*> neighbours;
/* optional additional node information */
};
int main (int argc, char const *argv[])
{
/* initialize nodes */
vector<Node> nodes(9);
/* add pointers to neighbouring nodes */
int i,j;
for (i=0;i<9;++i) {
for (j=0;j<9;++j) {
if (adjmatrix[i][j]==0) continue;
nodes[i].neighbours.push_back(&nodes[j]);
}
}
/* print number of neighbours */
for (i=0;i<9;++i) {
cout << "Node " << i
<< " has " << nodes[i].neighbours.size() <<" outbound edges." << endl;
}
return 0;
}
Here, the graph is represented as an array of nodes with pointers to reachable neighbouring nodes. After setting up the nodes and their neighbour pointers you use this data structure to perform the graph algorithms you want, in this (trivial) example print out the number of outbound directed edges each node has.