Taking portions of an array - c++

Suppose I have a 4 by 4 matrixes like this:
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
User enters a random portion number,for the sake of simplicity let it be 2.
I want to create 2x2 matrixes inside of the big matrix.
Submatrice1:
1 1
2 2
Submatrice2:
3 3
4 4
Submatrice3:
1 1
2 2
Submatrice3:
3 3
4 4
And then i want to replace
every number in submatrice 1 with a
every number in matrice 2 with b
every number in matrice 3 with
every number in matrice 4 with d
Last form of matrix:
a a c c
a a c c
b b d d
b b d d
And this should be generalized for n*m case.
I've no idea about where to begin.I'd appericate any ideas.

I'd go with an index-based calculation, as it seems the initial content doesn't matter.
/* Input: matrix and the size (2 in the example) */
/* The number of blocks. */
int block_height = (matrix.length + size/2) / size;
for(int row = 0; row < matrix.length; row++) {
for(int col = 0; col < matrix[0].length; col++) {
int block_row = row / size;
int block_col = col / size;
/* If we count up -> down, right -> left */
char block_index = block_col * block_height + block_row;
matrix[row][col] = 'a' + block_index;
}
}
This will start placing non-alfabet characters once the alfabet runs out, though.
It should do the following for 2, I don't really know if this side case if what you thought of.
[ 1 1 1 1 1 ] [ a a d d g ]
[ 2 2 2 2 2 ] [ a a d d g ]
[ 3 3 3 3 3 ] --> [ b b e e h ]
[ 4 4 4 4 4 ] [ b b e e h ]
[ 5 5 5 5 5 ] [ c c f f i ]

I would do it like this:
someArray[4] = your input.
someBigArray[n][m];
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(i < n/2)
if(j < m/2)
someBigArray[n][m] = (char)(someArray[0] + offsetASCIIToA)
else
someBigArray[n][m] = (char)(someArray[1] + offsetASCIIToA)
else
if(j < m/2)
someBigArray[n][m] = (char)(someArray[2] + offsetASCIIToA)
else
someBigArray[n][m] = (char)(someArray[3] + offsetASCIIToA)
}
}
This is a pseduo code solution. You can adjust it for boundary cases and what not. I would just let integer division decide your border cases, this makes the most sense and is easiest, but you can modify the logic in minor ways to make it behave like you want. You could also include the logic in multiple for loops, using combinations if i = n/2, j = m/2, i < m/2 so on and so fourth. This is mildly more performant(less branching), but a bit more code. Each solution is O(m * n). The solution below outlines this possible logic.
for(int i = 0; i < n/2; i++)
for(int j = 0; j < m/2; j++)
someBigArray[n][m] = (char)(someArray[0] + offsetASCIIToA)
for(int i = n/2; i < n; i++)
for(int j = 0; j < m/2; j++)
someBigArray[n][m] = (char)(someArray[1] + offsetASCIIToA)
for(int i = 0; i < n/2; i++)
for(int j = m/2; j < m; j++)
someBigArray[n][m] = (char)(someArray[2] + offsetASCIIToA)
for(int i = n/2; i < n; i++)
for(int j = m/2; j < m; j++)
someBigArray[n][m] = (char)(someArray[3] + offsetASCIIToA)
All you have to do now is figure out your conversion of values in someArray to their appropriate character value. Just look up ASCII tables for this information, and use casting.
NOTE: this is making some assumptions about your problem. Your example, I feel, may be particularly poor. How you modify this for if your array is potentially 5 values could be defined too many ways for me to provide insight into how I would solve it.

Related

Optimized (memory-wise) implementation of full graph in C++

I need to implement Watts-Strogatz algorithm and I'm running into some problems with creating a full graph. The way I'm implemeting it, it takes up so much memory and I need to work on big systems so that is a problem.
I'm creating a matrix called lattice for my n nodes with their n - 1 = k neighbours. For eg. let's say n = 7. My lattice will look like:
1 6 2 5 3 4
2 0 3 6 4 5
3 1 4 0 5 6
4 2 5 1 6 0
5 3 6 2 0 1
6 4 0 3 1 2
0 5 1 4 2 3
And now the code to create it.
This is main.cpp:
#include "lattice.h"
#include <vector>
int main() {
/*
* initial parameters
*/
int n = 7; //number of agents MUST BE ODD
int k = 6; //number of agents with whom we wire; N - 1 for full graph
// NEEDS TO BE EVEN
int** lattice = new int* [n];
/*
* creating ring lattice
*/
for (int i = 0; i < n; i++) {
lattice[i] = new int [k];
}
createRingLattice (n, k, lattice);
delete[](lattice);
std::cout << std::endl;
return 0;
}
And this is the function createRingLattice:
void createRingLattice (int n, int k, int** lattice) {
/*
* setting up ring lattice
*/
//table of the nearest neighbours
//next iN previous iP
int* iP = new int [n];
int* iN = new int [n];
for (int i = 0; i < n; i++) {
iP[i] = i - 1;
iN[i] = i + 1;
}
//boundary conditions
iP[0] = n - 1;
iN[n - 1] = 0;
for (int i = 0; i < n; i++) {
int countP = 0;
int countN = 0;
for (int j = 0; j < k; j++) {
if (j % 2 == 0) {
if (i + countN > n - 1) {
lattice[i][j] = iN[i + countN - n];
} else {
lattice[i][j] = iN[i + countN];
}
countN++;
}
if (j % 2 == 1 ) {
if (i - countP < 0) {
lattice[i][j] = iP[n + i - countP];
} else {
lattice[i][j] = iP[i - countP];
}
countP++;
}
}
}
delete[](iN);
delete[](iP);
}
First question:
Is there a way to implement this with much less memory usage?
Second question:
I've seen people implementing graphs with adjacency list (this one for example) but I'm wondering if it's acctually more optimized than my implemantation? It does use pointers as well and I'm not the expert so it's hard for me to determine whether it's better when it comes to memory usage.
Note: I'm not concerned about speed at the moment.

How to turn equation with decrementing indexing into math equation with summation?

Similar to this question: Turn while loop into math equation?, I have the following nested loop that I am trying to convert into a math equation as I need to write this up in a format that doesn't look like code. I believe I am going to need some type of summation equation.
Here is the code:
int num = 0;
for (int i = nr - 1; i >= 0; i--) {
for (int j = nc - 1; j >= 0; j--) {
ela[i][j] = num;
eha[i][j] = num + ea[i][j] - 1;
num += ea[i][j];
}
}
I know that summations start from a lower bound and continue to a higher bound, so I'm not quite sure how to apply a summation here since I start from a higher index and continue to a lower index.
I'm not sure why I'm getting downvoted, as the question I referenced is very similar to mine, has the same tags and is upvoted 14 times. Please comment below if I can improve my question somehow.
Update:
I was able to update the formula as follows:
nr = 50;
nc = 10;
num = sum[ea[i,j],i=0,nr-1,j=0,nc-1]; // correct based upon nr, nc and ea
for (int i = 0; i < nr; i) {
for (int j = 0; j < nc; j++) {
num = num - ea[i,j];
ela[i][j] = num;
eha[i][j] = num + ea[i,j] - 1;
}
}
If I am right, you can transcribe the effect as
You can describe this as the matrix ela being a 2D suffix sum of the matrix ea (for every element, sum of the elements that follow in the lexicographical ordering), while eha is the sum of matrices ela and ea minus all ones.
If the problem is just with how to express the sum when you're looping the other direction, you can change your code to:
int num = 0;
for (int i = 0; i < nr; i++) {
for (int j = 0; j < nc; j++) {
ela[nr - i][nc - j] = num;
eha[nr - i][nc - i] = num + ea[nr - i][nc - j] - 1;
num += ea[nr - i][nc - j];
}
}
I'm not saying you have to change your code to this, but from here it should be more obvious how to change this to use summation notation.
It's hard to tell without any context, but the code in question becomes more intelligible if you think of the arrays as vectors enumerating the elements in reverse order, row-major. The code below is functionally equivalent to the original one posted, but arguably easier to follow.
// n.b. ela[nr - 1 - i][nc - 1 - j] == rela(nc * i + j);
int &rela(int k) { return ela[nr - 1 - k / nc][nc - 1 - k % nc]; }
int &reha(int k) { return elh[nr - 1 - k / nc][nc - 1 - k % nc]; }
int &rea(int k) { return ea[nr - 1 - k / nc][nc - 1 - k % nc]; }
for (int k = 0, sum = 0; k < nr * nc - 1; k++) {
rela(k) = sum;
sum += rea(k);
reha(k) = sum - 1;
}
In plain English, rela(k) is the partial sum of rea elements 0 ... k-1 and reha(k) is one less than the partial sum of rea elements 0 ... k (also, rela(k) == reha(k - 1) + 1 for k > 0).
Technically, this description could be translated back in terms of the 2d arrays, but it becomes rather messy quickly.

Finding regional maximum elements by iterative method

Assumed that I'd find regional maximum elements in the following matrix. The regional maximum are 8-connected elements with the same value t, whose external boundary all have a value less than t. In this case, the results expected are one element that equals 8 and five elements that equal 9.
1 1 1 1 1 1 1 1 1 1
1 2 2 2 2 2 2 1 1 1
1 1 2 8 2 2 2 9 1 1
1 1 1 1 2 2 9 9 9 1
1 2 2 2 2 2 2 9 1 1
1 1 1 1 1 1 1 1 1 1
For the first situation, it is very easy to pick 8 from its 8-connected neighbors because 8 is the greatest among them. The pseudo code:
for (i = 0; i < 10; i++) {
for (j = 0; j < 6; j++) {
if element(i, j) > AllOfNeighbors(i, j)
RecordMaxElementIndex(i, j);
}
}
But for the second situation, I get confused. This time 9 is greater than some of its neighbors and equals to the other neighbors. The pseudo code would be:
for (i = 0; i < 10; i++) {
for (j = 0; j < 6; j++) {
// Start iteration
if element(i, j) > AllOfNeighbors(i, j)
RecordMaxElementIndex(i, j);
else if element(i, j) > SomeOfNeighbors(i, j) &&
element(i, j) == TheOtherNeighbors(i, j)
RecordTheOtherNeighborsIndex(i, j);
// Jump to the start now
}
}
For example, when (i, j) is (7, 2), elements at (6, 3), (7, 3) and (8, 3) will be recorded for the next iterative round. I'm not sure whether using iterative method is proper here but I think TheOtherNeighbors(ii, jj) could be treated as element(i, j) and repeat the same process to find the regional maximum. Moreover, (6, 3) cannot be compared to (7, 2), (7, 3) and (8, 3)again in case endless loop. So how to implement the iterative method? Any guide would be helpful.
As I understand, you may create the connected components using Disjoint-set_data_structure and mark component that are not maximal...
Pseudo code:
DisjointSet disjointSet[10][6]
// Init disjointSet
for (i = 0; i < 10; i++) {
for (j = 0; j < 6; j++) {
disjointSet[i][j].MakeSet({i, j});
disjointSet[i][j].MarkAsMaximal(); // extra flag for your case
}
}
// Create Connected component and mark as not maximal
for (i = 0; i < 10; i++) {
for (j = 0; j < 6; j++) {
for (auto neighborDisjointSet : NeighborsWithSameValue(i, j)) {
Union(disjointSet[i][j], neighborDisjointSet);
}
if (element(i, j) < AnyOfNeighbors(i, j)) {
disjointSet[i][j].MarkAsNotMaximal();
}
for (auto neighborDisjointSet : NeighborsWithSmallValue(i, j) {
neighborDisjointSet.MarkAsNotMaximal();
}
}
}
// Collect result.
std::set<DisjointSet> maximumRegions;
for (i = 0; i < 10; i++) {
for (j = 0; j < 6; j++) {
if (disjointSet[i][j].IsMarkAsMaximal) {
maximumRegions.insert(disjointSet[i][j]);
}
}
}

matrix multiplication as column major

I am trying to multiply as column major and I can't seem to find the right formula!
I want to have the matrices as 1D.
Let's say I have these matrices:
A=
1 3
2 4
and B=
5 2 1
6 3 7
The above matrices are assumed that are stored already in column major order.
I am trying:
int main(int argc, const char* argv[]) {
int rows=2;
int cols=3;
int A[rows*rows];
int B[rows*cols];
int res[rows*cols];
A[0]=1;
A[1]=3;
A[2]=2;
A[3]=4;
B[0]=5;
B[1]=2;
B[2]=1;
B[3]=6;
B[4]=3;
B[5]=7;
/*A[0]=1;
A[1]=2;
A[2]=3;
A[3]=4;
B[0]=5;
B[1]=6;
B[2]=2;
B[3]=3;
B[4]=1;
B[5]=7;
*/
//multiplication as column major
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
res[i+j*rows]=0;
for (int k=0;k<rows;k++){
res[i+j*rows]+=A[i+k*rows]*B[k+j*cols];
}
}
}
for (int i=0;i<rows*cols;i++){
printf("\n\nB[%d]=%d\t",i,res[i]);
}
return 0;
}
I am not getting the correct results.
Also,I can't understand (in the case where the matrices are stored in column major already) ,how to index the matrices A and B.
A[0]=1;
A[1]=3;
...
or
A[0]=1;
A[1]=2;
...
I don't want to transpose the matrices and then use row major.
I want to handle the data as column major.
Because the indices ,if stored as column major,will be different (hence,will matter in order to do the multiplication).
There are two things that lead to your confusion here.
First, the data in your contiguous one-dimensional vector is not in column-major order as you say, but in row-major order, as is the usual layout of two-dimensional contiguous arrays in C. The linear one-dimensional indices of row i and column j in a matrix with M rows and N columns (MxN) are:
A[i*N + j] // row major
A[i + M*j] // column major
The "major" refers to the dimension of the outer loop when traversing the array sequentially with two nested loops:
n = 0;
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
printf("%8d", A[n++]);
}
printf("\n");
}
Second, you use the two dimensions rows and columns which are the dimensions of the resulting matrix, which is confusing, because the number of columns in A is rows.
In fact, there are three different dimensions involved in matrix multiplication when you multiply an MxL matrix A with an LxN matrix B to get an MxN matrix C. In your case, M and L happen to be both 2:
L (k) | N (j)
|
| 5 2 1
L (k) |
| 6 3 7
|
-----------------+-------------
|
1 3 | 23 11 22
M (i) |
2 4 | 34 16 30
|
The letters in parentheses are the variables the code below uses to iterate over the respective dimension.
Now you can multiply your matrices in row-major format:
#define M 2
#define N 3
#define L 2
int A[M * L] = {1, 3, 2, 4};
int B[L * N] = {5, 2, 1, 6, 3, 7};
int res[M * N];
int i, j, k;
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
res[j + i * N] = 0;
for (k = 0; k < L; k++) {
res[j + i * N] += A[k + i * L] * B[j + k * N];
}
}
}
for (i = 0; i < M * N; i++) printf("[%d] = %d\n", i, res[i]);
or in column-major format:
#define M 2
#define N 3
#define L 2
int A[M * L] = {1, 2, 3, 4};
int B[L * N] = {5, 6, 2, 3, 1, 7};
int res[M * N];
int i, j, k;
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
res[j * M + i] = 0;
for (k = 0; k < L; k++) {
res[j * M + i] += A[k * M + i] * B[j * L + k];
}
}
}
for (i = 0; i < M * N; i++) printf("[%d] = %d\n", i, res[i]);
Both input and output are in the respective matrix representation and differ in the two cases, of course.
What do you think about
res[i+j*rows]+=A[i+k*rows]*B[k+j*cols];
what it will do?
It will access array res, A and B out of bound when i and k becomes 1 and j becomes 2.
res[1+2*2]+=A[1+1*2]*B[1+2*3] = res[5]+=A[4]*B[7];
This will invoke undefined behavior and you may get either expected or unexpected result.
I think you need this:
res[i*rows+j] += A[i*rows + k] * B[j + k*cols];

Sudoku solver keeps getting stuck for some reason

So I had to write a program for a computer project for high school and I thought of doing a sudoko solver. The 'solve' algorithm is implemented like this:-
For any points where only one element 'fits' looking at rows, columns, 3x3 set, put that number in. Do this repeatedly till it can't be done anymore. This is seen in the 'singleLeft' function.
If a number 'fits' in some point but nowhere else in the associated row, column or 3x3 set, put that number in. This can be seen in the 'checkOnlyAllowed' function.
If we're not done yet, do a 'guess' - take some number that 'fits' in the point, put it in there and then solve again using this algorithm (recurse) - if it works, we're done.
So far, I have this code:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
//Prints a message and exits the application.
void error(const char msg[])
{
cout << "An error occurred!" << endl;
cout << "Description: " << msg << endl;
exit(0);
}
//A representation of a sudoku board. Can be read from a file or from memory.
class Sudoku
{
protected:
//For a point x, y and a number n in the board, mAllowed[x][y][n]
//is 1 if n is allowed in that point, 0 if not.
int mAllowed[9][9][10];
int filledIn;
public:
/*
* For mBoard[i][j], the location is (i,j) in the below map:
*
* (0,0) (0,1) (0,2) (0,3) (0,4) (0,5) (0,6) (0,7) (0,8)
* (1,0) (1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7) (1,8)
* (2,0) (2,1) (2,2) (2,3) (2,4) (2,5) (2,6) (2,7) (2,8)
*
* (3,0) (3,1) (3,2) (3,3) (3,4) (3,5) (3,6) (3,7) (3,8)
* (4,0) (4,1) (4,2) (4,3) (4,4) (4,5) (4,6) (4,7) (4,8)
* (5,0) (5,1) (5,2) (5,3) (5,4) (5,5) (5,6) (5,7) (5,8)
*
* (6,0) (6,1) (6,2) (6,3) (6,4) (6,5) (6,6) (6,7) (6,8)
* (7,0) (7,1) (7,2) (7,3) (7,4) (7,5) (7,6) (7,7) (7,8)
* (8,0) (8,1) (8,2) (8,3) (8,4) (8,5) (8,6) (8,7) (8,8)
*
*/
int mBoard[9][9];
//Read in from file with given name.
Sudoku(char filename[])
{
filledIn = 0;
int i, j, k;
//Fill the board with 0s.
for (i = 0; i < 9; ++i)
for (j = 0; j < 9; ++j)
mBoard[i][j] = 0;
//Set every number to 'allowed' initially.
for (i = 0; i < 9; ++i)
for (j = 0; j < 9; ++j)
for (k = 1; k <= 9; ++k)
mAllowed[i][j][k] = 1;
//Read in from the file.
ifstream file(filename);
if (!file)
error("File doesn't exist!");
for (i = 0; i < 9; ++i)
for (j = 0; j < 9; ++j)
if (file)
{
int m;
file >> m;
if (m)
set(i, j, m);
}
else
error("Not enough entries in file!");
}
//Solve the board!
int solve()
{
int prevFilledIn;
do
{
prevFilledIn = filledIn;
singleLeft();
checkOnlyAllowed();
} while (filledIn - prevFilledIn > 3);
if (filledIn < 81)
guess();
return filledIn == 81;
}
//Given a point i, j, this looks for places where this point
//disallows a number and sets the 'mAllowed' table accordingly.
void fixAllowed(int i, int j)
{
int n = mBoard[i][j], k;
for (k = 0; k < 9; ++k)
mAllowed[i][k][n] = 0;
for (k = 0; k < 9; ++k)
mAllowed[k][j][n] = 0;
//Look in 3x3 sets too. First, set each coordinate to the
//highest multiple of 3 below itself. This takes us to the
//top-left corner of the 3x3 set this point was in. Then,
//add vectorially all points (x,y) where x and y each are
//one of 0, 1 or 2 to visit each point in this set.
int x = (i / 3) * 3;
int y = (j / 3) * 3;
for (k = 0; k < 3; ++k)
for (int l = 0; l < 3; ++l)
mAllowed[x + k][y + l][n] = 0;
mAllowed[i][j][n] = 1;
}
//Sets a point i, j to n.
void set(int i, int j, int n)
{
mBoard[i][j] = n;
fixAllowed(i, j);
++filledIn;
}
//Try using 'single' on a point, ie, only one number can fit in this
//point, so put it in and return 1. If more than one number can fit,
//return 0.
int trySinglePoint(int i, int j)
{
int c = 0, m;
for (m = 1; m <= 9; ++m)
c += mAllowed[i][j][m];
if (c == 1)
{
for (m = 1; m <= 9; ++m)
if (mAllowed[i][j][m])
set(i, j, m);
//printBoard();
return 1;
}
return 0;
}
//Try to solve by checking for spots that have only one number remaining.
void singleLeft()
{
for (;;)
{
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
if (!mBoard[i][j])
if (trySinglePoint(i, j))
goto logic_worked;
//If we reached here, board is either full or unsolvable by this logic, so
//our job is done.
return;
logic_worked:
continue;
}
}
//Within rows, columns or sets, whether this number is 'allowed' in spots
//other than i, j.
int onlyInRow(int n, int i, int j)
{
for (int k = 0; k < 9; ++k)
if (k != j && mAllowed[i][k][n])
return 0;
return 1;
}
int onlyInColumn(int n, int i, int j)
{
for (int k = 0; k < 9; ++k)
if (k != i && mAllowed[k][j][n])
return 0;
return 1;
}
int onlyInSet(int n, int i, int j)
{
int x = (i / 3) * 3;
int y = (j / 3) * 3;
for (int k = 0; k < 3; ++k)
for (int l = 0; l < 3; ++l)
if (!(x + k == i && y + l == j) && mAllowed[x + k][y + l][n])
return 0;
return 1;
}
//If a number is 'allowed' in only one spot within a row, column or set, it's
//guaranteed to have to be there.
void checkOnlyAllowed()
{
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
if (!mBoard[i][j])
for (int m = 1; m <= 9; ++m)
if (mAllowed[i][j][m])
if (onlyInRow(m, i, j) || onlyInColumn(m, i, j) || onlyInSet(m, i, j))
set(i, j, m);
}
//Copy from a given board.
void copyBoard(int board[9][9])
{
filledIn = 0;
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
{
if (board[i][j] > 0)
++filledIn;
mBoard[i][j] = board[i][j];
}
}
//Try to solve by 'guessing'.
void guess()
{
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j)
for (int n = 1; n <= 9; ++n)
if (!mBoard[i][j])
if (mAllowed[i][j][n] == 1)
{
//Do a direct copy so that it gets the 'mAllowed'
//table too.
Sudoku s = *this;
//Try solving with this number at this spot.
s.set(i, j, n);
if (s.solve())
{
//It was able to do it! Copy and report success!
copyBoard(s.mBoard);
return;
}
}
}
//Print the board (for debug purposes)
void printBoard()
{
for (int i = 0; i < 9; ++i)
{
for (int j = 0; j < 9; ++j)
cout << mBoard[i][j] << " ";
cout << endl;
}
cout << endl;
char s[5];
cin >> s;
}
};
int main(int argc, char **argv)
{
//char filename[42];
//cout << "Enter filename: ";
//cin >> filename;
char *filename = argv[1];
Sudoku s(filename);
if (!s.solve())
error("Couldn't solve!");
cout << "Solved! Here's the solution:" << endl << endl;
for (int i = 0; i < 9; ++i)
{
for (int j = 0; j < 9; ++j)
cout << s.mBoard[i][j] << " ";
cout << endl;
}
return 0;
}
(code including line numbers: http://sprunge.us/AiUc?cpp)
Now I understand that it isn't very good style, but it came out of a late-night coding session and also we use an older compiler in the school lab so I had to do some things differently (in that compiler, the standard headers have the '.h' extension, variables declared in for loops are in outside-for scope, ... ).
The file should contain whitespace-delimited digits for each spot in the board starting from the top-left going left to right and top to bottom, with empty spots signified by '0's.
For the following file, it works rather well:
5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 0 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 0 0 2 8 0
0 0 0 4 1 9 0 0 5
0 0 0 0 8 0 0 7 9
However, this one gives it trouble:
0 9 4 0 0 0 1 3 0
0 0 0 0 0 0 0 0 0
0 0 0 0 7 6 0 0 2
0 8 0 0 1 0 0 0 0
0 3 2 0 0 0 0 0 0
0 0 0 2 0 0 0 6 0
0 0 0 0 5 0 4 0 0
0 0 0 0 0 8 0 0 7
0 0 6 3 0 4 0 0 8
If I comment out the print statements and track the progress I can see that it starts by heading out in the wrong direction at points. Eventually it gets stuck toward the end and the backtracking never gets far back enough. I think it's something wrong with the 'checkOnlyAllowed' part...
What do you think could be the problem?
Also - I know I could've used a bitfield for the 'mAllowed' table but we don't officially know about bitwise operations yet in school. :P
At line 170 you have a goto that is jumping out of a for loop, then continuing. This could give you some weird behavior with continuing the wrong loop, behavior that might depend on the specific compiler.
Try replacing lines 164-177 with:
164 for (;;)
165 {
166 bool successfullyContributedToTheBoard = false;
167 for (int i = 0; i < 9; ++i)
168 for (int j = 0; j < 9; ++j)
169 if (!mBoard[i][j])
170 if (trySinglePoint(i, j))
171 successfullyContributedToTheBoard = true;
172 if (!successfullyContributedToTheBoard)
173 return;
174 }
I didn't look at your code but your strategy is exactly the same as the one I used to code a Sudoku solver. But I can't remember it being very slow. I got solutions in an instant. The maximum number of "guesses" the program had do make was 3 during my tests. That was for Sudoku problems which were supposed to be very hard. Three is not a big number with respect to back tracking and you can pick a cell which has only a few possibilities left (two or three) which limits the search space to about 20-30 states only (for hard Sudoku problems).
What I'm saying is, it's possible to use this strategy and solve Sudoku problems really fast. You only have to figure out how to optimize your code. Try to avoid redundant work. Try to remember things so you don't need to recalculate them again and again.
Alright, I got it working! It seems that the i, j loop within 'guess' was unecessary - ie., it should only do a guess on one empty spot because its 'child processes' will handle the rest. Fixing this actually made the code simpler. Now it works really well, and actually its very quick!
Thanks for your help, everyone. ;-)