Process all elements in map based on multiple conditions - c++

I have the following data structure:
struct Data
{
int p1;
int p2;
int p3;
int size;
};
I need to sum size of all elements in map based on p1, p2 and p3 parameters. Here is an example code:
std::unordered_map<int, Data> m;
m[1] = Data{ 11, 22, 33, 10 };
m[2] = Data{ 33, 22, 11, 15 };
m[3] = Data{ 55, 55, 55, 25 };
int p1 = -1, p2 = 22, p3 = -1;
int size = 0;
for(const auto [key, data]: m)
{
if ((p1 >= 0) && (p2 >= 0) && (p3 >= 0))
{
if ((p1 == data.p1) && (p2 == data.p2) && (p3 == data.p3))
{
size += data.size;
}
}
else if ((p1 >= 0) && (p2 >= 0) && (p3 < 0))
{
if ((p1 == data.p1) && (p2 == data.p2))
{
size += data.size;
}
}
else if ((p1 >= 0) && (p2 < 0) && (p3 >= 0))
{
if ((p1 == data.p1) && (p3 == data.p3))
{
size += data.size;
}
}
else if ((p1 < 0) && (p2 >= 0) && (p3 >= 0))
{
if ((p2 == data.p2) && (p3 == data.p3))
{
size += data.size;
}
}
else if ((p1 < 0) && (p2 < 0) && (p3 >= 0))
{
if (p3 == data.p3)
{
size += data.size;
}
}
else if ((p1 < 0) && (p2 >= 0) && (p3 < 0))
{
if (p2 == data.p2)
{
size += data.size;
}
}
else if ((p1 >= 0) && (p2 < 0) && (p3 < 0))
{
if (p1 == data.p1)
{
size += data.size;
}
}
else
{
size += data.size;
}
}
As you can see map items are matched based on p1, p2 and p3 values. The size sum equals 25 for the above parameters. Is it possible to simplify that code using c++17/stl features ?

If I understand correctly, you can highly simplify your for range loop as follows
for ( auto const & [key, data] : m )
if ( ((p1 < 0) || (p1 == data.p1))
&& ((p2 < 0) || (p2 == data.p2))
&& ((p3 < 0) || (p3 == data.p3)) )
size += data.size;
If you prefer, you can use std::for_each(), including <algorithm>
std::for_each(m.cbegin(), m.cend(), [&](auto const & p)
{ if ( ((p1 < 0) || (p1 == p.second.p1))
&& ((p2 < 0) || (p2 == p.second.p2))
&& ((p3 < 0) || (p3 == p.second.p3)) )
size += p.second.size; });
but I don't see advantages over the preceding solution.

Related

Verifying that inputs are in range

I'm having a problem implementing this.. the program is meant to take date input in the format dd.mm.yyyy, it does that already but I've been trying to add the code that checks
if the date is more than 31 or February is more than 28
if the month is more than 12
It should return an error since the input is incorrect
And also if a user start input with . then the program shouldn't allow more than 2 inputs of .. so that the user can just just go back with the arrow buttons and type in the correct input
#include "examplevalidator.h"
ExampleValidator::ExampleValidator(QObject* parent)
: QValidator (parent)
{
}
ExampleValidator::~ExampleValidator()
{
}
QValidator::State ExampleValidator::validate( QString & input, int & pos ) const
{
if (input.isEmpty()) return Intermediate;
bool ok;
QString str;
str = input[pos-1];
if(input.size() == 10
&& ((input[2] == '.'))
&& ((input[5] == '.'))
&& input[0].isDigit()
&& input[1].isDigit() && (input.toInt(&ok, 10) <= 31)
&& input[3].isDigit()
&& input[4].isDigit() && (input.toInt(&ok, 10) <= 12)
&& input[6].isDigit()
&& input[7].isDigit()
&& input[8].isDigit()
&& input[9].isDigit() && (input.toInt(&ok, 10) <= 2020)
// && (pos == 1 )&& (input.toInt(&ok, 10) <= 3)
// && (pos == 2 )&& (input.toInt(&ok, 10) <= 31)
)
return Acceptable;
if(input.size() > 10)
return Invalid;
if((pos == 1 )&& (input.toInt(&ok, 10) <= 3) && input[0].isDigit())
{return Intermediate;}
if((pos == 2) && (input.toInt(&ok, 10) <= 31) && input[pos-1].isDigit())
{return Intermediate;}
if((pos == 3) && (input.toInt(&ok, 10) <= 1) && input[pos-1].isDigit())
{return Intermediate;}
if((pos == 4) && (input.toInt(&ok, 10) <= 1) && input[3].isDigit())
{return Intermediate;}
if((pos == 5) && (input.toInt(&ok, 10) <= 12) && input[4].isDigit())
{return Intermediate;}
// if((pos == 6) && (input.toInt(&ok, 10) <= 999999) && input[pos-1].isDigit())
// {return Intermediate;}
if((pos == 7) && (input.toInt(&ok, 10) <= 9) && input[6].isDigit())
{return Intermediate;}
if((pos == 8) && (input.toInt(&ok, 10) <= 99) && input[7].isDigit())
{return Intermediate;}
if((pos == 9) && (input.toInt(&ok, 10) <= 999) && input[8].isDigit())
{return Intermediate;}
if((pos == 10) && (input.toInt(&ok, 10) < 99999) && input[9].isDigit())
{return Intermediate;}
if (input[0] == '.' )
{return Intermediate;}
if(pos > 1)
{
if (input.isEmpty()) return Intermediate;
if((pos > 1) || (pos <=2 ) && (input[pos-1] == '.'))
return Intermediate;
if(pos > 8 && pos <= 10 && input[pos-1].isDigit())
{return Intermediate;}
else {return Invalid;}
}
}
You can use a regular expression to validate dd.mm.yyyy
Have a look at https://regex101.com/ for trying them out.
Something like the code below should get you started
#include <regex>
std::smatch match;
const std::regex ddmmyyyyRegExp(R"((([0-9]{2})\.([0-9]{2})\.([0-9]{4})))");
std::string dd;
std::string mm;
std::string yyyy;
if (std::regex_search(input, match, ddmmyyyyRegExp) && match.size() == 4)
{
dd= match.str(1);
mm= match.str(2);
yyyy= match.str(3);
}
I've been able to fix the code, but still I'm unable to check if the inputs are in a particular range. I'm trying to check if the date limit isn't more than 31 and month isn't greater than 12
ExampleValidator::ExampleValidator(QObject* parent)
: QValidator (parent)
{
}
ExampleValidator::~ExampleValidator()
{
}
QValidator::State ExampleValidator::validate( QString & input, int & pos ) const
{
if (input.isEmpty()) return Intermediate;
bool ok;
QString str;
str = input[pos-1];
if(pos > 0 && input[0] != '.')
{
if (input.isEmpty()) return Intermediate;
if(((pos == 1 )&& (input.toInt(&ok, 10) <= 9) && input[0].isDigit() && input.size() != 10))
{return Intermediate;}
if(((pos == 2) && (input.toInt(&ok, 10) <= 99) && input[1].isDigit() && input.size() != 10))
{return Intermediate;}
if(((pos == 3) && (input.toInt(&ok, 10) <= 999)) && (input[2].isDigit() || input[2] == '.') && input.size() != 10)
{return Intermediate;}
if((pos == 4) && (input.toInt(&ok, 10) <= 9999) && input[3].isDigit() && input.size() != 10)
{return Intermediate;}
if((pos == 5) && (input.toInt(&ok, 10) <= 99999) && input[4].isDigit() && input.size() != 10)
{return Intermediate;}
if(((pos == 6) && (input.toInt(&ok, 10) <= 999999)) && (input[5].isDigit() || input[5] == '.') && input.size() != 10)
{return Intermediate;}
if((pos == 7) && (input.toInt(&ok, 10) <= 99999999) && input[6].isDigit() && input.size() != 10)
{return Intermediate;}
if((pos == 8) && (input.toInt(&ok, 10) <= 999999999) && input[7].isDigit() && input.size() != 10)
{return Intermediate;}
if((pos == 9) && (input.toInt(&ok, 10) <= 999999999) && input[8].isDigit() && input.size() != 10)
{return Intermediate;}
if((pos == 10) && (input.toInt(&ok, 10) < 2020) && input[9].isDigit() && input[2] == '.' && input[5]=='.' )
{
return Acceptable;}
}
if(((pos == 1) && (input[0] == '.')) || ((pos == 2) && (input[1] == '.')))
{
return Intermediate;
}
else if (input.isEmpty()) {return Intermediate;}
}```

What would be the time complexity of solution to this problem?

Question:
https://www.spoj.com/problems/BALNUM/
My Solution:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
string s;
vector<ll>v;
ll dp[20][2][3][3][3][3][3][3][3][3][3][3][2];
ll solve(ll i,ll less,ll start,ll m0,ll m1,ll m2,ll m3,ll m4,ll m5,ll m6,ll m7,ll m8,ll m9){
if(i == s.size()){
if((m1 == 2 or m1 == 0) and (m3 == 2 or m3 == 0) and (m5 == 2 or m5 == 0) and (m7 == 2 or m7 == 0) and (m9 == 2 or m9 == 0) and (m0 == 1 or m0 == 0) and (m2 == 1 or m2 == 0) and (m4 == 1 or m4 == 0) and (m6 == 1 or m6 == 0) and (m8 == 1 or m8 == 0)){
return 1;
}
return 0;
}
ll &ret = dp[i][less][m0][m1][m2][m3][m4][m5][m6][m7][m8][m9][start];
if(ret != -1) return ret;
ll k = less ? 9 : v[i];
ll ans = 0;
for(ll j = 1; j <= k; j++){
if(j == 1){
ans += solve(i+1,less | (j < v[i]),0,m0,((m1+1)%3 == 0) ? 1:(m1+1)%3,m2,m3,m4,m5,m6,m7,m8,m9);
}else if(j == 2){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,((m2+1)%3 == 0) ? 1:(m2+1)%3,m3,m4,m5,m6,m7,m8,m9);
}else if(j == 3){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,((m3+1)%3 == 0) ? 1:(m3+1)%3,m4,m5,m6,m7,m8,m9);
}else if(j == 4){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,((m4+1)%3 == 0) ? 1:(m4+1)%3,m5,m6,m7,m8,m9);
}else if(j == 5){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,((m5+1)%3 == 0) ? 1:(m5+1)%3,m6,m7,m8,m9);
}else if(j == 6){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,m5,((m6+1)%3 == 0) ? 1:(m6+1)%3,m7,m8,m9);
}else if(j == 7){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,m5,m6,((m7+1)%3 == 0) ? 1:(m7+1)%3,m8,m9);
}else if(j == 8){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,m5,m6,m7,((m8+1)%3 == 0) ? 1:(m8+1)%3,m9);
}else if(j == 9){
ans += solve(i+1,less | (j < v[i]),0,m0,m1,m2,m3,m4,m5,m6,m7,m8,((m9+1)%3 == 0) ? 1:(m9+1)%3);
}
}
if(!start){
ans += solve(i+1,less | (0 < v[i]),0,((m0+1)%3 == 0) ? 1:(m0+1)%3,m1,m2,m3,m4,m5,m6,m7,m8,m9);
}
if(start){
ans += solve(i+1,1,1,0,0,0,0,0,0,0,0,0,0);
}
return ret = ans;
}
int main(){
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
ll t;
cin>>t;
while(t--){
ll x;
cin>>x;
--x;
s = to_string(x);
memset(dp,-1,sizeof(dp));
v.clear();
for(char c:s) v.push_back(c-'0');
ll a=solve(0,0,1,0,0,0,0,0,0,0,0,0,0);
cin>>s;
memset(dp,-1,sizeof(dp));
v.clear();
for(char c:s) v.push_back(c-'0');
ll b=solve(0,0,1,0,0,0,0,0,0,0,0,0,0);
cout<<b-a<<endl;
}
}
Here the array i use for memoization is dp[20][2][3][3][3][3][3][3][3][3][3][3][2] (20 is max length of integer A or B)
Is the time complexity O(n) with a very high constant (like 2*3*3*3*3*3*3*3*3*3*3*2) where n is max length of integer A or B?
Its T * ( N * (2^2 * 3^10 * 9) + C ), The constant factor is really huge, but overall i think you can say that the time complexity is T * N * (a huge constant factor).
So you could say its O(T*N).

Watershed implementation in C++

I'm working in the watershed algortih in C++. I have implemented a source that i've found but i didn't get the expected results. I obtain:
[
But the result should be this:
[
I have charge the image .bmp into a matrix an then i obtain the Gradient of the image using the Sobel operator.
My wathershed algorith now is:
void Watershed() {
stack<punto> s;
punto p, neighbour;
C_Matrix prueba3 (Gradiente.FirstRow(), Gradiente.LastRow(), Gradiente.FirstCol(), Gradiente.LastCol(), -1);
int auxU, auxV, Eaux, L=1;
for (double g = Gradiente.Min(); g <= Gradiente.Max(); g++) {
for (int i = Gradiente.FirstRow(); i <= Gradiente.LastRow(); i++) {
for (int j = Gradiente.FirstCol(); j <= Gradiente.LastCol(); j++) {
if (Gradiente(i, j) == g) {
p.Guarda(i, j);
s.push(p);
}
while (s.empty() == 0) {
p = s.top();
s.pop();
auxU = p.x;
auxV = p.y;
Eaux = -1;
// 8-connectivity
for (int i = 0; i < 8; i++) {
if (i == 0)
neighbour.Guarda(auxU - 1, auxV - 1);
else if (i == 1)
neighbour.Guarda(auxU, auxV - 1);
else if (i == 2)
neighbour.Guarda(auxU + 1, auxV - 1);
else if (i == 3)
neighbour.Guarda(auxU - 1, auxV);
else if (i == 4)
neighbour.Guarda(auxU + 1, auxV);
else if (i == 5)
neighbour.Guarda(auxU - 1, auxV + 1);
else if (i == 6)
neighbour.Guarda(auxU, auxV + 1);
else
neighbour.Guarda(auxU + 1, auxV + 1);
if (neighbour.x >= Gradiente.FirstRow() && neighbour.x <= Gradiente.LastRow()
&& neighbour.y >= Gradiente.FirstCol() && neighbour.y <= Gradiente.LastCol()) {
if (prueba3(neighbour.x, neighbour.y) > 0) {
if (Eaux == -1) {
Eaux = prueba3(neighbour.x, neighbour.y);
}
else if (prueba3(neighbour.x, neighbour.y) != Eaux)
Eaux = 0;
}
}
}
if (auxU >= Gradiente.FirstRow() && auxU <= Gradiente.LastRow()
&& auxV >= Gradiente.FirstCol() && auxV <= Gradiente.LastCol()) {
if (Eaux >= 0) {
prueba3(auxU, auxV) = Eaux;
}
else {
prueba3(auxU, auxV) = L;
L++;
}
}
else {
C_Print("Se sale");
C_PrintNum("AuxU", auxU);
C_PrintNum("AuxV", auxV);
}
}
}
}
}
C_PrintNum("L = ", L);
double max = prueba3.Max();
if (max > 255.0) {
prueba3.Stretch(0, 255);
}
aux = C_Image(prueba3);
}
I don't know where is the fail, maybe my source has mistakes.

C++ Visual Studio interprets the class method as static

Visual Studio interprets the class method as static but they are not. I have 110 Errors when i build below code.
Errors: Foto with errors 1. , Foto with errors 2.
It may wrong declares these methods?
//header
class Player {
public:
Player(int x, int y) {
PlayerX = x;
PlayerY = y;
};
void doAction(int input, Mapa *mapa);
int getDirection();
Vector2 getPosition();
int
PlayerX, PlayerY, direction;
void turn(int dir);
void move(int move, Vector2 mapSize, Mapa *mapa);
Vector2 getCordInFrontOfCharacter();
Vector2 getCordBehindCharacter();
};
and cpp file:
#include "Vector2.h"
#include "Player.h"
#include "Mapa.h"
using namespace std;
int PlayerX = 0, PlayerY = 0;
int direction = 0;
void Player::doAction(int input, Mapa *mapa) {
if (input == (char)72)
this->move(1, *mapa->mapSize, mapa);
else if (input == (char)80)
this->move(-1, *mapa->mapSize, mapa);
if (input == (char)75)
this->turn(-1);
else if (input == (char)77)
this->turn(1);
}
void Player::turn(int dir) {
if (dir < 0)
dir = 2 - dir;
direction = (direction + dir) % 4;
}
void Player::move(int move, Vector2 mapSize, Mapa *mapa) {
if (
move = 1
&& getCordInFrontOfCharacter().y - 1 >= 0
&& getCordInFrontOfCharacter().x - 1 >= 0
&& getCordInFrontOfCharacter().y - 1 < mapSize.y
&& getCordInFrontOfCharacter().x - 1 < mapSize.x
&& mapa->_Mapa[getCordInFrontOfCharacter().y - 1][getCordInFrontOfCharacter().x - 1] == '0') {
if (this->direction == 0)
this->PlayerY -= move;
else if (this->direction == 2)
this->PlayerY += move;
else if (this->direction == 1)
this->PlayerX += move;
else if (this->direction == 3)
this->PlayerX -= move;
if (this->PlayerY < 1)
this->PlayerY = 1;
if (this->PlayerX < 1)
this->PlayerX = 1;
if (this->PlayerY > mapSize.y)
this->PlayerY = mapSize.y;
if (this->PlayerX > mapSize.x)
this->PlayerX = mapSize.x;
}
else if (
move = 1
&& this->getCordBehindCharacter().y - 1 >= 0
&& this->getCordBehindCharacter().x - 1 >= 0
&& this->getCordBehindCharacter().y - 1 < mapSize.y
&& this->getCordBehindCharacter().x - 1 < mapSize.x
&& mapa->_Mapa[this->getCordBehindCharacter().y - 1][this->getCordBehindCharacter().x - 1] == '0') {
if (this->direction == 0)
this->PlayerY -= move;
else if (this->direction == 2)
this->PlayerY += move;
else if (this->direction == 1)
this->PlayerX += move;
else if (this->direction == 3)
this->PlayerX -= move;
if (this->PlayerY < 1)
this->PlayerY = 1;
if (this->PlayerX < 1)
this->PlayerX = 1;
if (this->PlayerY > mapSize.y)
this->PlayerY = mapSize.y;
if (this->PlayerX > mapSize.x)
this->PlayerX = mapSize.x;
}
}
int Player::getDirection() {
return this->direction;
}
Vector2 Player::getPosition() {
return Vector2(this->PlayerX, this->PlayerY);
}
Vector2 Player::getCordInFrontOfCharacter() {
if (this->direction == 2)
return Vector2(this->PlayerX, this->PlayerY + 1);
else if (this->direction == 0)
return Vector2(this->PlayerX, this->PlayerY - 1);
else if (this->direction == 3)
return Vector2(this->PlayerX - 1, this->PlayerY);
else if (this->direction == 1)
return Vector2(this->PlayerX + 1, this->PlayerY);
return Vector2(0, 0);
}
Vector2 Player::getCordBehindCharacter() {
if (direction == 2)
return Vector2(this->PlayerX, this->PlayerY - 1);
else if (this->direction == 0)
return Vector2(this->PlayerX, this->PlayerY + 1);
else if (this->direction == 3)
return Vector2(this->PlayerX + 1, this->PlayerY);
else if (this->direction == 1)
return Vector2(this->PlayerX - 1, this->PlayerY);
return Vector2(0, 0);
}
Thanks for help.
The Visual Studio compilater apparently gets confused at this function signature
void Player::move(int move, Vector2 mapSize, Mapa *mapa)
where the same name is used for a parameter and the function itself.
Change that to make them distinct:
void Player::move(int move_, Vector2 mapSize, Mapa *mapa)
// ^
In cpp file i initialize non-static methods with "::"
It's pretty much impossible to initialize method in c++. I you meant class members, well, then that's wrong.
If you have non-static member, you can't do that:
int foo::member = 0; // error, member is non-static
Every foo object has it's own int member, so it's not shared between them. You must set it for every object in constructor (maybe default values are what you are looking for):
foo::foo (int _mem = 0, ... ) : member(_mem) {...}

Sudoku Solving Function Explanation

I have been searching for a Sudoku Solving Algorithm for a while and I found this code. But I have some difficulties. I can't understand it. If there are conflicts with all numbers between 1 and 9 in a single cell, the program should stop, right? But it continues. Can somebody explain me how the code works, please? Here it is:
bool Sudoku::Help_Solve(int i, int j)
{
int nextrow, nextcol;
while(change[i][j] == 1) //We find the first cell in which we can change the number
{
j++;
if(j > 9)
{
j = 1;
i++;
}
if(i > 9) return true;
}
for(int p = 1; p <= 9; p++)
{
if(Game.Check_Conflicts(p, i, j)) //We are checking for conflicts
{
board[i][j] = p;
nextrow = i;
nextcol = j+1;
if(nextcol > 9)
{
nextcol = 1;
nextrow++;
}
if(nextcol == 1 && nextrow == 10) return true;
if(Game.Help_Solve(nextrow, nextcol)) return true;
}
}
board[i][j] = 0;
return false;
}
Not enough code to explain properly, what happens in Game.Check_Conflicts(p, i, j), is this function getting called recursively?
Here is the whole code if you want to see it:
#include <iostream>
#include <iomanip>
#include <time.h>
#include <cstdlib>
#include <windows.h>
using namespace std;
class Sudoku
{
private:
int board[9][9];
int change[9][9];
public:
Sudoku();
void Print_Board();
void Add_First_Cord();
bool Help_Solve(int i, int j);
bool Check_Conflicts(int p, int i, int j);
};
Sudoku Game;
void setcolor(unsigned short color) //The function that you'll use to
{ //set the colour
HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hcon,color);
}
Sudoku::Sudoku()
{
for(int i = 0; i <= 9; i++)
for(int j = 0; j <= 9; j++)
board[i][j] = 0;
}
void Sudoku::Print_Board()
{
for(int i = 1; i <= 9; i++)
{
for(int j = 1; j <= 9; j++)
{
if(change[i][j] == 1)
{
setcolor(12);
cout << board[i][j] << " ";
setcolor(7);
}
else cout << board[i][j] << " ";
if(j%3 == 0) cout << "| ";
}
cout << endl;
if(i%3 == 0) cout << "------+-------+--------" << endl;
}
}
void Sudoku::Add_First_Cord()
{
board[1][1] = 5; change[1][1] = 1;
board[1][2] = 3; change[1][2] = 1;
board[1][5] = 7; change[1][5] = 1;
board[2][1] = 6; change[2][1] = 1;
board[2][4] = 1; change[2][4] = 1;
board[2][5] = 9; change[2][5] = 1;
board[2][6] = 5; change[2][6] = 1;
board[3][2] = 9; change[3][2] = 1;
board[3][3] = 8; change[3][3] = 1;
board[3][8] = 6; change[3][8] = 1;
board[4][1] = 8; change[4][1] = 1;
board[4][5] = 6; change[4][5] = 1;
board[4][9] = 3; change[4][9] = 1;
board[5][1] = 4; change[5][1] = 1;
board[5][4] = 8; change[5][4] = 1;
board[5][6] = 3; change[5][6] = 1;
board[5][9] = 1; change[5][9] = 1;
board[6][1] = 7; change[6][1] = 1;
board[6][5] = 2; change[6][5] = 1;
board[6][9] = 6; change[6][9] = 1;
board[7][2] = 6; change[7][2] = 1;
board[7][7] = 2; change[7][7] = 1;
board[7][8] = 8; change[7][8] = 1;
board[8][4] = 4; change[8][4] = 1;
board[8][5] = 1; change[8][5] = 1;
board[8][6] = 9; change[8][6] = 1;
board[8][9] = 5; change[8][9] = 1;
board[9][5] = 8; change[9][5] = 1;
board[9][8] = 7; change[9][8] = 1;
board[9][9] = 9; change[9][9] = 1;
}
bool Sudoku::Check_Conflicts(int p, int i, int j)
{
for(int k = 1; k <= 9; k++)
if(board[i][k] == p) return false;
for(int q = 1; q <= 9; q++)
if(board[q][j] == p) return false;
/*
*00
000
000
*/
if((j == 1 || j == 4 || j == 7) && (i == 1 || i == 4 || i == 7))
{
if(board[i][j+1] == p || board[i][j+2] == p || board[i+1][j] == p ||
board[i+2][j] == p || board[i+1][j+1] == p || board[i+1][j+2] == p ||
board[i+2][j+1] == p || board[i+2][j+2] == p)return false;
}
/*
000
000
*00
*/
if((j == 1 || j == 4 || j == 7) && (i == 3 || i == 6 || i == 9))
{
if(board[i-1][j] == p || board[i-2][j] == p || board[i][j+1] == p ||
board[i][j+2] == p || board[i-1][j+1] == p || board[i-1][j+2] == p ||
board[i-2][j+1] == p || board[i-2][j+2] == p)return false;
}
/*
000
*00
000
*/
if((j == 1 || j == 4 || j == 7) && (i == 2 || i == 5 || i == 8))
{
if(board[i-1][j] == p || board[i-1][j+1] == p || board[i-1][j+2] == p ||
board[i][j+1] == p || board[i][j+2] == p || board[i+1][j] == p ||
board[i+1][j+1] == p || board[i+1][j+2] == p)return false;
}
/*
0*0
000
000
*/
if((j == 2 || j == 5 || j == 8) && (i == 1 || i == 4 || i == 7))
{
if(board[i][j-1] == p || board[i][j+1] == p || board[i+1][j+1] == p ||
board[i+1][j-1] == p || board[i+1][j] == p || board[i+2][j-1] == p ||
board[i+2][j] == p || board[i+2][j+1] == p)return false;
}
/*
000
0*0
000
*/
if((j == 2 || j == 5 || j == 8) && (i == 2 || i == 5 || i == 8))
{
if(board[i-1][j] == p || board[i-1][j-1] == p || board[i-1][j+1] == p ||
board[i][j+1] == p || board[i][j-1] == p || board[i+1][j+1] == p ||
board[i+1][j] == p || board[i+1][j-1] == p)return false;
}
/*
000
000
0*0
*/
if((j == 2 || j == 5 || j == 8) && (i == 3 || i == 6 || i == 9))
{
if(board[i][j-1] == p || board[i][j+1] == p || board[i-1][j] == p ||
board[i-1][j+1] == p || board[i-1][j-1] == p || board[i-2][j] == p ||
board[i-2][j+1] == p || board[i-2][j-1] == p) return false;
}
/*
00*
000
000
*/
if((j == 3 || j == 6 || j == 9) && (i == 1 || i == 4 || i == 7))
{
if(board[i][j-1] == p || board[i][j-2] == p || board[i+1][j] == p ||
board[i+1][j-1] == p || board[i+1][j-2] == p || board[i+2][j] == p ||
board[i+2][j-1] == p || board[i+2][j-2] == p) return false;
}
/*
000
00*
000
*/
if((j == 3 || j == 6 || j == 9) && (i == 2 || i == 5 || i == 8))
{
if(board[i-1][j] == p || board[i-1][j-1] == p || board[i-1][j-2] == p ||
board[i][j-1] == p || board[i][j-2] == p || board[i+1][j] == p ||
board[i+1][j-1] == p || board[i+1][j-2] == p) return false;
}
/*
000
000
00*
*/
if((j == 3 || j == 6 || j == 9) && (i == 3 || i == 6 || i == 9))
{
if(board[i][j-1] == p || board[i][j-2] == p || board[i-1][j] == p ||
board[i-1][j-1] == p || board[i-1][j-2] == p || board[i-2][j] == p ||
board[i-2][j-1] == p || board[i-2][j-2] == p) return false;
}
return true;
}
bool Sudoku::Help_Solve(int i, int j)
{
int nextrow, nextcol;
while(change[i][j] == 1)
{
j++;
if(j > 9)
{
j = 1;
i++;
}
if(i > 9) return true;
}
for(int p = 1; p <= 9; p++)
{
if(Game.Check_Conflicts(p, i, j))
{
board[i][j] = p;
nextrow = i;
nextcol = j+1;
if(nextcol > 9)
{
nextcol = 1;
nextrow++;
}
if(nextcol == 1 && nextrow == 10) return true;
if(Game.Help_Solve(nextrow, nextcol)) return true;
}
}
board[i][j] = 0;
return false;
}
int main()
{
Game.Add_First_Cord();
Game.Help_Solve(1, 1);
Game.Print_Board();
system("pause");
return 0;
}
It looks like Sudoku::Check_Conflicts returns true if the number CAN be placed there, or false if it CAN'T be placed there due to a simple conflict. A different function name could maybe better self-document the code.
The thing is rhat I can't understand why it continues if in the end it
returns false :/
It doesn't ALWAYS return at the bottom of the function tho':
bool Sudoku::Help_Solve(int i, int j)
{
int nextrow, nextcol;
while(change[i][j] == 1) //We find the first cell in which we can change the number
{
j++;
if(j > 9)
{
j = 1;
i++;
}
if(i > 9) return true;
-------------------------^^^^
returns true if we have filled all squares.
}
for(int p = 1; p <= 9; p++)
{
if(Game.Check_Conflicts(p, i, j)) //We are checking for conflicts
{
board[i][j] = p;
nextrow = i;
nextcol = j+1;
if(nextcol > 9)
{
nextcol = 1;
nextrow++;
}
if(nextcol == 1 && nextrow == 10) return true;
-----------------------------------------------------^^^^
returns when we have filled everything!
if(Game.Help_Solve(nextrow, nextcol)) return true;
---------------------------------------------------------^^^^
returns if we filled at the next level of solution.
}
}
board[i][j] = 0;
return false;
-----------^^^^^ returns if we failed to fill the whole thing.
}
As someone else mentioned in a comment, there are some trivial things that can be done to improve on the algorithm - such as looking for the "most suitable place to fill first" [which doesn't improve the worst case, but it does improve the typical case].
I have written a Sudoku solver that uses a similar algorithm, but it tries to find the cell with the lowest number of candidates (possible numbers to go in the that cell) and only tries recursively if there are multiple choices.