I have faced this C++ problem:
In numerical analysis and scientific computing, a sparse matrix or sparse array is a matrix in which most of the elements are zero. There is no strict definition how many elements need to be zero for a matrix to be considered sparse but a common criterion is that the number of non-zero elements is roughly the number of rows or columns. By contrast, if most of the elements are nonzero, then the matrix is considered dense. The number of zero-valued elements divided by the total number of elements (e.g., m × n for an m × n matrix) is sometimes referred to as the sparsity of the matrix.
Write a class for storing a sparse matrix. Your class should support matrix sizes up to 1million x 1million.
Your class should be able to do any of the following:
A. Generate a random sparse matrix
B. Have the ability for an input matrix to be specified by a programmer
C. Compute the sparsity of a matrix
D. Rotate the matrix
I did research on the matter. I found this approach:
A proper way to create a matrix in c++
but I a doubt this would work because the shear size requirement (1M x 1M) in the problem.
Another approach I found using maps:
What is the best way to create a sparse array in C++?
but it is not quite what I need and I am unsure whether the (1M x 1M) requirement is met. Not sure how to approach part B as well. Also the the map is not encapsulated in the class.
I am interested in learning how to do this. This is not a school project or anything. This was an interview question that I failed to find the answer for.
Edit: Here's my implementation. Although I need to improve on it as it crashes right now if I specify a matrix size of 1Mx1M. I need to make it store only non-zero values.
Your feedback on the implementation is appreciated.
HEADER:
#ifndef SPARSEMATRIX_H
#define SPARSEMATRIX_H
#include <map>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
class SparseMatrix
{
public:
// Default constructor
SparseMatrix(unsigned int r, unsigned int c);
// Constructor that takes a 2D vector
SparseMatrix(std::vector<std::vector<int>> matrix);
// Deconstructor
~SparseMatrix();
// Print all matrix elements on console
void printMatrix();
// Return the sparsity
float computeSparsity();
// Rotate matrix by 90 degrees clockwise
void rotate90Clockwise();
// Return the element at the specified indices
int at(unsigned int rIndex, unsigned int cIndex);
private:
// Number of rows for the matrix
unsigned int rows;
// Number of columns for the matrix
unsigned int cols;
// Holds the number of zero-value elements in matrix
unsigned int zeroCounter;
// Map to hold the matrix in key-value fashion
std::map<std::string,int> data;
};
#endif // SPARSEMATRIX_H
SOURCE:
#include "sparsematrix.h"
#define MAX_SIZE (unsigned int) 1000000
#define MIN_SIZE (unsigned int) 1
SparseMatrix::SparseMatrix( unsigned int r, unsigned int c )
{
// Acquire the size required for the matrix
rows = r;
cols = c;
zeroCounter = 0;
// Check if the desired matrix is within design limit (1Mx1M elements)
if( rows > MAX_SIZE || rows < MIN_SIZE || cols > MAX_SIZE || cols < MIN_SIZE )
throw std::out_of_range("Matrix is out of range");
// Loop to generate random values and store in map
for( unsigned int i = 0; i < rows; ++i )
{
for( unsigned int j = 0; j < cols; ++j )
{
std::string key = std::to_string(i) + "," + std::to_string(j);
// Generate random value
unsigned int value = rand() % 10;
// Keep count of zero value elements
if( value == 0 ) zeroCounter++;
// Store value in map
data[key] = value;
}
}
}
SparseMatrix::SparseMatrix(std::vector<std::vector<int> > matrix)
{
unsigned int colNum = 0;
// Compute max column length
for (unsigned int i = 0; i < matrix.size(); ++i)
{
colNum = std::max( { colNum, matrix[i].size() } );
}
// Loop to transfer the elements from vector to map
// Fill all non existent elements with zero value
for (unsigned int i = 0; i < matrix.size(); ++i)
{
for (unsigned int j = 0; j < colNum; ++j)
{
std::string key = std::to_string(i) + "," + std::to_string(j);
unsigned int value;
if( j < matrix[i].size() )
{
// Element exists
value = matrix[i][j];
}
else
{
// Element does not exist; fill with zero
value = 0;
}
// Keep count of zero value elements
if( value == 0 ) zeroCounter++;
// Store value in map
data[key] = value;
}
}
}
SparseMatrix::~SparseMatrix()
{
// Matrix deconstructor
}
void SparseMatrix::printMatrix()
{
// Print all matrix elements on console
for(auto elem : data)
{
std::cout << elem.first << " " << elem.second << std::endl;
}
std::cout << " " << std::endl;
}
float SparseMatrix::computeSparsity()
{
// Return the calculated sparsity
return ((float)zeroCounter/(rows*cols));
}
void SparseMatrix::rotate90Clockwise()
{
std::map<std::string,int> temp;
std::string oldKey;
std::string newKey;
//Transpose matrix first
for(unsigned int r = 0; r < rows; r++)
{
for(unsigned int c = r; c < cols; c++)
{
oldKey = std::to_string(r) + "," + std::to_string(c);
newKey = std::to_string(c) + "," + std::to_string(r);
temp[newKey] = data[oldKey];
if( oldKey != newKey && data.count(newKey))
temp[oldKey] = data[newKey];
}
}
// Assign the temp map to our data map
data = temp;
// Matrix is transposed now so rows and cols should be swaped
std::swap(rows, cols);
// Reverse elements of matrix on row order
for(unsigned int r = 0; r < rows; r++)
{
for(unsigned int c =0; c < cols/2; c++)
{
oldKey = std::to_string(r) + "," + std::to_string(c);
newKey = std::to_string(r) + "," + std::to_string(cols-c-1);
data[newKey] = temp[oldKey];
if( oldKey != newKey && temp.count(newKey))
data[oldKey] = temp[newKey];
}
}
}
int SparseMatrix::at(unsigned int rIndex, unsigned int cIndex)
{
// Check if the requested element is within matrix range
if( rIndex >= rows || cIndex >= cols )
throw std::out_of_range("Indices out of range");
// Construct key for the requested element
std::string key = std::to_string(rIndex) + "," + std::to_string(cIndex);
// Return element at key
return data[key];
}
Related
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 sorting 2 vectors using a vector of index.
the 2 vectors have not the same size. One vector (keys) is size X and the other (descriptors) is size X*128 (one key is parametrized by 128 values).
In order to create the vector of index, I generated a vector of unsigned, and used the iota function to put in this vector [0,1,2,...,X]
then I use the sort function to sort these index depending scale of a key (keys[i].s).
After that, I generate another vector in which I copy the values using the vector of index for both descriptors and keys (calling them descriptors_tmp, and keys_tmp), and then I want to make the first keys vector equal to the keys_tmp, and the same for descriptors equals to descriptors_tmp.
My question are :
-Is there a way to make that without making any copy. Since I don't need the previous version of keys and descriptors, I could just make the vector point on the other vector (something like *keys = *keys_tmp) ?
-Is there an easier way to achieve what I'm trying to achieve?
My code :
void _siftMatch::getIdxOfSorting(std::vector<unsigned>& idx_scale_order)
{
//keys[i].s is the scale and I sort depending decreasing scale
auto cmp_scale = [this](int i, int j) {
return keys[i].s > keys[j].s;
};
std::sort(idx_scale_order.begin(), idx_scale_order.end(), cmp_scale);
}
void _siftMatch::sort() {
//vector containing the index of sorted
std::vector<unsigned>idx_scale_order;
idx_scale_order.resize(keys.size());
//Generate [0,1,...,X]
std::iota(idx_scale_order.begin(), idx_scale_order.end(), 0);
//Sort the vector
getIdxOfSorting(idx_scale_order);
std::vector<float> descriptors_tmp;
std::vector<SiftGPU::SiftKeypoint> keys_tmp;
for (int i = 0; i < idx_scale_order.size(); ++i) {
keys_tmp.push_back(keys[idx_scale_order[i]]);
for (int j = 0; j < 128; ++j)
descriptors_tmp.push_back(descriptors[idx_scale_order[i] * 128 + j]);
}
//This is here that I want to put descriptors_tmp and keys_tmp in descriptors and keys
//descriptors.swap(descriptors_tmp.data);
}
Is there a way to make that without making any copy
This example of sorting 3 arrays according to one of the arrays, using a 4th generated array of indices that are sorted according to one of the 3 arrays may help. The key part of this is the in place reordering of all 4 arrays according to the array of indices. You'll need to modify this for your situation. I'm not sure why you are converting the array of indices to an array of numeric strings (via the itoa calls), using the indices directly works better for the example in this answer.
// sort 3 vectors according to one of them
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
int main()
{
std::vector <int> A; // ages
std::vector <std::string> N; // names
std::vector <int> Z; // zip codes
std::vector <size_t> I; // indices
int tA;
std::string tN;
int tZ;
A.push_back(37);
N.push_back("Ted");
Z.push_back(54211);
A.push_back(21);
N.push_back("John");
Z.push_back(53421);
A.push_back(31);
N.push_back("Fred");
Z.push_back(52422);
A.push_back(21);
N.push_back("Sam");
Z.push_back(51422);
// display the vectors
for(size_t i = 0; i < A.size(); i++)
std::cout << std::setw(6) << N[i]
<< std::setw(8) << Z[i]
<< std::setw(4) << A[i] << std::endl;
std::cout << std::endl;
// initialize the vector of indices
for(size_t i = 0; i < A.size(); i++)
I.push_back(i);
// sort I according to A
std::stable_sort(I.begin(), I.end(),
[&A](size_t i, size_t j) {return
A[i] < A[j];});
// reorder A, N, Z in place also restore I
// time complexity is O(n)
for(size_t i = 0; i < A.size(); i++){
size_t j, k;
if(i != I[i]){
tA = A[i];
tN = N[i];
tZ = Z[i];
k = i;
while(i != (j = I[k])){
A[k] = A[j];
N[k] = N[j];
Z[k] = Z[j];
I[k] = k;
k = j;
}
A[k] = tA;
N[k] = tN;
Z[k] = tZ;
I[k] = k;
}
}
// display the sorted vectors
for(size_t i = 0; i < A.size(); i++)
std::cout << std::setw(6) << N[i]
<< std::setw(8) << Z[i]
<< std::setw(4) << A[i] << std::endl;
return 0;
}
#include <iostream>
using namespace std;
int main() {
int n,d,i=0,temp;
cin>>n>>d;
int a[1000000];
for(i=0;i<n;i++){
cin>>a[i];
}
while(d--){
temp=a[0];
for(i=1;i<n;i++){
a[i-1]=a[i];}
a[n-1]=temp;
}
for(i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
how to optimize it further as it's giving TLE error. the input file is very large obviously.
Some suggestions:
Rotate by the full amount d in a single loop (note that the result is a different array b):
for (i = 0; i < n; i++) {
b[(i+n-d) % n]=a[i];
}
Don't touch the array at all but transform the index when accessing it, for example:
cout << a[(i+n-d) % n] << " ";
The second version requires extra calculation to be done whenever accessing an array element but it should be faster if you don't need to access all array elements after each rotate operation.
There is also a way to do the rotation in-place by using a helper function that reverses a range of the array. It's a bit odd but might be the best solution. For convenience I have used a std::vector instead of an array here:
void ReverseVector( std::vector<int>& a, int from, int to ) {
for (auto i = 0; i < (to - from) / 2; i++) {
auto tmp = a[from + i];
a[from + i] = a[to - i];
a[to-i] = tmp;
}
}
void RotateVector( std::vector<int>& a, int distance ) {
distance = (distance + a.size()) % a.size();
ReverseVector( a, 0, a.size() - 1 );
ReverseVector( a, 0, distance - 1 );
ReverseVector( a, distance, a.size() - 1 );
}
I have a matrix of values (stored as an array of values) and a vector with the matrix dimensions( dims[d0, d1, d2]).
I need to build a string like that:
"matA(j, k, l) = x;"
where j, k, l are the indices of the matrix and x the value of the element. I need to write this for each value of the matrix and for matrices with 2 to n dimensions.
I have a problem isolating the base case and replicating it in a useful way. I did a version in a switch case with a case for each dimension and a number of for cycles equal to the number of dimensions:
for (unsigned int k=1; k<=(dims[2]); k++)
{
for (unsigned int j=1; j<=(dims[1]); j++)
{
for (unsigned int i=1; i<=(dims[0]); i++)
{
strs << matName << "(" << i << "," << j << ","<< k << ")="<< tmp[t]<< "; ";
....
but is not what I wanted.. Any idea for a more general case with a variable number of dimensions?
You need a separate worker function to recursively generate the series of indices and main function which operates on it.
For example something like
void worker(stringstream& strs, int[] dims, int dims_size, int step) {
if (step < dims_size) {
... // Add dims[step] to stringstream. Another if may be necessary for
... // whether include `,` or not
worker(strs, dims, dims_size, step + 1);
} else {
... // Add cell value to stringstream.
}
}
string create_matrix_string(int[] dims, int dims_size, int* matrix) {
... // Create stringstream, etc.
strs << ... // Add matrix name etc.
worker(strs, dims, dims_size, 0);
strs << ... // Add ending `;` etc.
}
The main problem here is the value, since the dimension is not known during compilation. You can avoid that by encoding matrix in single-dimensional table (well, that's what C++ is doing anyway for static multidimensional tables) and call it using manually computed index, eg. i + i * j (for two-dimensional table). You can do it, again, by passing an accumulated value recursively and using it in final step (which I omitted in example above). And you probably have to pass two of them (running sum of polynomial components, and the i * j * k * ... * x product for indices from steps done so far.
So, the code above is far from completion (and cleanliness), but I hope the idea is clear.
You can solve this, by doing i, j and k in a container of the size of dim[] - sample:
#include <iostream>
#include <vector>
template< typename Itr >
bool increment( std::vector< int >& ijk, Itr idim, int start )
{
for( auto i = begin(ijk); i != end(ijk); ++i, ++idim )
{
if( ++*i <= *idim )
return true;
*i = start;
}
return false;
}
int main()
{
using namespace std;
int dim[] = { 5, 7, 2, 3 };
const int start = 1;
vector< int > ijk( sizeof(dim)/sizeof(*dim), start );
for( bool inc_done = true; inc_done
; inc_done = increment( ijk, begin(dim), start ) )
{
// .. here make what you want to make with ijk
cout << "(";
bool first = true;
for( auto j = begin(ijk); j != end(ijk); ++j )
{
if( !first )
cout << ",";
else
first = false;
cout << *j;
}
cout << ")= tmp[t] " << endl;
}
return 0;
}