Simple dynamic programming exercise [closed] - c++
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
||*||
|/|*\
//|\*
/||*|
||*|\
|/*||
Related
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"; }
Reversing Rectangle character after certain height
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"; } }
USACO 2006 FortMoo DP Bug
I am currently doing a practice problem from the USACO 2006 Contest, which is basically the following: Given a grid of dots and X's such as ...... ..X..X X..X.. ...... ..X... find the rectangle with the biggest area such that the perimeter of the rectangle includes no X's. For example, the rectangle denoted by the f's is the best possibility. .ffff. .fX.fX Xf.Xf. .ffff. ..X... Here is the original problem statement. So far, I've written a code that runs with the correct output for 11 out of the 13 test cases, but two of the last test cases don't work. Here is my code. #include <iostream> using namespace std; #define INF 0x3f3f3f3f const int MAX = 200 + 5; int N, M, MAXAREA = 0; bool ok[MAX][MAX][MAX], land[MAX][MAX]; int main() { /// read in input // land[i][j] = 1 if there is a swampy area at (i, j) cin >> N >> M; for(int i = 0; i < N; i++) { for(int j = 0; j < M; j++) { char ch; cin >> ch; land[i][j] = (ch == 'X'); } } /// precompute crossing lines // ok[col][row1][row2]: there are not X's from row1 to row2 in column col for(int col = 0; col < M; col++) for(int row1 = 0; row1 < N; row1++) for(int row2 = row1; row2 < N; row2++) { if(land[row2][col]) break; else ok[col][row1][row2] = true; } /// run dynamic programming // first loop through all pairs of rows for(int row1 = 0; row1 < N; row1++) { for(int row2 = row1; row2 < N; row2++) { // for each pair of rows, go from left to right for columns. lhs_col = LHS column for(int lhs_col = 0; lhs_col < M; ) { // find the first LHS column that has no X's at all if(!ok[lhs_col][row1][row2]) { lhs_col++; continue; } // next_col & last_col are next & last columns that are perfectly clear int cur_col = lhs_col, next_col = INF, last_col = lhs_col; // make sure cur_col has top and bottom vertices clear while(cur_col < M && !land[row1][cur_col] && !land[row2][cur_col]) { // finds the first and last column that are perfectly clear if(ok[cur_col][row1][row2]) next_col = min(next_col, last_col = cur_col); cur_col++; } // get maximum area MAXAREA = max(MAXAREA, (row2 - row1 + 1) * (last_col - lhs_col + 1)); // if there is no next_col that is perfectly clear or the next one is itself if(next_col == INF || next_col == lhs_col) break; else lhs_col = next_col; } } } /// output answer cout << MAXAREA << endl; } And here is one of the input cases that causes it to not work. My code outputs 966 while it should be 1488. The other test case is so large, there is no point in pasting it here. I'd greatly appreciate any help. Thank you so much!
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
Recursive Sudoku solver almost working but getting stack overflow for empty grid
I'm trying to solve Sudoku by recursive. The program working great. The problem is that the stack is only keep-able of 4-6K recursive. That's mean that if I'm leaving the soduku with more than 6-7 empty cells, the combination needed to solve it is: 4^7 = 16384 > 4-5K... How can I improve my program to work with less calls? The program is working good out of this problem. The function: void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N]) is all the business. I give you here all the numbers you need for correct soduku to not wast your time. You can some of them out and see how it's work: 0 0 1 0 1 2 0 2 3 0 3 4 1 0 4 1 1 3 1 2 2 1 3 1 2 0 3 2 1 1 2 2 4 2 3 2 3 0 2 3 1 4 3 2 1 3 3 3 -1 and the code: #include <iostream> using namespace std; const int N = 2; void zero_soduku(int soduku[][N*N]); void zero_arr(int temp_arr[], int size); void get_input(int soduku[][N*N], bool fixed_values[][N*N]); void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N]); bool check_soduku(const int soduku[][N*N]); bool check_rows(const int soduku[][N*N]); bool check_cols(const int soduku[][N*N]); bool check_sub_interval(const int soduku[][N*N]); void print_soduku(const int soduku[][N*N]); int main() { int soduku[N*N][N*N] = { 0 }, row = 0, col = 0; bool fixed_values[N*N][N*N] = { false }; get_input(soduku, fixed_values); solve_soduku(soduku, row, col, fixed_values); cout << endl; print_soduku(soduku); system("pause"); return EXIT_SUCCESS; } bool check_soduku(const int soduku[][N*N]) { if (check_rows(soduku) && check_cols(soduku) && check_sub_interval(soduku)) return true; return false; } bool check_rows(const int soduku[][N*N]) { int temp_arr[N*N] = { 0 }; for (auto i = 0; i < N*N; i++) { zero_arr(temp_arr, N*N); for (auto j = 0; j < N*N; j++) temp_arr[soduku[i][j] - 1]++; for (auto k = 0; k < N*N; k++) if (temp_arr[k]>1) return false; } return true; } bool check_cols(const int soduku[][N*N]) { int temp_arr[N*N] = { 0 }; for (auto i = 0; i < N*N; i++) { zero_arr(temp_arr, N*N); for (auto j = 0; j < N*N; j++) temp_arr[soduku[j][i] - 1]++; for (auto k = 0; k < N*N; k++) if (temp_arr[k]>1) return false; } return true; } bool check_sub_interval(const int soduku[][N*N]) { int temp_arr[N*N] = { 0 }; for (auto rows_intervals = 0; rows_intervals < N; rows_intervals++) for (auto cols_intervals = 0; cols_intervals < N; cols_intervals++) for (auto i = rows_intervals*N; i < rows_intervals*N + N; i++) for (auto j = cols_intervals*N; j < cols_intervals*N + N; j++) { temp_arr[soduku[i][j] - 1]++; //end of interval, check if !good interval if (i == rows_intervals*N + N - 1 && j == cols_intervals*N + N - 1) { for (auto k = 0; k < N*N; k++) if (temp_arr[k]>1) return false; zero_arr(temp_arr, N*N); } } return true; } void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N]) { static int counter = 0; counter++; cout << endl << counter << endl; //Not empty cell if (soduku[row][col] != 0) //Not end of line if (col < N*N - 1) { col++; solve_soduku(soduku, row, col, fix_v); } else //Not end of rows if (row < N*N - 1) { row++; col = 0; solve_soduku(soduku, row, col, fix_v); } else //end of soduku if (check_soduku(soduku)) { print_soduku(soduku); return; } /////// Finishd soduku but answaer not good ////////////////// else //Last cell not max if (soduku[row][col] < N*N - 1) { soduku[row][col]++; print_soduku(soduku); cout << endl; solve_soduku(soduku, row, col, fix_v); } //Last cell max, going back... else { while (soduku[row][col] == N*N || fix_v[row][col]) { if (!fix_v[row][col]) { soduku[row][col] = 1; print_soduku(soduku); cout << endl; } if (col > 0) { col--; continue; } if (col == 0 && row > 0) { col = N*N - 1; row--; } } if (!fix_v[row][col]) { soduku[row][col]++; print_soduku(soduku); cout << endl; } solve_soduku(soduku, row, col, fix_v); } ////////////////////////////////////////////////////////////////////////// //Empty cell else { soduku[row][col]++; print_soduku(soduku); cout << endl; solve_soduku(soduku, row, col, fix_v); } } void zero_arr(int temp_arr[], int size) { for (auto i = 0; i < size; i++) temp_arr[i] = 0; } void zero_soduku(int soduku[][N*N]) { for (int i = 0; i < N*N; i++) for (int j = 0; j < N*N; j++) soduku[i][j] = 0; } void get_input(int soduku[][N*N], bool fixed_values[][N*N]) { cout << endl << "Please enter locatin and nums into soduku: "; int row = 0, col, value; while (row != -1) { cin >> row; if (row == -1) return; cin >> col >> value; soduku[row][col] = value; fixed_values[row][col] = true; } } void print_soduku(const int soduku[][N*N]) { for (auto i = 0; i < N*N; i++) for (auto j = 0; j < N*N; j++) { cout << soduku[i][j] << " "; if (j == N*N - 1) cout << endl; } //system("pause"); }`enter code here`
Your algorithm appears to be, roughly: 1) Try each move in turn 2) Check the entire board to see if it's valid 3) Repeat until the entire board is filled This is obviously very inefficient. The code will be making many moves which are illegal, then only realizing this belatedly, after fact. I would suggest that you completely get rid of this, and attempt to implement something a little bit more efficient. Try to think how carbon-based life forms solve sudoku puzzles, and implement the same algorithm. Do you also do the above approach, when you solve a sudoku puzzle? Of course not. You do something like this: 1) For each position on the board, instead of storing just the current number in that position, if any, also store additional information: namely, if there is no number in that position, also store all possible numbers which would legal moves for that position. For a completely empty board, for example, each position on the sudoku board would contain all values 1-9. From this, we then make the next logical step: 2) When making a move and placing a value in some position, say 4, you will remove the value 4 from all other cells in its 3x3 square, and remove 4 from all other cells in the same row and column. Because that number will no longer be a valid move in those cells. Conversely, when undoing a move, and removing the 4 from the cell, this means that the value 4 is now legal in all cells in its 3x3 square, and its row and column, so you would put this value in all of those positions, as a number that's now a legal move in those positions. 3) When deciding which next move to make, scan the board first, looking for any cell that has only one possible legal number. This means, of course, that this is the only legal move for that cell, so you make it. 4) If you find any cell that has no legal values left, this means that you reached an unsolvable state, so you'll undo your last move, and then try the next valid move from that point on. 5) Otherwise, you should just pick one of the cells that has the fewest possible legal moves left, make the first move, then keep going, then if you reach an unsolvable state, and return to this move, you undo it, and try the next move. This seems to me an approach that should be much more efficient, as it should end up making the least number of illegal moves. It is also closely mimics how carbon-based lifeforms solve sudoku puzzles by themselves. P.S. To initialize a new sudoku puzzle with prefilled numbers, just start with an empty sudoku board, with all cells allowing all numbers 1-9 as legal moves, then make each move, as described above, to fill in the initial numbers on the sudoku board.