Reversing Rectangle character after certain height - c++

I am stuck in some tricky part. I have to reverse the rectangle character after certain height in c++ like below
111111111
122222221
123333321
123333321
122222221
111111111
in above i have to reverse rectangle character after height 3. My code works well in for first three rows but it didn't work for reversing. Input Rows 6 and Columns 9. Can any one tell where i am doing in my code. Below is my code
void Rectangle(int rows, int cols){
int mid = rows / 2, midcol = cols / 2;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
if (i > j)
{
if (i <= mid)
{
cout << j;
}
else if (j < midcol)
{
cout<< j;
}
else if (j == midcol)
{
cout<<cols - j - 1;
}
else
{
cout<<cols - j;
}
}
else if (i > cols - j)
{
cout<< cols - j + 1;
}
else
{
cout<< i;
}
}
cout << endl;
}
}
int main() { // Get the number
int row;
int columns;
cout<<"plase enter a Row height:";
cin >> row;
cout<<"plase enter a Columns:";
cin >> columns;
Rectangle(row, columns);
system("pause");
return 0;
}

We can observe the following.
Up to the mid column, the values are the column values, but not higher then the row values.
Over the middle column the column numbers are revered. What does this mean? If you have 10 columns and want to reverse it, then you have to subtract the column number from the width 10. So
10-6 = 4
10-7 = 3
10-8 = 2
10-9 = 1
10-10 = 0;
The same is valid for the rows.
So, for normal columns (< middle value). the column number
For column numbers above the middle, the reversed column number (see above)
But not bigger then the limited row value
The limited row value is calculated as per the above scheme
In my demo program I use a std::vector<std::vector<int>> to store the values. Calculated values start with 0. So I add 1 for each value add the end.
Please see:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cmath>
void showRectangle(const size_t height, const size_t width) {
std::vector lines{ height, std::vector(width, 0U) };
// Calculate the vales in the middle
const size_t midHeight{ static_cast<size_t>(std::ceil(height / 2.0)) };
const size_t midWidth{ static_cast<size_t>(std::ceil(width / 2.0)) };
// Iterate over all rows and columns
for (size_t row{ 0U }; row < height; ++row) {
for (size_t column{ 0U }; column < width; ++column) {
// Calculate the vaule for row and column
lines[row][column] = (std::min((column >= midWidth) ? (width - column-1) : column,
(row >= midHeight) ? (height - row - 1) : row)) +1 ;
}
}
// Show output
for (const std::vector<size_t>& vi : lines) {
std::copy(vi.begin(), vi.end(), std::ostream_iterator<size_t>(std::cout));
std::cout << "\n";
}
}
int main() {
// Explain the user that he has to enter the height in rows
std::cout << "\nEnter the height of the rectangle in rows: ";
// Get the height. And check, if input worked
if (size_t height{}; std::cin >> height) {
// Explain the user that he has to enter the width in columns
std::cout << "Enter the width of the rectangle in columns: ";
if (size_t width{}; std::cin >> width) {
// SHow result
std::cout << "\n\nResulting rectangle:\n\n";
showRectangle(height, width);
}
else {
std::cerr << "\n*** Error: wrong input for width\n";
}
}
else {
std::cerr << "\n*** Error: wrong input for height\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';
}
}
}
}
}

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

I have to do a program that do a square in c++ with incremental letter

Hello and thank you for coming here.
I have to do a program that will draw a number of square choosed by the user with incremental letter.
For example, if the user choose 4 square, it will return :
DDDDDDD
DCCCCCD
DCBBBCD
DCBABCD
DCBBBCD
DCCCCCD
DDDDDDD
At the time being, my code look like this ;
#include <iostream>
using namespace std;
int main()
{
int size;
int nbsquareletter;
cout << " How many square ?" << endl;
cin >> nbsquareletter;
size = nbsquareletter * 2 - 1;
char squareletter = 'a';
for (int row = 1; row <= size; ++row)
{
for (int col = 0; col <= size; ++col)
{
if (row < col) {
cout << (char)(squareletter + row - 1) << " ";
}
else if (row > col)
{
cout << (char)(squareletter + col) << " ";
}
/*
cout << col << " ";
cout << row << " ";
*/
}
cout << endl;
}
}
If you have any ideas to help me, don't hesitate, I'm struggling. it's been 3.5 hours. Thanks you for reading and have a good day !
Try to keep things simple. If you start write code before you have a clear idea of how to solve it you will end up with convoluted code. It will have bugs and fixing them will make the code even less simple.
Some simple considerartions:
The letter at position (i,j) is determined by the "distance" from the center. The distance is max(abs(i - i_0), abs(j - j_0).
The center is at (i,j) = (size-1,size-1) when we start to count at upper left corner (0,0).
The letters can be picked from an array std::string letters = "ABCDEFG...".
i and j are in the range [0,2*size-1)
Just writing this (and nothing more) down in code results in this:
#include <iostream>
#include <string>
void print_square(int size){
std::string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i_0 = size-1;
int j_0 = size-1;
for (int i=0;i< 2*size-1;++i){
for (int j=0;j< 2*size-1;++j) {
int index = std::max(std::abs(i-i_0),std::abs(j-j_0));
std::cout << letters[index];
}
std::cout << "\n";
}
}
int main() {
print_square(4);
}
Which produces output
DDDDDDD
DCCCCCD
DCBBBCD
DCBABCD
DCBBBCD
DCCCCCD
DDDDDDD
Your code cannot print the right output, because when row == col there is no output, and it misses the diagonal. I didnt look further than that.
Instead of fixing bugs in your code I decided to suggest you my own solution. Maybe some other answers will be related to bugs in your code.
On piece of paper I figured out 4 different formulas for 4 parts of a drawn picture, formulas computing what letter to take inside English alphabet. Afterwards I take this letter from array with alphabet.
Try it online!
#include <iostream>
int main() {
int n = 0;
std::cin >> n;
char const letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < 2 * n - 1; ++i) {
for (int j = 0; j < 2 * n - 1; ++j)
std::cout << letters[
i <= j && i + j < 2 * n - 1 ? n - i - 1 :
i <= j && i + j >= 2 * n - 1 ? j - n + 1 :
i > j && i + j < 2 * n - 1 ? n - j - 1 :
i > j && i + j >= 2 * n - 1 ? i - n + 1 : 25
];
std::cout << std::endl;
}
}
Input:
7
Output:
GGGGGGGGGGGGG
GFFFFFFFFFFFG
GFEEEEEEEEEFG
GFEDDDDDDDEFG
GFEDCCCCCDEFG
GFEDCBBBCDEFG
GFEDCBABCDEFG
GFEDCBBBCDEFG
GFEDCCCCCDEFG
GFEDDDDDDDEFG
GFEEEEEEEEEFG
GFFFFFFFFFFFG
GGGGGGGGGGGGG
Let's define some functions, to make the recurrence relation obvious.
std::vector<std::string> WrapInLetter(char letter, std::vector<std::string> lines)
{
for (auto & line : lines)
{
line.insert(line.begin(), letter);
line.insert(line.end(), letter);
}
std::size_t size = (lines.size() * 2) + 1;
std::string edge(size, letter); // A string formed of size copies of letter
lines.insert(lines.begin(), edge);
lines.insert(lines.end(), edge);
return lines;
}
std::vector<std::string> SquareLetter(char letter)
{
if (letter == 'A') return { "A" };
return WrapInLetter(letter, SquareLetter(letter - 1));
}
Now main just has to call that function and loop over the result.
int main()
{
std::cout << "How many square ?" << std::endl;
int size;
std::cin >> size;
for (auto line : SquareLetter('A' + size - 1))
{
std::cout << line << std::endl;
}
}

How to extract the indexes of the cells in the same diagonal of a 2D matrix C++

As stated above, I am trying to get the elements of a 2D matrix using only C++
The matrix has MxN dimensions, and it may be so that N!=M, N >= M or M < N (basically the dimensions can be anything and are determined in execution time)
I have tried to go about it using 2 nested for loops but so far the code just keeps getting more & more complex & does not produce consistent results.
Visual aid:
I am trying to get the 2nd for loop to iterate through the colored cells of the matrix starting from top left - i.e. in every loop the amount/position of the cells that the 2nd loop iterates through keeps changing & I am starting to wonder whether this can be done at all given that N & M are not known on compile time.
Thanks for your time in advance.
~EDIT1:
Here is what the iteration of the elements would look like for a non square matrix (same thing applies if the rows where more than the columns)
~EDIT2:
Here is the code so far: (testable!)
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
void func(void);
// use these variables to specify the dimensions arbitrarily
// keep in mind I need this to work with relatively big matrices
int row = 5, col = 5;
string arr[][10]= {{"0", "0", "0", "0", "0", "0", "0", "0", "0", "0" },
{"0", "1,1", "1,2", "1,3", "1,4", "1,5", "1,6", "1,7", "1,8", "1,9" },
{"0", "2,1", "2,2", "2,3", "2,4", "2,5", "2,6", "2,7", "2,8", "2,9" },
{"0", "3,1", "3,2", "3,3", "3,4", "3,5", "3,6", "3,7", "3,8", "3,9" },
{"0", "4,1", "4,2", "4,3", "4,4", "4,5", "4,6", "4,7", "4,8", "4,9" },
{"0", "5,1", "5,2", "5,3", "5,4", "5,5", "5,6", "5,7", "5,8", "5,9" },
{"0", "6,1", "6,2", "6,3", "6,4", "6,5", "6,6", "6,7", "6,8", "6,9" },
{"0", "7,1", "7,2", "7,3", "7,4", "7,5", "7,6", "7,7", "7,8", "7,9" },
{"0", "8,1", "8,2", "8,3", "8,4", "8,5", "8,6", "8,7", "8,8", "8,9" },
{"0", "9,1", "9,2", "9,3", "9,4", "9,5", "9,6", "9,7", "9,8", "9,9" } };
bool f = false, f2 = false;
int main (void)
{
func();
return 0;
}
void func(void)
{
if(row < col)
{
//remember that row > col
f = true;
}
unsigned short m_i; //mask for the counter of the outer for loop (i) - counts how many times the
unsigned short j_end = 1; //stores the max number of iterations the inner loop should do - increments accordingly
unsigned short k = 1; //stores the starting index of the inner loop - starts incrementing once (j_end == col)
cout << "row = " << row << ", col = " << col << endl;
cout << "total \"i\" loops " << (row + col -1) << endl << endl;
for (unsigned short i=1; i<=row + col -1; i++) // row + col -1 is the total number of diagonals in any matrix
{ // and also the total number of iterations we need
if( i > row) // here I implement the row > col scenario, the rest should be similar
{
m_i = row; // the mask should never go above the max row number
}else if(i == row)
{
m_i = row;
if (f = true) f2 = true; // using f2 remember that we've reached the max number for rows
}else{
m_i = i; // (i < row) so just pass i
}
for(unsigned short j=k; j<=j_end; j++){
cout<< arr[m_i][j]<<" ";
if(m_i > 1){
m_i--;
}else{
m_i = 1;
}
}
cout<<endl<< "*************" << endl;
if(j_end == col )
{
k++; // increment starting index of inner loop
}else{
j_end++; // max number for inner loop not yet achieved so increment max number
}
if(m_i == row)
{
k++;
}
} // end outer loop
} // end func
You can use this code to test it for yourself the output should be something like this:
And you can change the row & col values to test for different dimensions.
So far I believe this code works for square matrices, but not so much when row != col
~EDIT3:
func() should take performance into consideration as I said before I expect the matrices to be quite large!
for( int manhattan_distance = 0; manhattan_distance < M + N - 1; ++manhattan_distance )
{
for( int i = 0; i <= manhattan_distance; ++i )
{
int j = manhattan_distance - i;
if( j < N && i < M )
{
...
}
}
}
Code:
#include <vector>
#include <utility>
#include <iostream>
int main() {
int n, m;
std::cin >> n >> m;
std::vector<std::pair<int, int> > result;
for (int k = 0; k < m; k++) {
int i = 0, j = k;
while (i < n && j >= 0)
{
result.push_back({ i, j });
i++;
j--;
}
}
for (int k = 1; k < n; k++) {
int i = k, j = m - 1;
while (i < n && j >= 0)
{
result.push_back({ i, j });
i++;
j--;
}
}
return 0;
}
Explanations:
If you look at the picture, you can see that diagonal is when you move i + 1 and j - 1. Until the first half, we start from the first row and try to go in direction specified. When we hit the end, we just go to the next column. Basically, every iteration we are just changing the starting point. The second part is a bit trickier, because we already traversed some of the lines, so we start from 1 (because we already traversed first row. Then applying the same direction as in the first half, we traverse the rest of the matrix.
You can do it like this:
void foo(int rows,int cols){
// first go vertically down
for (int start_row = 0;start_row<rows;start_row++){
int col = 0;
int row = start_row;
while (col < cols && row >= 0){
std::cout << row << "," << col << " ";
row--;
col++;
}
std::cout << std::endl;
}
// now horizantally
for (int start_col = 0;start_col<cols;start_col++){
int col = start_col;
int row = rows-1;
while (col < cols && row >= 0){
std::cout << row << "," << col << " ";
row--;
col++;
}
std::cout << std::endl;
}
}
It might be possible to write it more compact, but it works.
OK I got an answer for this, all thought its not refined.
It is working properly but it is not optimized.
EDIT: c#... did not see it was for c++, but the idea is the same
using System;
Random r = new Random();
int rows = r.Next(10,13); // or any range of rows
int cols = r.Next(10,20); // same applies
int[,] matrix = new int[rows,cols];
// mark upper diagonal
for(var i=0; i<= cols; i++)
markByCol(i,0,cols-i);
// mark lower diagonal
for(var i=1; i<= rows; i++)
markByCol(cols+1+i,i,cols-1);
// stringify matrix to view it properly
string line = string.Empty;
for(int i=0; i< rows; i++)
{
line = string.Empty;
for(int j=0; j< cols; j++)
{
line+= matrix[i,j]+" | ";
}
Console.WriteLine(line);
}
// the actual function
int markByCol(int marker,int row,int col){
if((row > -1 && row < rows) && (col > -1 && col < cols))
{
matrix[row,col] = marker;
return markByCol(marker,row+1,col-1);
}
else
return 0;
}
Here is a jsFiddle. just hit play. This implementation marks each diagonal with a specific integer so you can scan and categorize each cell by its value, in terms of which diagonal crosses it.
https://dotnetfiddle.net/Qy8J1O

Simple dynamic programming exercise [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Let's have a field (of given dimensions) of little squares with a value on each square. From each square, one can move only to the square directly below, or the one diagonally to the left or right. The task is to find the maximum combined value of a journey through the field.
For example for the input
1
6 5
3 1 7 4 2
2 1 3 1 1
1 2 2 1 8
2 2 1 5 3
2 1 4 4 4
5 2 7 5 1
the output should be 32, but my code outputs 20.
My approach was to exhaustively try all the possible routes through the field in the following manner:
y == last_row return value[x,y]
f(x,y)
y != last_row return value[x,y] + max(f(x-1,y+1),f(x,y+1),f(x+1,y+1))
Is there an error in my approach, in my code, or both?
The code is here:
#include <iostream>
#include <vector>
#include <limits>
using namespace std;
typedef int T;
T max(T x, T y, T z) {
if(x < y) {
if(y < z) return z;
else return y;
}
else {
if(y > z) return x;
else {
if(x > z) return x;
else return z;
}
}
}
//Finds the maximum amount of stones possibly gathered by following coordinates x,y
//The topmost left is (0,0), bottom right is (columns-1,rows-1)
T max_stones_found_following(T x, T y, vector< vector<T> > A) {
//Reached the last row?
if(y == A.size()-1) return A[x][y];
else {
T went_left, went_right, went_down;
if(x-1 >= 0) went_left = max_stones_found_following(x-1, y+1, A);
else went_left = numeric_limits<T>::min();
if(x+1 <= A[x].size()-1) went_right = max_stones_found_following(x+1, y+1, A);
else went_right = numeric_limits<T>::min();
went_down = max_stones_found_following(x, y+1, A);
return A[x][y] + max(went_left, went_right, went_down);
}
}
int main() {
//Initialization
T test_cases, rows, columns, stones_found, max_stones;
vector< vector<T> > A;
cin >> test_cases;
while(test_cases--) {
//Field input
cin >> rows >> columns;
for(int i = 0; i < rows; i++) {
vector<T> row;
for(int j = 0; j < columns; j++) {
T in;
cin >> in;
row.push_back(in);
}
A.push_back(row);
}
max_stones = 0;
stones_found = 0;
//Try starting at different positions in the first row
for(int i = 0; i < columns; i++) {
stones_found = max_stones_found_following(i, 0, A);
if(stones_found > max_stones) max_stones = stones_found;
}
//Output
cout << max_stones << endl;
}
return 0;
}
Some of your problems:
Method max is more complex that needed. You are making to many comparison to find the max. See bellow.
Your principal problem is using i and j inverted, according to the calling site i means the column where to start in the row 0 and in the method max_stones_found_following you are using as the row of the matrix of values.
Fixed Code (by the way it's a really slow solutions for big input data, and not dynamic programming):
#include <iostream>
#include <vector>
#include <limits>
using namespace std;
typedef int T;
T max(T x, T y, T z) {
return std::max(x, std::max(y, z));
}
// Finds the maximum amount of stones possibly gathered by following coordinates
// x,y
// The topmost left is (0,0), bottom right is (columns-1,rows-1)
T max_stones_found_following(T x, T y, vector<vector<T>> A) {
// Reached the last row?
if (y == A.size() - 1)
return A[y][x];
else {
T went_left, went_right, went_down;
if (x - 1 >= 0)
went_left = max_stones_found_following(x - 1, y + 1, A);
else
went_left = numeric_limits<T>::min();
if (x + 1 <= A[y].size() - 1)
went_right = max_stones_found_following(x + 1, y + 1, A);
else
went_right = numeric_limits<T>::min();
went_down = max_stones_found_following(x, y + 1, A);
return A[y][x] + max(went_left, went_right, went_down);
}
}
int main() {
// Initialization
T test_cases, rows, columns, stones_found, max_stones;
vector<vector<T>> A;
cin >> test_cases;
while (test_cases--) {
// Field input
cin >> rows >> columns;
for (int i = 0; i < rows; i++) {
vector<T> row;
for (int j = 0; j < columns; j++) {
T in;
cin >> in;
row.push_back(in);
}
A.push_back(row);
}
max_stones = 0;
stones_found = 0;
// Try starting at different positions in the first row
for (int i = 0; i < columns; i++) {
stones_found = max_stones_found_following(i, 0, A);
if (stones_found > max_stones)
max_stones = stones_found;
}
// Output
cout << max_stones << endl;
}
return 0;
}
See definition of dynamic programming. It's applicable to solve problems that:
Can be break into sub-problems.
And this sub-problems overlaps some how.
Ex: this problem can be divided into sub-problems as, what is the best path from row 0 -> row i. With this in mind the problem of the best path to row i, only depend of the best paths to row i-1 and the values of the matrix for the ith row. Using this you extend the solution to row i until reach last row.
In the last row would be the best path until every column of that row, search the max of this.
Source Code (Dynamic Programming):
#include <algorithm>
#include <iostream>
#include <vector>
typedef std::vector<int> row_t;
typedef std::vector<row_t> matrix_t;
int main() {
// Initialization
int test_cases, rows, columns;
matrix_t A;
std::cin >> test_cases;
while (test_cases--) {
std::cin >> rows >> columns;
for (int i = 0; i < rows; i++) {
row_t row(columns);
int in;
for (int j = 0; j < columns; j++) {
std::cin >> in;
row[j] = in;
}
A.push_back(row);
}
// Dynamic Programming Here
// For storage the best path until each cell
matrix_t best_A (rows, row_t(columns, 0));
std::copy(A[0].cbegin(), A[0].cend(), best_A[0].begin());
for (int i = 1; i < rows; i++) {
for (int j = 0; j < columns; j++) {
// right down
if (j > 0 && best_A[i - 1][j - 1] + A[i][j] > best_A[i][j]) {
best_A[i][j] = best_A[i - 1][j - 1] + A[i][j];
}
// left down
if (j < columns - 1 && best_A[i - 1][j + 1] + A[i][j] > best_A[i][j]) {
best_A[i][j] = best_A[i - 1][j + 1] + A[i][j];
}
// down
if (best_A[i - 1][j] + A[i][j] > best_A[i][j]) {
best_A[i][j] = best_A[i - 1][j] + A[i][j];
}
}
}
// End Dynamic Programming
auto it = std::max_element(best_A[best_A.size() - 1].cbegin(), best_A[best_A.size() - 1].cend());
// Output
std::cout << *it << std::endl;
}
return 0;
}
As commented previously you can calculate the best path to row i reading only the first i rows, you could do it on the fly (when reading, read first rows, calculate best starting positions, read second row, calculate best path until every column of second row, and so on), this is very good if the input is really, really big. You also don't need to save the best path until rows 1..i, you only need to have the last row calculated and the best paths of the actual row calculating.
Dynamic programming is a great way to approach this problem. But like anonymous commented, you aren't using it, or at least not in a clear fashion.
If you have C columns, then you have C possible starting locations, and C second locations, but there are 3*C - 2 pairs of (first, second). The way to leverage dynamic programming is to note the Markov nature, and for each cell in the second row, of all paths ending in that cell, keep only the one with the best score.
Then for each additional row, you again evaluate 3*C - 2 paths, keeping only C of them.
Repeat until you reach the bottom.
Implementation-wise, you should have a vector of C "best" paths to the current row, and build the vector of C best paths to the next row. Then the next row becomes the current row (use vector::swap). Each "path" must store at minimum the accumulated value, but storing the history of locations visited might also be nice.
In fact, you never even need to store the entire grid in memory. You can perform all processing for each row as you read it.
NOTE: Use of dynamic programming here makes the complexity R*C instead of C * 3^R
It was actually a lot of fun coming up with a real solution. Warning: pointers ahead!
#include <iostream>
#include <sstream>
#include <vector>
void solve_one_case();
int main(int argc, char** argv)
{
/* driver */
const std::string input = "6 5\n"
"3 1 7 4 2\n"
"2 1 3 1 1\n"
"1 2 2 1 8\n"
"2 2 1 5 3\n"
"2 1 4 4 4\n"
"5 2 7 5 1";
std::stringbuf inputstream(input, std::ios_base::in);
auto const oldbuf = std::cin.rdbuf();
std::cin.rdbuf(&inputstream);
solve_one_case();
std::cin.rdbuf(oldbuf);
return 0;
}
void solve_one_case()
{
/* get board size from input */
int rows = 1, columns = 1;
std::cin >> rows >> columns;
std::vector<char> route(rows * columns, '|');
/* get first row from input */
std::vector<int> current_row, prev_row;
current_row.resize(columns);
for( int& start_score : current_row )
std::cin >> start_score;
/* get all cells from input, solving */
char* pRoute = &route[columns];
for( int row = 1; row < rows; ++row ) {
prev_row = current_row;
int cell = 0;;
for( int column = 0; column < columns; ++column )
{
std::cin >> cell;
if (column > 0 && prev_row[column-1] > current_row[column]) {
current_row[column] = prev_row[column-1];
*pRoute = '\\';
}
if (column + 1 < columns && prev_row[column+1] > current_row[column]) {
current_row[column] = prev_row[column+1];
*pRoute = '/';
}
current_row[column] += cell;
++pRoute;
}
}
/* find best value in final row */
int best_score = current_row[0], best_end = 0;
for( int i = 1; i < columns; ++i ) {
if (best_score < current_row[i]) {
best_score = current_row[i];
best_end = i;
}
}
std::cout << "Best score is " << best_score << "\n";
/* backtrack along route */
int route_column = best_end;
for( int row = 0; row < rows; ++row ) {
char breadcrumb = '*';
pRoute -= columns;
std::swap(pRoute[route_column], breadcrumb);
switch (breadcrumb) {
case '/': ++route_column; break;
case '\\': --route_column; break;
}
}
/* print routes */
pRoute = &route[0];
for( int row = 0; row < rows; ++row ) {
std::cout.write(pRoute, columns);
pRoute += columns;
std::cout << '\n';
}
std::cout << std::flush;
}
Output:
Best score is 32
||*||
|/|*\
//|\*
/||*|
||*|\
|/*||