How to print and modify char in C++ - c++

I want to create a project that will print the '|' character as 4 layers going 1 3 5 7 something like
|
|||
|||||
|||||||
I wrote a for loop for this and the code is here:
for (int i = 1; i <= 4; i++) {
//for loop for displaying space
for (int s = i; s < 4; s++) {
cout << " ";
}
//for loop to display star equal to row number
for (int j = 1; j <= (2 * i - 1); j++) {
cout << "|";
}
// ending line after each row
cout << "\n";
}
So how can I make a code that will take user input like
cout << "Please enter a row number \n" << "Please enter a column number" << endl;
and let say the user entered 2 as row number 2 as column number I want the output to be something like
|
|
|||||
|||||||
Deletes 2 '|' character from the 2nd row
First I think putting every character in a array like char arr[] = { '|' , '||' , '|||', '||||'}
and deleting according to user input but I failed. Any help?

Here is a solution:
#include <iostream>
#include <vector>
std::size_t getLayerCount( )
{
std::cout << "How many layers to print: ";
std::size_t layerCount { };
std::cin >> layerCount;
return layerCount;
}
std::vector< std::vector<char> > generateShape( const std::size_t layerCount )
{
const std::size_t MAX_CHAR_COUNT_IN_A_ROW { layerCount * 2 };
constexpr char spaceChar { ' ' };
std::vector< std::vector<char> > shape( layerCount, std::vector<char>( MAX_CHAR_COUNT_IN_A_ROW, spaceChar ) );
for ( std::size_t row { }; row < layerCount; ++row )
{
for ( std::size_t offset { layerCount - row - 1 }; offset < layerCount + row; ++offset )
{
shape[ row ][ offset ] = '|';
}
shape[ row ][ MAX_CHAR_COUNT_IN_A_ROW - 1 ] = '\0';
}
return shape;
}
void printShape( const std::vector< std::vector<char> >& shape )
{
for ( const auto& row : shape )
{
std::cout.write( row.data( ), row.size( ) ).write( "\n", 1 );
}
}
void deleteSpecificChars( std::vector< std::vector<char> >& shape )
{
std::cout << "Please enter a row number: ";
std::size_t rowNumber { };
std::cin >> rowNumber;
std::cout << "Please enter a column number: ";
std::size_t colNumber { };
std::cin >> colNumber;
--rowNumber;
--colNumber;
const std::size_t layerCount { shape.size( ) };
const std::size_t posOfFirstCharInRow { layerCount - rowNumber - 1 };
const std::size_t posOfTargetCharInRow { posOfFirstCharInRow + colNumber };
const std::size_t posOfLastCharInRow { posOfFirstCharInRow + ( 2 * rowNumber ) };
for ( std::size_t idx { posOfTargetCharInRow }; idx <= posOfLastCharInRow; ++idx )
{
shape[ rowNumber ][ idx ] = ' ';
}
}
int main( )
{
const std::size_t layerCount { getLayerCount( ) };
std::vector< std::vector<char> > shape { generateShape( layerCount ) };
printShape( shape );
deleteSpecificChars( shape );
printShape( shape );
return 0;
}
Sample input/output:
How many layers to print: 4
|
|||
|||||
|||||||
Please enter a row number: 2
Please enter a column number: 2
|
|
|||||
|||||||
Another one:
How many layers to print: 5
|
|||
|||||
|||||||
|||||||||
Please enter a row number: 4
Please enter a column number: 4
|
|||
|||||
|||
|||||||||

Limiting your pile of bars to 4 levels, this should work:
You basically just want a fixed size string of bars, '|'.
Then remove n consecutive characters from that string.
The only thing you have to calculate is the starting index to start removing from, then replace n characters with blanks.
You can add some checks for row and col boundaries.
[Demo]
#include <iostream> // cout
#include <string>
int main()
{
std::string bars(16, '|');
auto get_start_deleting_pos = [](int row, int col) {
if (row == 1) { if (col > 1) { return -1; } return 0; }
else if (row == 2) { if (col > 3) { return -1; } return col; }
else if (row == 3) { if (col > 5) { return -1; } return 3 + col; }
else if (row == 4) { if (col > 7) { return -1; } return 8 + col; }
else return -1;
};
auto print_bars = [&bars]() {
std::cout << " " << bars[0] << "\n";
std::cout << " " << bars.substr(1, 3) << "\n";
std::cout << " " << bars.substr(4, 5) << "\n";
std::cout << bars.substr(9) << "\n";
};
auto start_deleting_from_row{4};
auto start_deleting_from_col{1};
auto num_chars_to_delete{4};
auto pos{ get_start_deleting_pos(start_deleting_from_row, start_deleting_from_col) };
if (pos != -1)
{
bars.replace(pos, num_chars_to_delete, num_chars_to_delete, ' ');
}
print_bars();
}
And if you want a more generic solution, where the user inputs the level, the row and col to start deleting from, and the number of characters to delete:
[Demo]
#include <iostream> // cout
#include <string>
auto get_size_for_levels(int l) { return l*l; }
auto get_index_for_row_and_col(int row, int col) { return (row - 1) * (row - 1) - 1 + col; }
auto get_num_cols_for_row (int row) { return row * 2 - 1; }
auto check_row_and_col(int levels, int row, int col) {
if (row < 1 or levels < row) { return false; }
if (col < 1 or get_num_cols_for_row(row) < col) { return false; }
return true;
}
int main()
{
auto levels{7}; // levels start at 1
auto start_deleting_from_row{4}; // rows start at 1
auto start_deleting_from_col{5}; // cols start at 1
auto num_chars_to_delete{6};
std::string bars(get_size_for_levels(levels), '|');
if (check_row_and_col(levels, start_deleting_from_row, start_deleting_from_col))
{
bars.replace(
get_index_for_row_and_col(start_deleting_from_row, start_deleting_from_col),
num_chars_to_delete,
num_chars_to_delete,
' ');
}
for (int l{1}; l <= levels; ++l)
{
std::cout
<< std::string(levels - l, ' ')
<< bars.substr(get_index_for_row_and_col(l, 1), get_num_cols_for_row(l))
<< "\n";
}
}

Related

Discovering plus patterns in 2-dimensional array

I'm not looking for a solution. All I'm looking for is guidance. I am stuck on this problem and I have no idea what to study or learn in order to solve it. I tried many solutions but they all have bugs. Please take a look.
the problem
Translation:
Given a matrix N x M
2 <= N <= 15
2 <= M <= 15
Every cell has either a 1 or 0. The user shall check if a plus symbol forms from the connected cells with value of 1. The segments that form the plus have same length and are perpendicular to one other, cutting in the middle. Write a program that shows have many valid pluses there are and the number of [1] cells inside the pluses.
The figure shows a correct plus and an incorrect plus.
I kindly ask that you show me some way to go about cracking this problem, some lesson to learn or some algorithm to read. Thank you! My code trying this problem is below.
#include <iostream>
using namespace std;
int main() {
int column = 8; // this is N
int row = 8; // this is M
int pluses = 0;
int addition = 1;
int ones = 0;
bool could_be_plus = true;
int example[row][column];
cout << "Place values [0] or [1]\n";
for (int i = 0; i < row; ++i)
for (int j = 0; j < column; ++j)
cin >> example[i][j];
cout << endl;
for (int i = 1; i < row - 1; ++i) {
for (int j = 1; j < column - 1; ++j) {
could_be_plus = true;
while (could_be_plus) {
//addition variable controls the number of layer outside first plus
if (example[i][j - addition] == 1 && example[i - addition][j] == 1 && example[i + addition][j] == 1 && example[i][j + addition] == 1) {
if (addition == 1) {
pluses++;
//including the center there are 5 ones
ones += 5;
addition++;
}
else {
ones += 4;
addition++;
}
}
else {
could_be_plus = false;
addition = 1;
}
}
}
cout << endl;
}
cout << "pluses: " << pluses << endl;
cout << "number of 1s: " << ones << endl;
};
My code had bugs that I couldn't fix regarding [1] cells (not part of the plus) that were touching the plus cells.
The needed algorithm is not so complicated. But, the solution needs a lot of typing work.
We iterate over each cell in the matrix. If a cell is '1' then it is a potential middle point of a cross and we can evaluate further.
We look in all 4 directions of the current cell in the matrix, starting from the current cell. Of course maximum until we hit the border of the matrix.
We count the number of '1's beneath the current cell.
Then, after we have counted all '1's, we check all counts for all directions.
According to the definition, they must be equal and greater than 0. In the drawing, where the lower wing of the potential cross is longer, it is deemed to be invalid.
There are really many potential soultions. I prepared one for you. Maybe you can then understand the algorithm better.
Please check:
#include <iostream>
#include <limits>
#include <iomanip>
#include <vector>
int main() {
#define GET_USER_INPUT 0
#if GET_USER_INPUT
// This will define the extension of the 2d matrix
std::size_t numberOfRows{}, numberOfColumns{};
// ---------------------------------------------------------------------------------------------
// Inform the user what to do and try to get the correct input
bool validInput{};
while (not validInput) {
std::cout << "\n\nPlease enter number of rows and number of columns for the matrix.\n"
"Condition: rows and columns are greater 1 and smaller than 16:\n";
// Try to read values
std::cin >> numberOfRows >> numberOfColumns;
// Chekc, if the input operation worked (nobody entered abc or similar)
if (not std::cin) {
std::cout << "\n\n*** Error: Invalid input format. Please try again\n\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
}
else {
// Check bounds
if ((numberOfRows > 1) and (numberOfRows < 16) and (numberOfColumns > 1) and (numberOfColumns < 16))
validInput = true;
else
std::cout << "\n\n*** Error: Values are out of bounds. Please try again\n\n";
}
}
// ---------------------------------------------------------------------------------------------
// Define and initialize a 2d vector
std::vector<std::vector<char>> matrix(numberOfRows, std::vector<char>(numberOfColumns,'-'));
// Just for display purposes, we want to have a copy of the matrix
std::vector<std::vector<char>> tmp(numberOfRows, std::vector<char>(numberOfColumns, '-'));
// ---------------------------------------------------------------------------------------------
// Fill the matrix
for (std::size_t row{}; row < numberOfRows; ++row) {
for (std::size_t col{}; col < numberOfColumns; ++col) {
validInput = false;
while (not validInput) {
std::cout << "\nEnter 1 or 0 for row '" << row + 1 << "' and column '" << col+1 << "': ";
if (std::cin >> matrix[row][col]) {
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if ((matrix[row][col] == '0') or (matrix[row][col] == '1')) {
std::cout << "\n\nCurrent matrix:\n";
for (std::size_t i{}; i < numberOfRows; ++i) {
for (std::size_t k{}; k < numberOfColumns; ++k) std::cout << matrix[i][k] << ' ';
std::cout << '\n';
}
std::cout << '\n';
validInput = true;
}
else
std::cout << "\n\n*** Error: Wrong input. Only '1 or '0' allowed, try again\n\n";
}
else {
std::cout << "\n\n*** Error: Wrong input characters, try again\n\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
}
}
#else
// Used predefine matrix
// ---------------------------------------------------------------------------------------------
// Define and initialize a 2d vector
std::vector<std::vector<char>> matrix{
{'0','1','0','0','0'},
{'1','1','1','0','0'},
{'0','1','0','1','0'},
{'0','0','1','1','1'},
{'0','1','0','1','0'},
{'0','1','0','1','0'},
{'1','1','1','0','0'},
{'0','1','0','0','0'},
{'0','1','0','0','0'},
};
std::vector<std::vector<char>> tmp = matrix;
std::size_t numberOfRows = matrix.size();
std::size_t numberOfColumns = matrix.front().size();
#endif
// ---------------------------------------------------------------------------------------------
// Lambdas to count the 1s beneath a given position
auto longestExtendRight = [&](std::size_t row, std::size_t col) -> unsigned {
unsigned counter{};
tmp[row][col] = '+';
while (col < numberOfColumns - 1) {
++col;
if (tmp[row][col] == '1') {
tmp[row][col] = '+';
++counter;
}
else
break;
}
return counter;
};
auto longestExtendLeft = [&](std::size_t row, std::size_t col) -> unsigned {
unsigned counter{};
tmp[row][col] = '+';
while (col > 0) {
--col;
if (tmp[row][col] == '1') {
tmp[row][col] = '+';
++counter;
}
else
break;
}
return counter;
};
auto longestExtendDown = [&](std::size_t row, std::size_t col) -> unsigned {
unsigned counter{};
tmp[row][col] = '+';
while (row < numberOfRows - 1) {
++row;
if (tmp[row][col] == '1') {
tmp[row][col] = '+';
++counter;
}
else
break;
}
return counter;
};
auto longestExtendUp = [&](std::size_t row, std::size_t col) -> unsigned {
unsigned counter{};
tmp[row][col] = '+';
while (row > 0) {
--row;
if (tmp[row][col] == '1') {
tmp[row][col] = '+';
++counter;
}
else
break;
}
return counter;
};
// ---------------------------------------------------------------------------------------------
// Now check each cell of the matrix, if there are the same numbers of 1 around
// Show matrix again:
std::cout << "\n\n\nMatrix:\n\n";
for (std::size_t i{}; i < numberOfRows; ++i) {
for (std::size_t k{}; k < numberOfColumns; ++k) std::cout << matrix[i][k] << ' ';
std::cout << '\n';
}
std::cout << "\n\n";
for (std::size_t row{}; row < numberOfRows; ++row) {
for (std::size_t col{}; col < numberOfColumns; ++col) {
// Only with a 1 in the middle
if (matrix[row][col] == '1') {
// Make a copy of the current matrix
tmp = matrix;
// Check for a cross
const unsigned extendRight = longestExtendRight(row, col);
const unsigned extendLeft = longestExtendLeft(row, col);
const unsigned extendDown = longestExtendDown(row, col);
const unsigned extendUp = longestExtendUp(row, col);
if ((extendRight == extendLeft) and (extendLeft == extendDown) and (extendDown == extendUp) and (extendRight > 0)) {
// Corss found. Show it
std::cout << "\n\nCross found:\n";
for (std::size_t i{}; i < numberOfRows; ++i) {
for (std::size_t k{}; k < numberOfColumns; ++k) std::cout << tmp[i][k] << ' ';
std::cout << '\n';
}
std::cout << '\n';
}
}
}
}
}

How to compare user input with the values in the 2D array?

I wrote this code that should ask the user for a number between 1 and 12 and then ask the user to enter a number between 1 and 4 x times the number the user chose between 1 and 12. It then should output a 2D array filled with random numbers and then compare the users input with the values in the 2D array, similar to Bingo if I do say so. Here is a sample I wrote of how my code should work:
Enter a number between 1 and 12: 3
Please enter 3 numbers.
1: Enter a number between 1 and 4: 2
2: Enter a number between 1 and 4: 3
3: Enter a number between 1 and 4: 3
Your numbers:
2 3 3
1 1 3
3 4 2
1 4 1
sorry, no match found
I got one last step that I am just completely stuck at, I want to compare the numbers the user entered to see if they got a match in row or columns, does anybody have any clue how might I work that out? thank you in advance.
Here is what I worked on up till now:
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
int Atemp = 0;
int Utemp = 0;
void printGrid(int &Umain);
bool compareGrid(int ** BingoArray, int * NumbersArray, int size);
int main(){
int Umain = 0;
//prompt user to enter a number between 1 and 12.
while (Umain > 12 || Umain < 1){
cout << "Please Enter a number between 1 and 12: ";
cin >> Umain;
}
int ** BingoArray = new int*[Umain];
for (int i=0;i<Umain;i++)
{
BingoArray[i] = new int[Umain];
}
// prompt user to enter a number between 1 and 4 * the number they entered in Umain
int * UserArray = new int[Umain];
for (int i=0;i<Umain;i++)
{
int selection = 0;
while (selection <1 || selection > 4)
{
cout<<"Please enter a number between 1 and 4: ";
cin >> selection;
if (selection<1 || selection > 4)
{
cout<<"Invalid Number";
}
else
{
UserArray[i] = selection;
}
}
}
printGrid(Umain);
compareGrid(BingoArray, UserArray, Atemp);
return 0;
}
//2D array filled with random numbers and outputs size according to the user
void printGrid(int &Umain){
cout<<endl;
cout<<" ";
int i=1,j;
for(j = 0; j <= 4*Umain; j++){
if(j%4==2){
cout<<" ";
}
}
cout<<endl;
for(i = 0; i <= 2*Umain; i++){
for(j = 0; j <= 2*Umain; j++){
if(i%2==0){
if(j==0){
cout<<" ";
}
if(j%2==0){
cout<<" ";
}else{
cout<<"---";
}
}else{
if(j%2==0){
cout<<" | ";
}else cout<< (rand()%4+1);
}
}
if(i%2!=0){
cout<<" ";
}
cout<<endl;
}
cout<<" ";
for(j = 0, i = 1; j <= 4*Umain; j++){
if(j%4==2){
cout<< " ";
}
}
cout<<endl;
}
//Compare selection with rows and columns of 2D array
bool compareGrid(int ** BingoArray, int * NumbersArray, int size) {
return false;
}
I played that stupid game a "few" times now and never won. Stupid game.
#include <cassert> // assert()
#include <cstddef> // std::size_t a type that is guaranteed to be big enough to
// hold all sizes of objects in memory and indexes into them
#include <limits> // std::numeric_limits<>
#include <vector> // std::vector<>
#include <iostream> // std::cin, std::cout
#include <random> // std::uniform_int_distribution<>, std::mt19937,
#include <chrono> // std::chrono::high_resolution_clock
#include <iterator> // std::ostream_iterator<>
// of course you can keep using std::rand(), std::srand() and std::time() form
// <cstdlib> and <ctime>, I just don't feel comfortable using these dinosaurs
// in new code any more.
// clears flags and empties an input stream
void clear(std::istream &is)
{
is.clear();
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
// prints the grid data assuming it has columns columns
void print_grid(std::vector<int> const &data, std::size_t columns)
{
for (std::size_t i{}; i < data.size(); ++i) {
std::cout << data[i] << ' ';
if ((i + 1) % columns == 0) // insert a newline every columns numbers
std::cout.put('\n');
}
}
// generate random numbers for the grid, as I said, keep using std::rand() if you
// are more at ease with that.
void fill_grid(std::vector<int> &data, std::mt19937 &rng)
{
std::uniform_int_distribution<int> dist{ 1, 4 };
std::generate(std::begin(data), std::end(data), [&]() { return dist(rng); });
}
// compares rows and columns of data to tips
bool compare_grid(std::vector<int> const &data, std::size_t columns, std::vector<int> const &tips)
{
assert(columns == tips.size()); // make sure the length of the columns is
// the same as the size of tips
// check the rows:
for (std::size_t i{}; i < columns * columns; i += columns) {
bool win = true; // assume a match at first
for (std::size_t k{ i }; win && k < i + columns; ++k)
win = data[k] == tips[k - i]; // and compare inside the loop
if (win) // the loop ends at the first mis-
return true; // match.
}
// compare columns:
for (std::size_t i{}; i < columns; ++i) {
bool win = true;
for (std::size_t k{ i }, t{}; win && k < i + columns * columns; k += columns, ++t)
win = data[k] == tips[t]; // t ... i am too lazy to figure out how to calculate
// the index for tips with k, i and columns
if (win)
return true;
}
return false;
}
int main()
{
std::size_t num_tips;
while (std::cout << "Enter a number between 1 and 12: ",
!(std::cin >> num_tips) || num_tips < 1 || 12 < num_tips)
{ // as long as extraction fails or the value is out of range:
std::cerr << "Input error :(\n\n";
clear(std::cin);
}
std::cout << "\nPlease enter " << num_tips << " numbers.\n";
std::vector<int> tips(num_tips);
for (std::size_t i{}; i < num_tips; ++i) {
while (std::cout << i + 1 << ": Enter a number between 1 and 4: ",
!(std::cin >> tips[i]) || tips[i] < 1 || 4 < tips[i])
{ // same as above: check if extraction is ok and a range check
std::cerr << "Input error :(\n\n";
clear(std::cin);
}
}
std::cout << "Your numbers:\n";
// displays all numbers in tips:
std::copy(std::begin(tips), std::end(tips), std::ostream_iterator<int>{ std::cout, " "});
std::cout << "\n\n";
// instead of num_tips arrays of num_tips a vector of
// num_tips * num_tips elements. calculate index with row * num_tips + column
std::vector<int> bingo(num_tips * num_tips);
// a random number generator to pass to fill_grid()
// somewhat similar to the dinosaur std::srand():
std::mt19937 rng{ static_cast<unsigned>(std::chrono::high_resolution_clock::now().time_since_epoch().count()) };
// fills the grid with random number 1...4
fill_grid(bingo, rng);
// print the grid:
print_grid(bingo, num_tips);
// print outcome. if compare_grid() returns true: "You Win! :)\n" if not, the other:
std::cout << (compare_grid(bingo, num_tips, tips) ? "You Win! :)\n" : "You Lose :(\n");
}
Sample "Gameplay":
Enter a number between 1 and 12: 5
Please enter 5 numbers.
1: Enter a number between 1 and 4: 2
2: Enter a number between 1 and 4: 4
3: Enter a number between 1 and 4: 1
4: Enter a number between 1 and 4: 3
5: Enter a number between 1 and 4: 2
Your numbers:
2 4 1 3 2
4 1 3 3 1
4 2 2 4 2
3 3 4 4 4
4 1 2 1 1
2 2 3 3 2
You Lose :(
To sum it up: Default outcome is "You Lose :(". :(
If you'd rather have a "2d" vector:
// ...
std::vector<std::vector<int>> bingo(num_tips); // a vector of vectors with
for (size_t i{}; i < num_tips; ++i) // num_tips rows
bingo[i].resize(num_tips); // for every row resize the row-vector to num_tips
// items
fill_grid(bingo, rng);
print_grid(bingo, num_tips); // no need to pass columns because that information
// is contained within bingo ... bingo.size()
std::cout << (compare_grid(bingo, tips) ? "You Win! :)\n" : "You Lose :(\n");
}
with
void print_grid(std::vector<std::vector<int>> const &data, std::size_t columns)
{
for (auto &row : data) {
for (auto col : row)
std::cout << col << ' ';
std::cout.put('\n');
}
}
void fill_grid(std::vector<std::vector<int>> &data, std::mt19937 &rng)
{
std::uniform_int_distribution<int> dist{ 1, 4 };
for(auto &row : data) // generate random numbers for every row:
std::generate(std::begin(row), std::end(row), [&]() { return dist(rng); });
}
bool compare_grid(std::vector<std::vector<int>> const &data, std::vector<int> const &tips)
{
assert(data.size() == tips.size());
for (std::size_t i{}; i < data.size(); ++i) {
bool win = true;
for (std::size_t k{}; win && k < data.size(); ++k)
win = data[i][k] == tips[k];
if (win)
return true;
}
for (std::size_t i{}; i < data.size(); ++i) {
bool win = true;
for (std::size_t k{}; win && k < data.size(); ++k)
win = data[k][i] == tips[k]; // just switch the indexes to compare
if (win) // columns instead of rows.
return true;
}
return false;
}
Using manual memory management: (ouch)
// ...
std::cout << "\nPlease enter " << num_tips << " numbers.\n";
int *tips = new int[num_tips];
for (std::size_t i{}; i < num_tips; ++i) {
while (std::cout << i + 1 << ": Enter a number between 1 and 4: ",
!(std::cin >> tips[i]) || tips[i] < 1 || 4 < tips[i])
{
std::cerr << "Input error :(\n\n";
clear(std::cin);
}
}
std::cout << "Your numbers:\n";
for (std::size_t i{}; i < num_tips; ++i)
std::cout << tips[i] << ' ';
std::cout << "\n\n";
int **bingo = new int*[num_tips];
for (size_t i{}; i < num_tips; ++i) {
bingo[i] = new int[num_tips];
}
fill_grid(bingo, num_tips, rng);
print_grid(bingo, num_tips);
std::cout << (compare_grid(bingo, tips, num_tips) ? "You Win! :)\n" : "You Lose :(\n");
// cleanup:
delete[] tips;
for (size_t i{}; i < num_tips; ++i)
delete[] bingo[i];
delete[] bingo;
}
with
void print_grid(int **data, std::size_t columns)
{
for (std::size_t row{}; row < columns; ++row) {
for (std::size_t col{}; col < columns; ++col)
std::cout << data[row][col] << ' ';
std::cout.put('\n');
}
}
void fill_grid(int **data, std::size_t columns, std::mt19937 &rng)
{
std::uniform_int_distribution<int> dist{ 1, 4 };
for (std::size_t row{}; row < columns; ++row)
std::generate(&data[row][0], &data[row][columns], [&]() { return dist(rng); });
}
bool compare_grid(int **data, int *tips, std::size_t num_tips)
{
for (std::size_t i{}; i < num_tips; ++i) {
bool win = true;
for (std::size_t k{}; win && k < num_tips; ++k)
win = data[i][k] == tips[k];
if (win)
return true;
}
for (std::size_t i{}; i < num_tips; ++i) {
bool win = true;
for (std::size_t k{}; win && k < num_tips; ++k)
win = data[k][i] == tips[k];
if (win)
return true;
}
return false;
}

How do I print the following pattern using 3 for loops instead of 4?

I'm trying to print the following pattern:
*
**
***
****
*****
****
***
**
*
Now, I know how to do it using 4 for loops:
for(i=1;i<=n;i++)
{
for(j=1;j<=i;j++)
{
cout<<"*";
}
cout<<"\n";
}
to print the first half and to print the second half:
for(i=1;i<=n;i++)
{
for(j=n;j>i;j--)
{
cout<<"*";
}
cout<<"\n";
}
Looking closely, both the outer for loops are the same. i.e.,
for(i=1;i<=n;i++).
Is there anyway to nest both the 'j' for-loops inside the i-for loop?
Using only one loop:
#include <iostream>
#include <string>
int main() {
for (unsigned i = 0; i < 10; ++i)
std::cout << std::string( i < 5 ? (i+1) : 10 - (i+1), '*') << std::endl;
return 0;
}
Would you care for not even three loops, but just two loops?
int n=5, i, j, k;
for (i=0; i<n*2-1; i++)
{
j=i;
if (j >= n)
j=n*2-2-j;
for (k=0; k<=j; k++)
std::cout << '*';
std::cout << std::endl;
}
using 2 loops:
int g=1;
for(int i=0;i<=5;i++){
for (int y=0;y<=i;y+=g){
cout<<"*";
}
cout<<endl;
if (i==4 && g==1){
cout<<"*****";
i=3;
g=-1;
}}
Instead of printing 5 lines, and then another 5, you could print 10, and calculate the number of stars in each line.
for(i = 1; i <= 2*n - 1; i++)
{
for(j = 1; j <= n - abs(i - n); j++)
{
cout<<"*";
}
cout<<"\n";
}
The expression n-abs(i-n) evaluates to i for values of i between 1 and n, and to 2n-i for values of i greater than n.
Just for fun, how about one loop:
for (int i=1, j=0, dir=1; i!=0;) {
cout << '*';
++j;
if (j==i) {
cout << '\n';
j = 0;
i += dir;
if (i==6) {
dir = -1;
i -= 2;
}
}
}
You can do it in one loop (maybe cheating a little bit):
size_t max = 5;
size_t rows = max * 2 - 1;
std::string line(std::string(max, '*') + '\n');
for ( size_t j = 0, k = max; j < rows; ++j ) {
std::cout << line.c_str() + ( j < max ? --k : ++k );
}
I know you didn't ask for it, but for completeness here's one with zero loops (recursion instead):
#include <iostream>
void print_stars(int count)
{
if (count > 0)
{
std::cout << '*';
print_stars(count - 1);
}
}
void print_line(int lines, int stars)
{
if (lines == 1)
print_stars(stars);
else
{
if (stars > 0)
{
print_stars(stars);
std::cout << std::endl;
}
print_line(lines - 1, stars + 1);
std::cout << std::endl;
if (stars > 0)
print_stars(stars);
}
}
int main()
{
int star_count = 5;
print_line(star_count + 1, 0);
return 0;
}
The pattern can be outputted using only one for loop.
Here is a demonstrative program.
#include <iostream>
#include <iomanip>
int main()
{
while ( true )
{
const char c = '*';
std::cout << "Enter non-negative number (0 - exit): ";
unsigned int n;
if ( !( std::cin >> n ) || n == 0 ) break;
std::cout << '\n';
for ( unsigned int i = 1; i < 2 * n; i++ )
{
unsigned int w = i <= n ? i : 2 * n - i;
std::cout << std::setfill( c ) << std::setw( w + 1 ) << '\n';
}
std::cout << std::endl;
}
return 0;
}
If to enter sequentially
5 4 3 2 1 0
then the program output will look the following way
Enter non-negative number (0 - exit): 5
*
**
***
****
*****
****
***
**
*
Enter non-negative number (0 - exit): 4
*
**
***
****
***
**
*
Enter non-negative number (0 - exit): 3
*
**
***
**
*
Enter non-negative number (0 - exit): 2
*
**
*
Enter non-negative number (0 - exit): 1
*
Enter non-negative number (0 - exit): 0
Using the same variables of this well-structured program as function parameters you can write a separate function that outputs the pattern.
Here you are.
#include <iostream>
#include <iomanip>
std::ostream & pattern( unsigned int n, char c = '*', std::ostream &os = std::cout )
{
for ( unsigned int i = 1; i < 2 * n; i++ )
{
unsigned int w = i <= n ? i : 2 * n - i;
os << std::setfill( c ) << std::setw( w + 1 ) << '\n';
}
return os;
}
int main()
{
while ( true )
{
std::cout << "Enter non-negative number (0 - exit): ";
unsigned int n;
if ( !( std::cin >> n ) || n == 0 ) break;
std::cout << '\n';
pattern( n );
std::cout << std::endl;
}
return 0;
}
Take into account that for example it is a bad idea to use the standard class std::string to output the pattern because the program will be inefficient due to allocation and reallocation of the dynamic memory for an object of the class.
If not to use the standard stream manipulators then you can use standard algorithm std::fill_n to hide the inner loop. In this case the program also will have only one explicit loop.
For example
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
while ( true )
{
const char c = '*';
std::cout << "Enter non-negative number (0 - exit): ";
unsigned int n;
if ( !( std::cin >> n ) || n == 0 ) break;
std::cout << '\n';
for ( unsigned int i = 1; i < 2 * n; i++ )
{
unsigned int w = i <= n ? i : 2 * n - i;
*std::fill_n( std::ostream_iterator<char>( std::cout ), w, c ) = '\n';
}
std::cout << std::endl;
}
return 0;
}
#include <iostream>
using namespace std;
int main() {
int i;
int j;
int count = 1;
for(i= 0;i<10;i++) {
if(i < 5) {
for(j=0;j<=i;j++) {
cout<<"*";
}
} else {
for(j=i-count;j>0;j--) {
cout<<"*";
}
count +=2;
}
cout<< "\n";
}
return 0;
}

C++ multiple returns from single function

still pretty new to C++.
Had to write a function in class to count the number of each digit in a multi-dimensional array.
Now I didn't think you could return multiple int values from a single called function and then use all of these returns in a text based answer, so I attempted to return a different value depending on the value requested as parameter for each digit.
The code below is unnecessarily long and I'm still receiving the following errors.
main-1-3.cpp: In function 'int main()':
main-1-3.cpp:12:21: error: too few arguments to function 'int
count_numbers(int(*)[4], int)'
count_numbers(array);
^
main-1-3.cpp:7:12: note: declared here
extern int count_numbers(int array[4][4], int);
With a bit of debugging I could likely fix up these compile errors, but I feel like my method is extremely convoluted and was wondering if it were possible to call the function as:
count_number(array[4][4])
(Removing the need for the Q parameter) and then have count_numbersreturn all ten of the number values and the just output them as text like << ",3:" << three << instead of << ",8:" << count_numbers(array, 8) <<
Anyway, the function.cpp and main.cpp are below.
If anyone could point me in the right direction it would greatly appreciated. Just need to know the correct method so I can condense this code.
function.cpp
#include <iomanip>
#include <locale>
#include <sstream>
#include <string>
#include <iostream>
int count_numbers(int array[4][4], int Q)
{
int X=0;
int Y=0;
int zero=0;
int one=0;
int two=0;
int three=0;
int four=0;
int five=0;
int six=0;
int seven=0;
int eight=0;
int nine=0;
while(X<4)
{
if(array[X][Y]==0)
{
zero=zero+1;
}
if(array[X][Y]==1)
{
one=one+1;
}
if(array[X][Y]==2)
{
two=two+1;
}
if(array[X][Y]==3)
{
three=three+1;
}
if(array[X][Y]==4)
{
four=four+1;
}
if(array[X][Y]==5)
{
five=five+1;
}
if(array[X][Y]==6)
{
six=six+1;
}
if(array[X][Y]==7)
{
seven=seven+1;
}
if(array[X][Y]==8)
{
eight=eight+1;
}
if(array[X][Y]==9)
{
nine=nine+1;
}
Y++;
if(Y==4)
{
Y=0;
X++;
}
}
if(Q==0)
{
return zero;
}
if(Q==1)
{
return one;
}
if(Q==2)
{
return two;
}
if(Q==3)
{
return three;
}
if(Q==4)
{
return four;
}
if(Q==5)
{
return five;
}
if(Q==6)
{
return six;
}
if(Q==7)
{
return seven;
}
if(Q==8)
{
return eight;
}
if(Q==9)
{
return nine;
}
}
main.cpp
#include <iomanip>
#include <locale>
#include <sstream>
#include <string>
#include <iostream>
extern int count_numbers(int array[4][4], int);
int array[4][4] = { {1,2,3,4} , {1,2,3,4} , {1,2,3,4} , {1,2,3,4}};
int main()
{
count_numbers(array);
std::cout << ",0:" << count_numbers(array, 0) << ",1:" << count_numbers(array, 1) << ",2:" << count_numbers(array, 2) << ",3:" << count_numbers(array, 3) << ",4:" << count_numbers(array, 4) << ",5:" << count_numbers(array, 5) << ",6:" << count_numbers(array, 6) <<",7:" << count_numbers(array, 7) << ",8:" << count_numbers(array, 8) << ",9:" << count_numbers(array, 9) << std::endl;
}
PS. Ignore incorrect indentation its just from pasting to this site
PPS. Thanks for any assistance.
EDIT
Thank you "Vlad From Moscow" for the assistance.
My initial (terrible) code would have worked if I'd simply removed the (unintentional) count_number(array); call from main.cpp
However the for loop system proposed by Vlad allowed me to shrink the code by 80%. It now looks like this:
int count_numbers(int array[4][4], int Q)
{
int ans=0;
for(int i=0; i<4; i++)
{
for(int j=0; j<4; j++)
{
ans += array[i][j] ==Q;
}
}
return ans;
}
Thank you for the assistance which was great, I began coding on Python so it was my lack of understanding of loops in C++ which was the real problem here.
Anyway, problem solved..
This call
count_numbers(array);
does not make sense and moreover is invalid because the function requires two arguments instead of one.
The function itself can be written the following way
const size_t N = 4;
size_t count_number( const int ( &a )[N][N], int value )
{
size_t n = 0;
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
n += a[i][j] == value;
}
}
return n;
}
and called like
std::cout << "0: " << count_number( array, 0 )
<< ", 1: " << count_number( array, 1 )
<< ", 2: " << count_number( array, 2 )
<< ", 3: " << count_number( array, 3 )
<< ", 4: " << count_number( array, 4 )
<< ", 5: " << count_number( array, 5 )
<< ", 6: " << count_number( array, 6 )
<< ", 7: " << count_number( array, 7 )
<< ", 8: " << count_number( array, 8 )
<< ", 9: " << count_number( array, 9 )
<< std::endl;
Here is a demonstrative program
#include <iostream>
const size_t N = 4;
size_t count_number( const int ( &a )[N][N], int value )
{
size_t n = 0;
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
n += a[i][j] == value;
}
}
return n;
}
int main()
{
int array[N][N] =
{
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 }
};
bool first = true;
for ( int value = 0; value < 10; ++value )
{
size_t n = count_number( array, value );
if ( n )
{
std::cout << ( first ? first = false, "" : ", " )
<< value << ": " << n;
}
}
std::cout << std::endl;
}
Its output is
1: 4, 2: 4, 3: 4, 4: 4
A more general approach can look the following way
#include <iostream>
#include <iterator>
#include <algorithm>
template <typename InputIterator, typename T>
size_t count_number( InputIterator first,
InputIterator last,
const T &value )
{
size_t n = 0;
for ( ; first != last; ++first )
{
n += std::count( std::begin( *first ), std::end( *first ), value );
}
return n;
}
int main()
{
const size_t N = 4;
int array[N][N] =
{
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 }
};
bool first = true;
for ( int value = 0; value < 10; ++value )
{
size_t n = count_number( std::begin( array ), std::end( array ), value );
if ( n )
{
std::cout << ( first ? first = false, "" : ", " )
<< value << ": " << n;
}
}
std::cout << std::endl;
}
The program output will be the same as it is shown above.
If the array contains only digits that you need to count then the function can look like
const size_t N = 4;
void count_digits( const int ( &a )[N][N], size_t ( &digits)[10] )
{
for ( size_t &x : digits ) x = 0;
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
++digits[a[i][j]];
}
}
}
To call the function you need to declare in main an array like for example
size_t digits[10];
you can return int[] or event better since you are using c++ return vector<int>.
In your function you can replace one, two, .. with something like
vector<int> result(10);
This will create a vector with 10 entries, all of them 0.
Then replace thing like three = three + 1 with result[3] = result[3] + 1 or even more condensed result[3]++
Then at the end you can write ... << ",0:" << result[0] << ... or even do a for loop like:
for (int i = 0; i < 10; ++i) count << "," << i << ":" << result[i];
You can do all this with int[] as well if that's required but you need to take care of allocating and deallocating the memory. vector will simplify your code a lot.

Print heap array in tree format

So I've been trying to implement an algorithm to output a heap array in tree format. For
instance if I have an array like A[10,6,8,2,4,3,6,0,1,3,2,2,1,0,2] I would like the output to be:
10-----6-----2-----0
| | |--1
| |--4-----3
| |--2
|--8-----3-----2
| |--1
|--6-----0
|--2
Update: Solved my question, I made an answer with the code for those interested.
A possible solution is to insert placeholders into the array and thus form a MxN matrix out if it. Then you can simply loop over it, insert a line feed after every row and indent cells having a placeholder.
This C++11 program outputs heap in a little bit different format:
// 10
// ||--------------||
// 6 8
// ||------|| ||------||
// 2 4 3 6
//||--|| ||--|| ||--|| ||--||
// 0 1 3 2 2 1 0 2
#include<iostream>
#include<vector>
#include<sstream>
#include<string>
#include<cmath>
#include<iomanip>
// http://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c
// will be used to compute height of the heap
size_t IntegerLogarithm2(size_t arg) {
size_t logarithm = 0;
while (arg >>= 1) ++logarithm;
return logarithm;
}
// will be used to compute number of elements at the level i
size_t IntegerPower2(size_t arg) {
if(arg)
return (size_t)2 << (arg-1);
else
return 1;
}
// returns total line length for the level
size_t LineLength(size_t level, size_t item_width, size_t spaces_between) {
return IntegerPower2(level) * (item_width + spaces_between) - spaces_between;
}
int main()
{
// The input heap array
std::vector<int> A = {10, 6, 8, 2, 4, 3, 6, 0, 1, 3, 2, 2, 1, 0, 2};
// The heap array split by levels
std::vector<std::vector<int> > levels;
// Height of the heap
size_t levels_number = IntegerLogarithm2(A.size() + 1);
levels.resize(levels_number);
// Now fill the levels
for (size_t i = 0; i < levels.size(); ++i) {
size_t elements_number = IntegerPower2(i);
levels[i].resize(elements_number);
for (size_t j = elements_number - 1, p = 0; p < elements_number; ++j, ++p)
levels[i][p] = A[j];
}
if (levels_number < 1) return 0;
int magnitude = (abs(A[0]) <= 1 ? 1 : abs(A[0]));
size_t tab_width = (size_t)floor(log(double(magnitude)) / log(10.0)) + 1;
// size_t longest_line = LineLength(levels_number - 1, tab_width, tab_width);
std::vector<std::string> text;
text.reserve(levels_number * 2 - 1);
// Do the aligned output to the strings array
for (size_t i = 0; i < levels_number; ++i) {
size_t outer_space_width = IntegerPower2(levels_number - 1 - i) - 1;
size_t inner_space_width = outer_space_width * 2 + 1;
std::string outer_space(outer_space_width * tab_width, ' ');
std::string inner_space(inner_space_width * tab_width, ' ');
std::ostringstream line;
line << outer_space;
if (i > 0) {
std::ostringstream branchline;
std::string joint(tab_width, '|');
std::string branch(inner_space_width * tab_width, '-');
branchline << outer_space;
if (levels[i].size() > 0) {
branchline << joint;
}
bool isline = true;
for (size_t j = 1; j < levels[i].size(); ++j, isline = !isline) {
if(isline)
branchline << branch << joint;
else
branchline << inner_space << std::setfill(' ') <<
std::setw(tab_width) << joint;
}
branchline << outer_space;
text.push_back(branchline.str());
}
if (levels[i].size() > 0) {
line << std::setfill(' ') << std::setw(tab_width) << levels[i][0];
}
for (size_t j = 1; j < levels[i].size(); ++j) {
line << inner_space << std::setfill(' ') <<
std::setw(tab_width) << levels[i][j];
}
line << outer_space;
text.push_back(line.str());
}
// Output the text
for (auto& i : text)
std::cout << i << std::endl;
return 0;
}
Yap, harder than it initially seemed. Effectively does what Sebastian Dressler proposed.
Here is the final implementation. Formatting scales with number length.
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
std::string do_padding (unsigned index, unsigned mlength){
std::string padding;
if (int((index-1)/2) != 0){
return (int((index-1)/2) % 2 == 0) ?
(do_padding(int((index-1)/2),mlength) + std::string(mlength+4,' ') + " ") :
(do_padding(int((index-1)/2),mlength) + std::string(mlength+3,' ') + " |") ;
}
return padding;
}
void printer (std::vector<int> const & tree, unsigned index, unsigned mlength){
auto last = tree.size() - 1 ;
auto left = 2 * index + 1 ;
auto right = 2 * index + 2 ;
std::cout << " " << tree[index] << " ";
if (left <= last){
auto llength = std::to_string(tree[left]).size();
std::cout << "---" << std::string(mlength - llength,'-');
printer(tree,left,mlength);
if (right <= last) {
auto rlength = std::to_string(tree[right]).size();
std::cout << "\n" << do_padding(right,mlength) << std::string(mlength+ 3,' ') << " | ";
std::cout << "\n" << do_padding(right,mlength) << std::string(mlength+ 3,' ') << " └" <<
std::string(mlength - rlength,'-');
printer(tree,right,mlength);
}
}
}
void print_tree (std::vector<int> & tree){
unsigned mlength = 0;
for (int & element : tree){
auto clength = std::to_string(element).size();
if (clength > mlength) {
mlength = std::to_string(element).size();
}
}
std::cout << std::string(mlength- std::to_string(tree[0]).size(),' ');
printer(tree,0,mlength);
}
int main() {
std::vector<int> test;
for(auto i =0; i<50; ++i){
test.push_back(rand() % 1000 + 1);
}
std::make_heap(test.begin(),test.end());
std::cout << "\n";
print_tree(test);
}