I'm playing around with C++ and decided to try printing geometric shapes to the console. After printing an equilateral triangle, I decided I should try printing a triangle with varying side lengths, so that one is longer / shorter than the other.
I've tried searching the internet for this, but couldn't find any good explanations for it. After failing to do it on my own, I'd appreciate some help. Below is my code for an equilateral triangle:
unsigned size{ 5 };
for (int x{ 0 }; x < size; x++) {
for (int y{ 0 }; y <= x; y++) {
std::cout << "*";
}
std::cout << std::endl;
}
Which works and prints:
*
**
***
****
*****
Issue is, it can't handle the lower side being longer than the left one, for example. How do I go about doing that, so that I can end up with something like...
*
***
****
******
********
...where the left side and the lower side are not equal?
This could be a start:
void paint_triangle(size_t x, size_t y) {
size_t Y=1;
while(Y<=y) std::cout << std::string(x*Y++/y, '*') << "\n";
}
Related
So for my university homework we are supposed to make a simple game of a 2D map with entities etc.
So I've figured a way of printing a map through it's dimensions and text formatting yet in our lessons it wasn't mentioned how we print on specific parts of the terminal. I've checked same questions but can't seem to get a solution.
Here is the code I use to print the map and make it's array. BLUE_B,STANDARD_B,OUTLINE and GREEN_B are declared above for the sake of color enrichment. Also IF POSSIBLE I don't want to use OS specific commands unless it's completely necessary. I use VS Code for Windows, compile with g++ on WSL Ubuntu-20.04.
for (int row = 0; row < i; row++) {
cout << OUTLINE "##";
for (int column = 0; column < j; column++) {
int n = rand() % 10; // According to "rand()"'s value we print either green, blue, or trees
if (n >= 3) { // We've assigned more values to green, in order to be more possible to be printed
cout << GREEN_B " "
STANDARD_B;
map[row][column] = 1;
} else if (n == 0 || n == 1) {
cout << BLUE_B " "
STANDARD_B;
map[row][column] = 0;
} else if (n == 2) {
int tree = rand() % 2;
cout << TREES "<>"
STANDARD_B;
map[row][column] = 0;
}
}
cout << OUTLINE "##"
STANDARD_B << endl;
}
for (i = 0; i < j + 2; i++) { // Bottom map border printing
cout << OUTLINE "##"
STANDARD_B;
}
If I understand the question correctly, you might be looking for iomanip. It is just one way of doing it. You can use setw and setfill to position different text in different areas. You can set different options for different outputs.
To move the text cursor to a specific line and column you need a “gotoxy”-style function.
Here is something that will work on both Linux terminals and the Windows Terminal. (It will not work on Windows Console without additional initialization help.)
#include <iostream>
const char * CSI = "\033[";
void gotoxy( int x, int y )
{
std::cout << CSI << (y+1) << ";" << (x+1) << "H";
}
Coordinates are (0,0) for the UL corner of the terminal. Here is a working example of use:
// continuing from above
#include <string>
int main()
{
// Clear a 40 x 10 box
for (int y = 0; y < 10; y++)
{
gotoxy( 0, y );
std::cout << std::string( 40, ' ' );
}
// Draw our centered text
gotoxy( 14, 5 );
std::cout << "Hello there!";
// Go to bottom of box and terminate
gotoxy( 0, 10 );
std::cout.flush();
}
For your game
I suggest you move the cursor to HOME (0,0) and draw the changed parts of your gameboard each frame.
I suppose that if you are on a local computer and your gameboard is relatively simple, you could probably get away with a complete redraw each frame...
Are you sure there is no professor-supplied macro or command to move the cursor home? (...as he has supplied magic macros to change the output color)?
I need an Algorithm that I will use to scan pixels out from the center. Problem is with different lengths and sizes, it sometimes can't get to the position (See Image below blue part).
To illustrate the problem more I will show the example output:
If you compare the pictures you will notice that it goes in a spiral and the outputs match with a regular for loop and obviously the problem that it doesn't print the blue part correctly
Here is the code:
#include<iostream>
#include<string>
#include<math.h>
int arr[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
int arrSize = sizeof(arr) / sizeof(arr[0]);
int width = 5;
int height = 3;
void normal2DArray() {
int index = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
index++;
}
}
}
int convertToInex(int x, int y) {
int left = x * y; // elements to the left
int right = (width - x) * y; // elements to the right
return left + right + x;
}
void spiralArray() {
// calculate middle point, which is also the start point
int x = round((float)width / 2) - 1;
int y = round((float)height / 2) - 1;
int direction = 0; // 0=right, 1=up, 2=left, 3=down
int turnCounter = 1;
int numSteps = 1;
int step = 1;
int index;
while (true) {
index = convertToInex(x, y); // defines the index position in arr
std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
switch (direction) {
case 0: x++; break;
case 1: y--; break;
case 2: x--; break;
case 3: y++; break;
}
index = convertToInex(x, y);
if (step % numSteps == 0) {
direction = (direction + 1) % 4;
turnCounter++;
if (turnCounter % 2 == 0) numSteps++;
}
step++;
if (step > arrSize) break;
}
}
void main() {
std::cout << "Output of Normal 2D Array:\n";
normal2DArray();
std::cout << "\n"; // better spacing
std::cout << "Output of Spiral Array:\n";
spiralArray();
}
I tried to keep the code as simple and small as possible. It should be ready to import and use.
And yes I already searched for my answer online but I didn't find anything that covered up the problem here nor had a similar setup like I have(1D arr and combined 2D array WIDTH/HEIGHT) and for sure not in c++.
❗ Also I need a Solution that works with all widths and heights and arr sizes and also works for any side ❗
I hope you can provide me with helpful answers and would be grateful with good and fast algorithm implementations/optimizations
EDIT:
Thanks to the replies in this Thread. I decided to go with the solution from #ldog for now even though I'm not completely satisfied with it.
Here are the edited code parts:
int failcounter = 0;
while (true) {
index = convertToInex(x, y); // defines the index position in arr
if (index < 0 || index > arrSize) failcounter++;
else std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
// unchanged code inbetween
if (step > arrSize + failcounter) break;
Based on your comment:
#Beta they don't need to connect. It just has to detect that it's outside the array size (in that case -1) and don't scan them and find the next continue point. So it would continue like this: 5, 1, 6, 11
it seems you don't care that the spiral goes "out-of-bounds". In this case, the trivial answer is, embed the shapes that have no spiral in one that is always guaranteed to have one.
Thus if your input rectangle is N x M, then embed it in a rectangle of size max(M,N) x max(M,N), solve the problem in the latter, and when printing just ignore non-existent numbers in the original problem. Your printed sequence then will always be unique up to how the embedding occurs. The most reasonable embedding would try to center the smaller rectangle as much as possible in the larger rectangle, but this is up to you.
In this case you don't need an algorithm as you can compute everything analytically if you care to do the book-keeping and figure out the formulas involved.
You can hit a dead end (meaning exit the grid) in four spots. In each case, jump to the next live pixel you would have reached, if any live cells remain.
You can do this fairly easily by keeping track of the four corners you've visited furthest from the starting pixel. Using compass coords and N for up, these are the NE, NW, SW, and SE extremes visited.
If you hit a dead end going N from the NE pixel, jump to the pixel one to the left of the NW pixel and set the movement direction to down. If that is also a dead end, jump to one below the SW pixel and set the movement direction to right. Etc... When all four corners and dead ends then you're done.
I have a 2D map in c++ which represents a game-field. On each field there can be a means of transport (e.g. car, plane ... (all previously defined in an enum)).
bool MainClass::isTrue(int x, int y, int w, int h)
{
for (int m = y; m < h; m++)
{
for (int n = x; n < w; n++)
{
if (map_.at(n-1).at(m-1) == SubClass::PartOfEnum::CAR ||
map_.at(n-1).at(m-1) == SubClass::PartofEnum::BOAT ||
map_.at(n-1).at(m-1) == SubClass::PartofEnum::SHIP ||
map_.at(n-1).at(m-1) == SubClass::PartofEnum::PLANE)
return (0);
}
}
return (1);
// other code ..
}
As someone can see, I'm iterating through parts of this map and want to know if on some defined coordinates there is one of those means of transport. The problem is the code inside of the for-loop which is repeating for each part of the enum. So my question is, if there is a solution for this kind of problem to write just one line of code instead of four. Maybe to save the parts of the enum in a separate variable and then take this variable for the loop. The original-enum also contains some other objects which should be not part of this loop (there are some other means of transport like bicycle in the original-enum but here only these four are relevant). Thanks in advance
So my question is, if there is a solution for this kind of problem to write just one line of code instead of four
You need four comparisons, but you don't need to access map_ more than once. A handy utility should do:
bool isVehicle(SubClass::PartOfEnum test) {
return test == SubClass::PartOfEnum::CAR ||
test == SubClass::PartofEnum::BOAT ||
test == SubClass::PartofEnum::SHIP ||
test == SubClass::PartofEnum::PLANE;
}
Which you then test against:
for (int n = x; n < w; n++)
{
if (isVehicle(map_.at(n-1).at(m-1)))
return (0);
}
A fairly straight-forward bit of refactoring. Other benefits beyond the single access is that one can tell what the condition is checking for, without delving into the details of how it's being checked. And now you can use the same condition in multiple places fairly easily, should you need to. Not to mention any update to the function will apply in all places you use it to perform the check.
One way to do it would be to use a bitmask. This is a method which turns the 4 comparisons into a 1 comparison and it might boost your performance. Say PartOfEnum is defined as follows:
enum PartOfEnum {
CAR = 1 << 0,
BOAT = 1 << 1,
SHIP = 1 << 2,
PLANE = 1 << 3,
VEHICLE = CAR | BOAT | SHIP | PLANE
};
Then the test would look like:
for (int n = x; n < w; n++)
{
if (map_.at(n-1).at(m-1) & PartOfEnum::VEHICLE)
return (0);
}
If you use an enum class though, you will need to provide the relevant operator overloads.
Similar to #DeiDei's solution, but for when enum is sequential:
#include <iostream>
enum Vehicle
{
CAR,
BOAT,
SHIP,
PLANE
};
int main()
{
int seaVehicle = 1 << BOAT | 1 << SHIP;
int map_content = CAR;
std::cout << "Is this a Sea Vehicle? " << std::boolalpha << bool(1 << map_content & seaVehicle) << std::endl;
map_content = BOAT;
std::cout << "Is this a Sea Vehicle? " << std::boolalpha << bool(1 << map_content & seaVehicle) << std::endl;
}
https://ideone.com/DiGfVl
Is this a Sea Vehicle? false
Is this a Sea Vehicle? true
I saw that there was another question almost just like this but the answer didn't do what I want it to.
This is for an assignment. I have a 4x4 grid and a users inputted starting and ending (x,y) coordinates. I need to send this info from main to a create_path function which calculates the shortest path then sends it to another function that prints the grid step by step of the markers location until it makes it to the wanted coordinate. I can't use arrays and I have to have main, create_path, and print_path. The marker can only go up, down, left, and right.
So I really have no clue what to do. I thought about creating a variable for each cell in the grid but didn't know where to go from there. If somebody knows a quick solution that only uses main and one other function that is okay because I am running out of time.
You don't need to see main because it just shows the user the grid and asks them for input then sends the input to this function:
void create_path(int xStart, int xEnd, int yStart, int yEnd)
{
}
As you have already pointed out yourself in the comments, the shortest path from (0,2) to (3,1) is "right 3 down 1" in other words: right 3-0=3 and down 2-1=1
And that's already pretty much the answer...
In general, how do find the shortest path from (xStart, yStart) to (xEnd, yEnd)? You just do the same thing as before again. It is "right xEnd-xStart, down yEnd-yStart".
So everything that the print_path function requires is just "where do I start" and "how much do I go right/left and how much do I go up/down?"
So you could use two variable in create_path
int right = xEnd-xStart;
int down = yEnd-yStart;
and you send these to print_path. You have not provided the signature of print_path, but it could look like this:
void print_path(int xStart, int yStart, int right, int down)
{
}
Within this function you just do two loops:
int i = xStart;
int xend = xStart + right; // observe: if right is negative, it's just subtraction
bool right = (right >= 0); // are we going right or left?
while(i != xend) {
std::cout << "next waypoint: x = " << i << ", y = " << yStart << std::endl;
if (right) {
i++;
} else {
i--;
}
}
And now you do the same thing for the y coordinate
int j = yStart;
int yend = yStart + down;
bool down = (down >= 0); // are we going down or up?
while(j != yend) {
std::cout << "next waypoint: x = " << xend << ", y = " << j << std::endl;
if (down) {
j++;
} else {
j--;
}
}
create_path has to be a recursive function.
conditions given should be :
First check if the points are in the boundary or not
Then check if the point is the desired point, if yes then return
Otherwise recurse for up, down, left, right and diagonal points.
I have this problem where I have to find the shortest path in an NxM grid from point A (always top left) to point B (always bottom right) by only moving right or down. Sounds easy, eh? Well here's the catch: I can only move the number shown on the tile I'm sitting on at the moment. Let me illustrate:
2 5 1 2
9 2 5 3
3 3 1 1
4 8 2 7
In this 4x4 grid the shortest path would take 3 steps, walking from top left 2 nodes down to 3, and from there 3 nodes right to 1, and then 1 node down to the goal.
[2] 5 1 2
9 2 5 3
[3] 3 1 [1]
4 8 2 [7]
If not for the shortest path, I could also be taking this route:
[2] 5 [1][2]
9 2 5 3
3 3 1 [1]
4 8 2 [7]
That would unfortunately take a whopping 4 steps, and thus, is not in my interest.
That should clear things out a bit. Now about the input.
The user inputs the grid as follows:
5 4 // height and width
2 5 2 2 //
2 2 7 3 // the
3 1 2 2 // grid
4 8 2 7 //
1 1 1 1 //
Homework
I have thought this through, but cannot come to a better solution than to simplify the inputted grid into an unweighed (or negative-weight) graph and run something like dijkstra or A* (or something along those lines) on it. Well... this is the part where I get lost. I implemented something to begin with (or something to throw to thrash right away). It's got nothing to do with dijkstra or A* or anything; just straight-forward breadth-first search.
The Code
#include <iostream>
#include <vector>
struct Point;
typedef std::vector<int> vector_1D;
typedef std::vector< std::vector<int> > vector_2D;
typedef std::vector<Point> vector_point;
struct Point {
int y, x;
vector_point Parents;
Point(int yPos = 0, int xPos = 0) : y(yPos), x(xPos) { }
void operator << (const Point& point) { this->Parents.push_back(point); }
};
struct grid_t {
int height, width;
vector_2D tiles;
grid_t() // construct the grid
{
std::cin >> height >> width; // input grid height & width
tiles.resize(height, vector_1D(width, 0)); // initialize grid tiles
for(int i = 0; i < height; i++) //
for(int j = 0; j < width; j++) // input each tile one at a time
std::cin >> tiles[i][j]; // by looping through the grid
}
};
void go_find_it(grid_t &grid)
{
vector_point openList, closedList;
Point previous_node; // the point is initialized as (y = 0, x = 0) if not told otherwise
openList.push_back(previous_node); // (0, 0) is the first point we want to consult, of course
do
{
closedList.push_back(openList.back()); // the tile we are at is good and checked. mark it so.
openList.pop_back(); // we don't need this guy no more
int y = closedList.back().y; // now we'll actually
int x = closedList.back().x; // move to the new point
int jump = grid.tiles[y][x]; // 'jump' is the number shown on the tile we're standing on.
if(y + jump < grid.height) // if we're not going out of bounds
{
openList.push_back(Point(y+jump, x)); //
openList.back() << Point(y, x); // push in the point we're at right now, since it's the parent node
}
if(x + jump < grid.width) // if we're not going out of bounds
{
openList.push_back(Point(y, x+jump)); // push in the new promising point
openList.back() << Point(y, x); // push in the point we're at right now, since it's the parent node
}
}
while(openList.size() > 0); // when there are no new tiles to check, break out and return
}
int main()
{
grid_t grid; // initialize grid
go_find_it(grid); // basically a brute-force get-it-all-algorithm
return 0;
}
I should probably also point out that the running time cannot exceed 1 second, and the maximum grid height and width is 1000. All of the tiles are also numbers from 1 to 1000.
Thanks.
Edited Code
#include <iostream>
#include <vector>
struct Point;
typedef std::vector<int> vector_1D;
typedef std::vector< std::vector<int> > vector_2D;
typedef std::vector<Point> vector_point;
struct Point {
int y, x, depth;
vector_point Parents;
Point(int yPos = 0, int xPos = 0, int dDepth = 0) : y(yPos), x(xPos), depth(dDepth) { }
void operator << (const Point& point) { this->Parents.push_back(point); }
};
struct grid_t {
int height, width;
vector_2D tiles;
grid_t() // construct the grid
{
std::cin >> height >> width; // input grid height & width
tiles.resize(height, vector_1D(width, 0)); // initialize grid tiles
for(int i = 0; i < height; i++) //
for(int j = 0; j < width; j++) // input each tile one at a time
std::cin >> tiles[i][j]; // by looping through the grid
}
};
int go_find_it(grid_t &grid)
{
vector_point openList, closedList;
Point previous_node(0, 0, 0); // the point is initialized as (y = 0, x = 0, depth = 0) if not told otherwise
openList.push_back(previous_node); // (0, 0) is the first point we want to consult, of course
int min_path = 1000000;
do
{
closedList.push_back(openList[0]); // the tile we are at is good and checked. mark it so.
openList.erase(openList.begin()); // we don't need this guy no more
int y = closedList.back().y; // now we'll actually move to the new point
int x = closedList.back().x; //
int depth = closedList.back().depth; // the new depth
if(y == grid.height-1 && x == grid.width-1) return depth; // the first path is the shortest one. return it
int jump = grid.tiles[y][x]; // 'jump' is the number shown on the tile we're standing on.
if(y + jump < grid.height) // if we're not going out of bounds
{
openList.push_back(Point(y+jump, x, depth+1)); //
openList.back() << Point(y, x); // push in the point we're at right now, since it's the parent node
}
if(x + jump < grid.width) // if we're not going out of bounds
{
openList.push_back(Point(y, x+jump, depth+1)); // push in the new promising point
openList.back() << Point(y, x); // push in the point we're at right now, since it's the parent node
}
}
while(openList.size() > 0); // when there are no new tiles to check, break out and return false
return 0;
}
int main()
{
grid_t grid; // initialize grid
int min_path = go_find_it(grid); // basically a brute-force get-it-all-algorithm
std::cout << min_path << std::endl;
//system("pause");
return 0;
}
The program now prints the correct answer. Now I have to optimize (run time is way too big). Any hints on this one? Optimizing is the one thing I suck at.
The Answer
In the end the solution appeared to consist of little code. The less the better, as I like it. Thanks to Dejan Jovanović for the beautiful solution
#include <iostream>
#include <vector>
#include <algorithm>
struct grid_t {
int height, width;
std::vector< std::vector<int> > tiles;
std::vector< std::vector<int> > distance;
grid_t() // construct the grid
{
std::cin >> height >> width; // input grid height & width
tiles.resize(height, std::vector<int>(width, 0)); // initialize grid tiles
distance.resize(height, std::vector<int>(width, 1000000)); // initialize grid tiles
for(int i = 0; i < height; i++) //
for(int j = 0; j < width; j++) // input each tile one at a time
std::cin >> tiles[i][j]; // by looping through the grid
}
};
int main()
{
grid_t grid; // initialize grid
grid.distance[0][0] = 0;
for(int i = 0; i < grid.height; i++) {
for(int j = 0; j < grid.width; j++) {
if(grid.distance[i][j] < 1000000) {
int d = grid.tiles[i][j];
if (i + d < grid.height) {
grid.distance[i+d][j] = std::min(grid.distance[i][j] + 1, grid.distance[i+d][j]);
}
if (j + d < grid.width) {
grid.distance[i][j+d] = std::min(grid.distance[i][j] + 1, grid.distance[i][j+d]);
}
}
}
}
if(grid.distance[grid.height-1][grid.width-1] == 1000000) grid.distance[grid.height-1][grid.width-1] = 0;
std::cout << grid.distance[grid.height-1][grid.width-1] << std::endl;
//system("pause");
return 0;
}
There is need to construct the graph, this can easily be solved with dynamic programming using one scan over the matrix.
You can set the distance matrix D[i,j] to +inf at the start, with D[0,0] = 0. While traversing the matrix you just do
if (D[i,j] < +inf) {
int d = a[i, j];
if (i + d < M) {
D[i + d, j] = min(D[i,j] + 1, D[i + d, j]);
}
if (j + d < N) {
D[i, j + d] = min(D[i,j] + 1, D[i, j + d]);
}
}
The final minimal distance is in D[M -1, N-1]. If you wish to reconstruct the path you can keep a separate matrix that marks where the shortest path came from.
You're overthinking it. :) Run a Breadth-First Search. The solution space is a binary tree, where each node branches into "right" or "down". From current point, generate the down point and right point, stuff their coordinates into a queue, repeat until at finish.
Without checking, something like this:
queue = [{ x: 0, y: 0, path: [] }] # seed queue with starting point
p = nil
do
raise NoSolutionException if p.empty? # solution space exhausted
p = queue.pop # get next state from the back of the queue
break if p.x == MAX_X - 1 && p.y == MAX_Y - 1 # we found final state
l = grid[p.x][p.y] # leap length
# add right state to the front of the queue
queue.unshift({x: p.x + l, y: p.y, path: p.path + [p] }) if p.x + l <= MAX_X
# add down state to the front of the queue
queue.unshift({x: p.x, y: p.y + l, path: p.path + [p] }) if p.y + l <= MAX_Y
end
puts p.path
Uglifying into C++ left as exercise for the reader :p
Build an unweighted directed graph:
There are NxM vertices. In what follows, vertex v corresponds to grid square v.
There is an arc from vertex u to v iff you can jump from grid square u to square v in a single move.
Now apply a shortest path algorithm from the top-right vertex to the bottom-left.
Finally, observe that you don't actually need to build the graph. You can simply implement the shortest path algoritm in terms of the original grid.
Start off with a brute force approach to get it to work, then optimize from there. The brute force is straight-forward: run it recursively. Take your two moves, recurse on those, and so on. Collect all the valid answers and retain the minimum. If the run time is too long, then you can optimize by a variety of means. For instance, some of the moves may be invalid (because they exceed a dimension of the grid) and can be eliminated, and so on. Keep optimizing until a worst case input runs at the desired speed.
Having said that, the performance requirements only make sense if you are using the same system and inputs, and even then there are some caveats. Big O notation is a much better way of analyzing the performance, plus it can point you to an algorithm and eliminate the need for profiling.