Creating a "#" border outside my 2d array - c++

Hi I'm currently trying to create a border for my dynamic 2D array, I managed to create the left and right side border of my 2d array grid. But I currently have trouble figuring out on how to do it for the top and bottom side of the 2d array grid.
Is the method I'm currently trying a good way to achieve this? Any help or suggestion would be greatly appreciated thanks!
void displayCity(int minX, int maxX, int minY, int maxY)
{
//Allocate the array.
int** twod = new int* [maxX];
for (int i = 0; i < maxX; i++)
{
twod[i] = new int[maxY];
}
for (int i = 0; i< maxX; ++i)
{
cout << '#';
for (int j = 0; j < maxY; ++j)
{
twod[i][j] = 0;
cout << twod[i][j] << ' ';
}
cout << setw(1) << '#';
cout << endl;
}
//Deallocate the array.
for (int i = 0; i < maxX; ++i)
{
delete[] twod[i];
}
delete[] twod;
}
This is my current output.
#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 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 #
#0 0 0 0 0 0 0 0 #

Don't use "new/delete" unless you really need to. (C++ core guidelines).
Instead rely on datastructures from stl, like std::vector (for dynamically allocated arrays). For example like this :
#include <vector>
#include <iostream>
#include <string>
// City class to hold city data (but not to render it).
class City
{
public:
City(std::size_t width, std::size_t height) :
m_width{ width },
m_height{ height },
m_city_blocks(height,std::vector<int>(width))
{
}
const auto& city_blocks() const noexcept
{
return m_city_blocks;
}
const auto width() const noexcept
{
return m_width;
}
const auto height() const noexcept
{
return m_height;
}
private:
std::size_t m_width;
std::size_t m_height;
// dynamically allocated arrays are best handled by vector
// not by using new (new/delete are no longer recommended)
// use STL containers or std::make_unique
std::vector<std::vector<int>> m_city_blocks;
};
// Seperate class for rendering cities
class Renderer
{
public:
void ShowCity(const City& city)
{
// make a string with enougn '#' to draw bottom and top line
std::string border(2ul * city.width() + 3ul, '#');
// output to screen
std::cout << border << "\n";
// loop over all rows in the city's blocks using a range based for loop
// use const since rendering should not modify the state of the city blocks
// only show them.
for (const auto& row : city.city_blocks())
{
std::cout << "# ";
// loop over all values and display them
for (const auto& value : row)
{
std::cout << value << " ";
}
std::cout << "#\n";
}
std::cout << border << "\n";
}
};
int main()
{
// make a 5*5 city
City city{ 5ul,5ul };
// create a renderer to display the city
Renderer renderer;
renderer.ShowCity(city);
return 0;
}

Your way of drawing the border is rather inflexible because you mix the data, and formatting and output of the data with formatting and output of the border.
Also your borders are not straight lines when the numbers have different number of digits.
I suggest you to first gather all the output to be printed inside borders, then inspect it to see how many lines there are and how long the lines are. Then you know where to print the border:
#include <sstream>
#include <iomanip>
#include <vector>
#include <iostream>
void print_with_border(std::stringstream& str,char border='#') {
std::vector<std::string> output;
size_t max_len = 0;
std::string line;
while(std::getline(str,line)) {
output.push_back(line);
max_len = std::max(max_len,line.size());
}
std::cout << std::string(max_len+4,border) << "\n";
for (const auto& l : output) {
std::cout << border << " " << std::setw(max_len) << std::left << l << " " << border << "\n";
}
std::cout << std::string(max_len+4,border) << "\n";
}
int main() {
std::stringstream ss;
ss <<"hello \n world";
print_with_border(ss);
}
Output:
##########
# hello #
# world #
##########
To print contents of a 2d array you just have to pipe the contents of the array with desired formatting into a stringstream.

Related

Compress a 2D array into a 1D Array

i have a quad (2D array) which is composed of numbers which ranges from 0 to 255
and the most frequent value of the array ( in my case 2) is the background value
i have to put all the values of the array except the background value ( i have to ignore all cases that contains a 2) in a 1D array with this arrangement
the line,the column,the value,the line,the next column,the next value
for example i have
{2,3,2,2},
{2,2,2,2},
in the 1D array it will be like { 1,2,3,}
i added spaces to make it more readable
here is my array
int image1[MAXL][MAXC]=
{
{2,3,2,2},
{2,2,2,2},
{2,255,2,2},
{255,2,2,2},
{2,255,2,2}
};
and the loop
for (int i = 0; i<nbc;i++)
{
for (int j=0; j<nbl;j++)
{
if (image1[j][i]==BackColor)
{
}
else
}
}
nbc and nbl are respectively the number of columns and lines
thanks you for your help
EDIT : i completely failed my example i didn't ignored the 2, should be fine now
A simple approach using std::vector
std::vector<int> result;
for (int i = 0; i<MAXL;i++)
{
for (int j=0; j<MAXC;j++)
{
if (image1[i][j] != BackColor) // Notice !=
{
result.push_back(i+1);
result.push_back(j+1);
result.push_back(image1[i][j]);
}
}
}
for (auto x : result)
{
std::cout << x << " ";
}
std::cout << endl;
Output:
1 2 3 3 2 255 4 1 255 5 2 255
http://ideone.com/yJawu5

C++ Recursion Graph Coloring Segmentation Fault

I am in an intro C++ class at uni, and we have a problem that I have been working on for a day or two, but I have been stuck and can't figure out why. The lab is to solve the graph-coloring problem with recursion. We input a file that has a matrix of vertices and their edges. Example-
8
0 1 0 0 0 1 1 0
1 0 1 1 1 0 0 0
0 1 0 0 0 0 1 0
0 1 0 0 1 0 0 1
0 1 0 1 0 0 1 1
1 0 0 0 0 0 1 0
1 0 1 0 1 1 0 1
0 0 0 1 1 0 1 0
With 8 being the number of vertices, and going in row-major order, 0 represents no edge an 1 represents an edge between the respective vertices. Here is the rest of my code, without comments at the moment, sorry. The code reads in a file, sets up a matrix, then uses a recursive algorithm to guess and check to see if the available colors(k) is enough to complete the graph coloring problem.
// Alex Cherecwich
// Lab7
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <fstream>
using namespace std ;
// -----------------------------------------------------------------
class graph
{
private:
int n;
int k;
int ** G;
int the_colors[];
bool adj_vertex(int m, int c);
public:
graph(int x){k = x;}
void read_graph(char * fname);
void set_color();
bool graph_color(int m);
} ;
// -----------------------------------------------------------------
void graph::read_graph(char *fname)
{
ifstream ifs;
ifs.open(fname);
if(!ifs.is_open())
{
cerr << "Can not open (read) file '" << fname <<"'"<< endl;
exit(1);
}
ifs >> n;
G = new(nothrow) int *[n];
for(int b = 0; b < n; b++)
{
G[b]= new(nothrow) int [n];
for(int j=0; j< n; j++)
{
ifs >> G[b][j];
}
}
ifs.close();
}
// -----------------------------------------------------------------
void graph::set_color()
{
the_colors[n];
for(int i = 0; i < n; i++)
{
the_colors[i] = -1;
}
}
// -----------------------------------------------------------------
bool graph::adj_vertex(int m, int c)
{
for(int i = 0; i < n; i++)
{
if(G[m][i] == 1 && the_colors[i] == c)
{
return false;
}
}
return true;
}
// -----------------------------------------------------------------
bool graph::graph_color(int m)
{
if(m == n)
{
cout << "Solution Found" << endl;
cout << "Vertex" << " " << "Color" << endl;
for(int i = 0; i < n; i++)
{
cout << i << " " << the_colors[i] << endl;
}
return true;
}
else
{
for(int c = 0; c < k; c++)
{
if(adj_vertex(m, c))
{
the_colors[m] = c;
bool r = graph_color(m + 1);
if(r) return true;
the_colors[m] = -1;
//return false;
}
}
return false;
}
}
// -----------------------------------------------------------------
int main(int argc, char **argv)
{
int k = atoi(argv[1]);
graph B(k);
B.read_graph(argv[2]);
B.set_color();
if(B.graph_color(0) == false)
{
cout << "No Solution Found" << endl;
}
return 0;
}
The input should be a.out k(number of colors) and the name of the file to be read. Everything works, and I get the right outputs I believe from what I have tested on paper, but I always get a Segmentation fault(core dumped) error message. I am not sure why this is, perhaps I am trying to access some index that doesn't exist, I am not sure. Also, whenever I use 3 as the number of colors(k) on the matrix above, I get this output, which is correct.
Solution Found
Vertex Color
0 0
1 1
2 0
3 2
4 0
5 1
6 2
7 1
Segmentation fault (core dumped)
However, whenever I have k>=4 on the same matrix above, I get this output, which still works but isn't the most efficient solution, which I we are supposed to output every time if a solution is possible.
Solution Found
Vertex Color
0 0
1 1
2 0
3 0
4 2
5 1
6 3
7 1
Segmentation fault (core dumped)
Also, the code works when there are not enough colors, but it still gives a Segmentation fault(core dumped) message. Either way, any and all help would be appreciated!
You never allocate memory for the_colors. It's pointing wherever, and you're lucky your program gets as far as it does.
int the_colors[];
This is not legal C++. It is an extension provided by your compiler, and it doesn't provide arrays that magically adjust their size as needed. Don't use it.
C++ has std::vector, use it for all your array-related needs.

How to find indexes from vector1 in vector2 in c++

i was envolving about a week with this issue, i have two vector for example vec1 and vec2, i want after search and find values from vec1 in vec2 return their indexes where only found for example:
vector<int>vec2 = { 1, 2, 2, 4 };
vector<int>vec1 = { 1, 2, 4 };
i want somthing like this pseudo code and this result:
pseudo code:
for i = 0 to vec2.size() do
return vec1 indexes in vec2;
end
result:
pass1:
1 0 0 0
pass2:
0 1 1 0
pass3:
0 0 0 1
final resault:
0 0 0 1
My code (it does not compile):
My code:
#include <vector>
#include <iostream>
using namespace std;
vector<int> find_index(vector<int>vec2, vector<int>vec1)
{
std::vector<double> tmp;
for (int i = 0; i<vec2.size(); i++)
{
for (int j = 0; j<vec2.size(); j++)
{
if (vec2[i] == vec1[j])
{
tmp.push_back(i);
}
}
}
return tmp;
}
int main()
{
vector<int>vec2 = { 1, 2, 2, 4 };
vector<int>vec1 = { 1, 2, 4 };
cout << find_index(vec2, vec1);
getchar();
return 0;
}
The code you have fails to compile for two reasons:
Using double item type for the tmp vector. A vector<double> does not convert implicitly to the required function result type vector<int>.
The standard library does not define output of vectors, so the cout << a vector in main doesn't compile.
To output the vector you can define function like this:
void write_to( ostream& stream, vector<int> const& v )
{
for( int i = 0; i < int( v.size() ); ++i )
{
stream << (i > 0? " " : "") << v[i];
}
}
and call it like this:
write_to( cout, find_index(vec2, vec1) );
cout << "\n";
It's also possible to write a little glue code that would enable the cout << notation, i.e. that would make it use the write_to function, but that is maybe just complication now.
With these changes your code compiles and outputs
0 1 2 3

C++ Passing 2D Arrays

I am trying to create a minesweeper game that loads the board from a flat file (no, it's not random). As per the assignment instructions, I am to pass a 2d array to a load function which will then parse the file which was passed as a command-line arguement.
Anyway, my problem is passing the 2D array. What is the proper way to go about doing it? Below is the code that I have thus-far:
#include <iostream>
using namespace std;
struct Tile
{
bool mine, visible;
int danger;
};
bool loadBoard( Tile **board, string filename );
const int gridSize = 6;
int main( int argc, char* argv[] )
{
Tile board[ gridSize ][ gridSize ];
loadBoard( board, argv[ 1 ] );
system("PAUSE");
return EXIT_SUCCESS;
}
bool loadBoard( Tile **board, string filename ) {
}
Since you're using C++, why not use
std::vector<std::vector<Tile>>
in preference to a C-style array?
Since you seem to need to use C-style arrays, you could use the approach arpanchaudhury suggests or you could pass Tile* and do something like
static void loadBoard(Tile *board, int rows, int cols, string filename) {
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
Tile* tile = &board[(row*gridSize)+col];
// populate Tile
}
}
}
In case you want to to pass the 2d-array please specify number of columns in the array.
bool loadBoard( Tile board[][size], string filename ) {}
though it is preferable to use vectors instead of simple arrays since you need not specify a pre-defined size
As long as you're using C++...
#include <iostream>
using namespace std;
struct Tile
{
bool mine, visible;
int danger;
};
// load a square board of declared-size.
template<size_t N>
void loadboard( Tile (&board)[N][N], const std::string& filename)
{
// load board here.
cout << "Loading from file: " << filename << endl;
for (size_t i=0;i<N;++i)
{
cout << "board[" << i << "]: [ ";
for (size_t j=0;j<N;++j)
{
// load element board[i][j] here
cout << j << ' ';
}
cout << ']' << endl;
}
cout << endl;
}
int main()
{
Tile board[6][6];
loadboard(board, "yourfilename.bin"); // OK dims are the same
Tile smaller[3][3];
loadboard(smaller, "anotherfile.bin"); // OK. dims are the same
// Tile oddboard[5][6];
// loadboard(oddboard, "anotherfile.bin"); // Error: dims are not the same.
return 0;
}
Output
Loading from file: yourfilename.bin
board[0]: [ 0 1 2 3 4 5 ]
board[1]: [ 0 1 2 3 4 5 ]
board[2]: [ 0 1 2 3 4 5 ]
board[3]: [ 0 1 2 3 4 5 ]
board[4]: [ 0 1 2 3 4 5 ]
board[5]: [ 0 1 2 3 4 5 ]
Loading from file: anotherfile.bin
board[0]: [ 0 1 2 ]
board[1]: [ 0 1 2 ]
board[2]: [ 0 1 2 ]
Of course, there are probably "specific instructions" to not use the templates feature of the language either. Then again, I bet those instructions don't include having SO users solve your problem either, so I don't take much stock in those being followed rigorously anytime soon.

c++ Algorithm to convert an integer into an array of bool

I'm trying to code an algorithm that will save to file as binary strings every integer in a range. Eg, for the range 0 to 7:
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
Note that the leading zeros and spaces between digits are essential.
What I cant figure out how to do in a simple way is to convert the integers to binary numbers represented by bool []s (or some alternate approach).
EDIT
As requested, my solution so far is:
const int NUM_INPUTS = 6;
bool digits[NUM_INPUTS] = {0};
int NUM_PATTERNS = pow(2, NUM_INPUTS);
for(int q = 0; q < NUM_PATTERNS; q++)
{
for(int w = NUM_INPUTS -1 ; w > -1 ; w--)
{
if( ! ((q+1) % ( (int) pow(2, w))) )
digits[w] = !digits[w];
outf << digits[w] << " ";
}
outf << "\n";
}
Unfortunately, this is a bit screwy as the first pattern it gives me is 000001 instead of 000000.
This is not homework. I'm just coding a simple algorithm to give me an input file for training a neural network.
Don't use pow. Just use binary math:
const int NUM_INPUTS = 6;
int NUM_PATTERNS = 1 << NUM_INPUTS;
for(int q = 0; q < NUM_PATTERNS; q++)
{
for(int w = NUM_INPUTS -1 ; w > -1; w--)
{
outf << ((q>>w) & 1) << " ";
}
outf << "\n";
}
Note: I'm not providing code, but merely a hint because the question sounds like homework
This is quite easy. See this example:
number = 23
binary representation = 10111
first digit = (number )&1 = 1
second digit = (number>>1)&1 = 1
third digit = (number>>2)&1 = 1
fourth digit = (number>>3)&1 = 1
fifth digit = (number>>4)&1 = 1
Alternatively written:
temp = number
for i from 0 to digits_count
digit i = temp&1
temp >>= 1
Note that the order of digits taken by this algorithm is the reverse of what you want to print.
The lazy way would be to use std::bitset.
Example:
#include <bitset>
#include <iostream>
int main()
{
for (unsigned int i = 0; i != 8; ++i){
std::bitset<3> b(i);
std::cout << b << std::endl;
}
}
If you want to output the bits individually, space-separated, replace std::cout << b << std::endl; with a call to something like Write(b), with Write defined as:
template<std::size_t S>
void Write(const std::bitset<S>& B)
{
for (int i = S - 1; i >= 0; --i){
std::cout << std::noboolalpha << B[i] << " ";
}
std::cout << std::endl;
}