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

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;
}

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';
}
}
}
}
}

printing the below pattern using just one loop

ive got the below code to print a pattern (attached below). However i'd like to just use one loop
#include<iostream>
using namespace std;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cout<<"*";
}
for(int j=1;j<=n-i;j++){
if(j%2!=0){
cout<<"_";
}else{
cout<<".";
}
}
cout<<endl;
}
for(int i=1;i<n;i++){
for(int j=1;j<=n-i;j++){
cout<<"*";
}
for(int j=1;j<=i;j++){
if(j%2==0){
cout<<".";
}else{
cout<<"_";
}
}
cout<<endl;
}
}
when n = 5, heres the output.
*_._.
**_._
***_.
****_
*****
****_
***_.
**_._
*_._.
how do i just make this into one single loop
Try this and see how it does what you want to understand the step you did not find on your own:
#include<iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n*2-1; i++) {
if (i <= n)
{
for (int j = 1; j <= i; j++) {
cout << "*";
}
for (int j = 1; j <= n - i; j++) {
if (j % 2 != 0) {
cout << "_";
}
else {
cout << ".";
}
}
cout << endl;
}
else
{
for (int j = 1; j <= n*2 - i; j++) {
cout << "*";
}
for (int j = 1; j <= i-n; j++) {
if (j % 2 == 0) {
cout << ".";
}
else {
cout << "_";
}
}
cout << endl;
}
}
}
I'd like to just use one loop.
I'll take it literally and show a starting point for a possible solution.
// Let's start by figuring out some dimensions.
int n;
std::cin >> n;
int height = 2 * n - 1;
int area = n * height;
// Now we'll print the "rectangle", one piece at a time.
for (int i = 0; i < area; ++i)
{ // ^^^^^^^^
// Extract the coordinates of the char to be printed.
int x = i % n;
int y = i / n;
// Assign a symbol, based on such coordinates.
if ( x <= y and x <= height - y - 1 )
{ // ^^^^^^ ^^^^^^^^^^^^^^^^^^^ Those are the diagonals.
std::cout << '*'; // This prints correctly the triangle on the left...
}
else
{
std::cout << '_'; // <--- But of course, something else should done here.
}
// End of row.
if ( x == n - 1 )
std::cout << '\n';
}
If you look at the pattern, then you can see a sort of "triangles". And this already gives a hint for the solution. Use a triangle function.
Please read about it here.
Then you will notice that always the "aboslute"-function, in C++ std::abs, is involved.
But first of all, it is easily visible that the number rows to print is always the width of a triangle * 2.
And the number of charcters in the pattern, can be calculated by applying the triangle function. Example for width 5:
Number of stars number of dashdot
Row width-abs(row-width) abs(row-width)
1 1 4
2 2 3
3 3 2
4 4 1
5 5 0
6 4 1
7 3 2
8 2 3
9 1 4
And this can be implemented easily now.
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std::string_literals;
int main() {
// Get the max width of the pattern and perform a short input validation
int maxWidth{};
if ((std::cin >> maxWidth) and (maxWidth > 0)) {
// The number of rows for the pattern is dependent on the width. It is a simple relation
const int numberOfRows = 2 * maxWidth;
// Show all rows
for (int row = 1; row < numberOfRows; ++row) {
// Use triangle formular to create star pattern
std::string starPattern(maxWidth - std::abs(row - maxWidth), '*');
// Create dashDot pattern
std::string ddp(std::abs(row - maxWidth), '\0');
std::generate(ddp.begin(), ddp.end(), [i = 0]() mutable { return i++ % 2 ? '.' : '_'; });
// Show output
std::cout << (starPattern+ddp) << '\n';
}
}
else std::cout << "\n*** Error: Invalid input\n\n";
}
Of course you can also create the whole pattern wit std::generate.
Maybe it is too complex for now.
And less understandable.
See:
#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
int main() {
// Get the max width of the pattern and perform a short input validation
if (int width{}; (std::cin >> width) and (width > 0)) {
std::vector<std::string> row(2 * width - 1);
std::for_each(row.begin(), row.end(), [&, r = 1](std::string& s) mutable {
s = std::string(width - std::abs(r - width), '*');
std::string ddp(std::abs(r++ - width),'\0');
std::generate(ddp.begin(), ddp.end(), [&, i = 0]() mutable{ return i++ % 2 ? '.' : '_'; });
s += ddp; std::cout << s << '\n'; });
}
else std::cout << "\n*** Error: Invalid input\n\n";
}

Why am I not able to push a pair after a limit in the vector?

The problem is to find if a given sequence of numbers can form a valid permutation or not. The problem statement is trivial for the real problem. So, I am pushing a pair of integers into the vector. The first part being the number itself and second being 0 or 1.
The code works fine till a sequence 1041 long (specific after debugging a lot). Just to debug I added a print statement after pushing each pair inside the vector. For a length of 1042, the code shows pushed 1040 and then pushed 1 (which is weird) and then just hangs on there.
I am attaching the code as well as the input and terminal output.
You can just check the main function
Code
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
using namespace std;
bool comparator_function(pair<int, int> a, pair<int, int> b) {
return (a.first < b.first);
}
//index_added -> the index at which the latest element was added
void set_r_array(int* r_array_ref, int* per_array_ref, int size, int* count, int index_added) {
for(int i = 1;i <= size; i++) {
count[i] = 0;
}
int temp = index_added;
while(index_added <= size) {
if(index_added == size) {
if(per_array_ref[index_added] == 0) {
r_array_ref[temp] = size;
break;
}
else {
r_array_ref[temp] = -1;
break;
}
}
else {
if(per_array_ref[index_added] == 0) {
r_array_ref[temp] = index_added;
break;
}
else {
index_added++;
}
}
}
for(int i = 1;i <= size; i++) {
if(r_array_ref[i] != -1) {
count[r_array_ref[i]]++;
}
}
}
bool check_max(int* count, int next_element, int size) {
int max_count = -1, index = 0;
for(int i = 1;i <= size; i++) {
int temp_val = count[i];
if(max_count <= temp_val) {
max_count = temp_val;
index = i;
}
}
int num = 0;
for(int i = 1;i <= size; i++) {
if(count[i] == max_count) {
num++;
}
}
//one max
if(num == 1) {
if(next_element == index) {
return true;
}
return false;
}
else {
for(int i = 1;i <= size; i++) {
if(count[i] == max_count) {
if(next_element == i) {
return true;
}
}
}
return false;
}
}
int main() {
int testCases;
cin >> testCases;
cin.ignore();
while(testCases-- > 0) {
int n, result_flag = 0;
cin >> n;
cin.ignore();
vector<pair<int, int>> per;
int temp;
for(int i = 0;i < n; i++) {
cin >> temp;
pair<int, int> temp_pair = make_pair(temp, i+1);
per.push_back(temp_pair);
//debug statement
cout << "pushed " << temp << endl;
}
auto start = std::chrono::high_resolution_clock::now();
cout << "start" << endl;
sort(per.begin(), per.end(), comparator_function);
int permutation_array[n+1], r_array[n+1], count[n+1];
for(int i = 0;i <= n; i++) {
permutation_array[i] = 0;
r_array[i] = i;
count[i] = 1;
}
cout << "end" << endl;
permutation_array[per[0].second] = per[0].first;
set_r_array(r_array, permutation_array, n, count, per[0].second);
//insertion of numbers
for(int i = 1;i < n; i++) {
//check if the next element inserted has the largest count rn or not
int next_element = per[i].second;
if(!check_max(count, next_element, n)) {
cout << "No" << endl;
result_flag = -1;
break;
}
permutation_array[per[i].second] = per[i].first;
set_r_array(r_array, permutation_array, n, count, per[i].second);
}
if(result_flag == 0) {
cout << "Yes" << endl;
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
cout << "Time: " << duration.count() << " microseconds" << endl;
}
}
Input 1
1
5
2 3 4 5 1
Output 1
pushed 2
pushed 3
pushed 4
pushed 5
pushed 1
start
end
Yes
Input 2
1
1042
1 2 3 4 ... so on till 1042
Output 2
pushed 1
pushed 2
.
.
.
pushed 1040
pushed 1
and then hangs, from here on
The complexity of the code is O(n^2). So, I don't think it has to do anything with that. Since the input can be at max 10^4 order. Moreover, according to the print debugging, I think the issue is with the input.
You have issue with input as you reach console line limit.
Put your input into a file should solve that issue.
Then you should be able to debug your algorithm which seems more complicated than needed.

C++ Virtual Galton Board

I have gotten this far in creating my Galton Board but fail to understand how to fix my code in regards to j and columns[j] not being in the main scope. I understand I have not declared them in the main function but not sure how to properly do so to obtain my results.
How do I get this fixed so that it outputs what my intentions are?
My intentions are simply when the code runs to output my data like so:
The number of marbles in slot 0 is 2.
The number of marbles in slot 1 is 4.
and so forth up to 7.
Here is the code I have:
#include <iostream>
#include <ctime>
using namespace std;
//Decide a L or R direction at random
char dropMarble()
{
//If 1 then L
if(rand() % 2)
{
return 'L';
}
//If 2 then R
else
{
return 'R';
}
}
void dropMarble(int columns[], int cols)
{
int i = 0, j = 0;
char LorR;
while((i + j) != cols)
{
LorR = dropMarble();
if(LorR == 'R')
{
//Marble goes right
++j;
}
else
{
//Marble goes left
++i;
}
}
cout << endl;
//Increment the count of marbles in the columns
++columns[j];
}
void printColumns(int columns[], int cols)
{
for(int i = 0; i< cols; ++i)
{
cout << columns[i] << "";
}
cout << endl;
}
int main()
{
srand(time(NULL));
int numberOfMarbles;
int numberOfColumns = 8;
int slots[numberOfColumns];
//Initialize the count of marbles in the columns to zero
for(int i = 1; i <= numberOfColumns; ++i)
{
slots[i] = 0;
}
cout << "Enter the number of marbles to drop: " << endl;
cin >> numberOfMarbles;
for(int i = 1; i <= numberOfMarbles; ++i)
{
cout << "The number of marbles in slot " << j << " is " << columns[j]
<< endl;
dropMarble(slots, numberOfMarbles);
printColumns(slots, numberOfMarbles);
}
return 0;
}
Not very sure what you want to achieve but you can try rewriting 2nd for loop like this -
for(int j = 0; j <= numberOfColumns; ++j) {
cout << "The number of marbles in slot " << j << " is " << slots[j]
<< endl;
dropMarble(slots, numberOfColumns);
printColumns(slots, numberOfColumns);
}
Is this what you're trying to do?
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
//Decide a L or R direction at random
bool dropMarble()
{
if(rand() % 2)
{
return false;
}
else
{
return true;
}
}
void dropMarble(vector<int> &columns, int cols)
{
int i = 0, j = 0;
bool GoneRight=true;
while((i + j) != cols)
{
GoneRight = dropMarble();
if(GoneRight)
{
//Marble goes right
++j;
}
else
{
//Marble goes left
// i is height small i is high, large i is low
++i;
}
}
//Increment the count of marbles in the columns
++columns[j];
}
void printColumns(vector<int> &columns, int cols)
{
for(int i = 0; i< cols; ++i)
{
cout << columns[i] << "";
}
cout << endl;
}
int main()
{
srand(time(NULL));
int numberOfMarbles;
int numberOfColumns = 8;
vector<int> slots;
slots.resize(8);
// int columns[numberOfColumns];
//Initialize the count of marbles in the columns to zero
for(int i = 1; i <= numberOfColumns; ++i)
{
slots[i] = 0;
}
cout << "Enter the number of marbles to drop: " << endl;
cin >> numberOfMarbles;
for(int i = 1; i <= numberOfMarbles; ++i)
{
dropMarble(slots, numberOfColumns);
}
for(int j = 0; j<numberOfColumns;++j){
cout << "The number of marbles in slot " << j << " is " << slots[j]
<< endl;
}
printColumns(slots, numberOfColumns);
return 0;
}
With a 1000 marbles:
The number of marbles in slot 0 is 7
The number of marbles in slot 1 is 30
The number of marbles in slot 2 is 100
The number of marbles in slot 3 is 213
The number of marbles in slot 4 is 262
The number of marbles in slot 5 is 225
The number of marbles in slot 6 is 122
The number of marbles in slot 7 is 34
73010021326322512234
Interesting idea. The key change really is to pass by reference a vector. You don't have to use a vector, you could parse an array via a pointer that would work also.
The other thing was to change the marble printing logic so it's in its own loop, and also to parse the number of columns rather than the number of marbles to your other functions.

C++, sort through array of numbers to find uniqueness

Say I have an array of 4 different numbers.
int numbers[4] = {50234, 50356, 50454, 50934};
How do you make a nested for loop in C++ to sort through these numbers from back to front in order to identify the required amount of digits needed for uniqueness?
From the example you can tell that you'll need 3 digits from the back to make sure no numbers contain similar tails of numbers. 50234, 50934 = 3 digits to have them unique = 502 and 509 respectively.
What would the for loop look like to go through each of these numbers one by one, number by number, and sort out identical numbers to reach an output of 3?
It would go like this:
4
6 - discard this number, it's not identical
4
4
Then:
3
5 - discard this number
3
Then:
2
9 Hurray! No similar numbers anymore, print out 3 being the answer.
I'm stumped and can't figure it out.
Any help would be greatly appreciated, thank you.
Say you start with
#include <unordered_set>
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
const std::vector<int> numbers{50234, 50356, 50454, 50934};
You can transform it into a vector of strings:
std::vector<std::string> string_numbers;
std::for_each(std::begin(numbers), std::end(numbers), [&](int n){ string_numbers.push_back(std::to_string(n)); });
Now we'll check the number of digits required, starting at 1:
size_t digits = 1;
while(true) {
At each iteration, we'll create an unordered_set
std::unordered_set<std::string> partials;
For each number, we'll attempt to place digits digits of it into the set:
for(const auto &s: string_numbers) {
if(s.size() <= digits) {
std::cout << "not unique" << std::endl;
return 0;
}
partials.insert(s.substr(0, digits));
}
If the size of the set is the size of the vector, we're done:
if(partials.size() == numbers.size()) {
std::cout << digits << " required" << std::endl;
return 0;
}
Otherwise, we need to increase the number of digits:
++digits;
}
}
Full code:
#include <unordered_set>
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
const std::vector<int> numbers{50234, 50356, 50454, 50934};
std::vector<std::string> string_numbers;
std::for_each(std::begin(numbers), std::end(numbers), [&](int n){ string_numbers.push_back(std::to_string(n)); });
size_t digits = 1;
while(true) {
std::unordered_set<std::string> partials;
for(const auto &s: string_numbers) {
if(s.size() <= digits) {
std::cout << "not unique" << std::endl;
return 0;
}
partials.insert(s.substr(0, digits));
}
if(partials.size() == numbers.size()) {
std::cout << digits << " required" << std::endl;
return 0;
}
++digits;
}
}
if you want to sort numbers so use one of sort algorithms let's say bubble sort. then check for uniqueness and store the unique values in a new array then print them:
we make our code for understanding and practice but in a real program we use libraries they are too much powerful and quick:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int numbers[4] = {50234, 50356, 50454, 50934};
// int numbers[4] = {50234, 50356, 50454, 50356};
for(int i(0); i < 4; i++)
{
for(int j(i + 1); j < 4; j++)
{
if(numbers[i] > numbers[j])
{
numbers[i] ^= numbers[j];
numbers[j] ^= numbers[i];
numbers[i] ^= numbers[j];
}
}
}
for(int i = 0; i < 4; i++)
cout << numbers[i] << ", ";
int nUniq = 0;
bool isUniq = true;
for(int i = 0; i < 4; i++)
{
isUniq = true;
for(int j(i + 1); j < 4; j++)
{
if(numbers[i] == numbers[j])
{
isUniq = false;
break;
}
}
if(isUniq)
nUniq++;
}
cout << nUniq << endl;
int* ptrUniq = new int[nUniq];
int k = 0;
for(int i = 0; i < 4; i++)
{
isUniq = true;
for(int j(i + 1); j < 4; j++)
{
if(numbers[i] == numbers[j])
{
isUniq = false;
break;
}
}
if(isUniq)
{
ptrUniq[k] = numbers[i];
k++;
}
}
cout << "\nhere are uniq values:\n\n";
for(int i = 0; i < nUniq; i++)
cout << ptrUniq[i] << ", ";
delete[] ptrUniq;
ptrUniq = NULL;
cout << endl << endl;
return 0;
}