I'm trying to make a Sudoku Solving program for a couple of days but I'm stuck with the methods. I found this algorithm here but I don't really understand it:
start at the first empty cell, and put 1 in it.
Check the entire board, and see if there are any conflicts
If there are coflicts on the board, increase the number in the current cell by 1 (so change 1 to 2, 2 to 3, etc)
If the board is clean move, start at step one again.
If all nine possible numbers on a given cell cause a conflict in the board, then you set this cell back to empty, go back to the previous cell, and start again from step 3 (this is where the 'backtracking' comes in).
Here is my code. I think something is wrong with my Help_Solve(...) function. Can you help me to identify the problem, please?
#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();
void Solve();
void 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 = 1; i <= 9; i++)
for(int j = 1; 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] == p || board[i-1][j+1] == p ||
board[i][j+1] == p || board[i+1][j+1] == p || board[i+1][j+2] == p ||
board[i][j+2] == p || board[i+1][j+2] == p)return false;
}
/*
0*0
000
000
*/
if((j == 2 || j == 5 || j == 8) && (i == 1 || i == 5 || i == 7))
{
if(board[i-1][j] == p || board[i+1][j] == p || board[i-1][j+1] == p ||
board[i][j+1] == p || board[i+1][j+1] == p || board[i+1][j+2] == p ||
board[i][j+2] == p || board[i+1][j+2] == 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][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-1][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-1] == 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;
}
void Sudoku::Help_Solve(int i, int j)
{
if(j <= 0)
{
i = i-1;
j = 9;
}
if(change[i][j] == 1) return Game.Help_Solve(i, j-1);
for(int p = 1; p <= 9; p++)
if(Game.Check_Conflicts(p, i, j))
{
board[i][j] = p;
return;
}
return Game.Help_Solve(i, j-1);
}
void Sudoku::Solve()
{
for(int i = 1; i <= 9; i++)
{
for(int j = 1; j <= 9; j++)
{
if(board[i][j] == 0 && change[i][j] == 0)
{
Game.Help_Solve(i, j);
}
}
}
for(int i = 1; i <= 9; i++)
for(int j = 1; j <= 9; j++)
if(board[i][j] == 0) Game.Help_Solve(i, j);
}
int main()
{
Game.Add_First_Cord();
Game.Solve();
Game.Print_Board();
system("pause");
return 0;
}
Edit: I need to use recursion right? But maybe the parameters I give to the function are wrong. I really don't know. In Add_First_Cord() I declare the starting values that every sudoku has in the beginning. Here are the values that I use: http://bg.wikipedia.org/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Sudoku-by-L2G-20050714.gif. I expect to see the solved sudoku as it is shown in wikipedia. But some solved values are right others are not. Here is what I get in the console
Suggested Approach
Implement a generic graph search algorithm
could use either IDFS or A* graph search
I would prefer the second
do this for a general directed graph
node type TNode
node successor function TNode => vector<TNode>
Define your Sudoku states
a state is a 9x9 array with a number 1, 2, ..., or 9 or a blank in each position
Define what a goal Sudoku state is
all 81 cells filled in
all 9 rows have numbers {1, 2, ..., 9} in them
all 9 columns have numbers {1, 2, ..., 9} in them
all 9 3x3 squares have numbers {1, 2, ..., 9} in them
Define your valid Sudoku state successor function
a state S can have number N added at row I, column J if:
cell (I,J) is empty
there is no other N in row I
there is no other N in column J
there is no other N in the 3x3 square containing (I,J)
the state successor function maps a state S to the vector of states that satisfy these rules
Apply your generic graph search algorithm (1) to the Sudoku state graph (2-4)
(optional) If you do choose to use A* graph search, you can also define a heuristic on your Sudoku state space to potentially drastically increase performance
how to design the heuristic is another whole problem, that's more of an art than a science
Current Approach
Your current approach mixes the specification of the graph to be searched and the implementation of the search algorithm. You're going to have a lot of difficulty if you mix those two. This problem naturally separates into two distinct pieces -- the algorithm and the graph -- so you can and should exploit that in your implementation. It will make it much simpler.
The other benefit you get if you go with this separation is that you will be able to reuse your graph search algorithm on a huge number of problems - very cool!
The following assumes you are trying to solve a given board, not generate a puzzle.
Basic (simple) approach
Create a class whose objects can hold a board (here called board_t). This class may internally use array, but must support copying boards.
Have a function void solve(board_t const& board); which repeats the following for each number n:
Copies your input
Enters n in the first empty cell of the copied board
If the copied board is a solution, print the solution and return.
Else If the board is still viable (e.g. no conflicts):
call solve(copied_board)
Performance
This is a recursive backtracking solution, which performs horribly for hard problems. You can significantly speed it up by proper pruning or deductive steps (e.g. if you end up with 8 numbers in a row after inserting one, you can immediately enter the ninth without any kind of search).
Reasoning
While certainly not an impressive technique, it has a high probability of working correctly, since you will only ever be modifying a copy to add a single value. This prevents corruption of your data structures (one problem your idea has is that it will destroy the numbers it finds when backtracking, are not necessarily the ones you just inserted, but may be part of the initial puzzle).
Improving performance is quite simple, once you start picking more intelligent heuristics (e.g. instead of testing the square in order, you could pick the ones with the fewest remaining moves and try to get them out of the way - or do the reverse...) or start doing a bit of deduction and pruning.
Note: The Algorithm Design Manual uses a Soduko solver to show the impact of these techniques on backtracking.
There is one very important modification to recursive algorithms: Use most constrained first approach. This means first to solve a cell with smallest number of possible candidates (when direct row/column/block conflicts are removed).
Another modification is: Change the board in-place; do not copy it. In each recursive call you modify only one cell on the board, and that cell used to be empty. If that call doesn't end up in a solved board somewhere down the recursive call tree, just clear the cell again before returning - this returns the board into original state.
You can find a very short and fast solution in C# on address: Sudoku Solver. It solves arbitrary sudoku board in about 100 steps only, all thanks to the most constrained first heuristic.
This is a classic Constraint Satisfaction Problem. I recommend doing some research on the topic to figure out the successful strategy. You will need to use AC-3 ( Arc Consistency 3) algorithm along with the backtracking techniques to solve the problem.
Related
void generateSudoku(int sudoku[][C])
{
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
sudoku[i][j] = generateRandNum(); //generate random number for all 2d array
while (sudoku[1][0] == sudoku[0][0] || sudoku[2][0] == sudoku[1][0] || sudoku[2][0] == sudoku[0][0]
|| sudoku[3][0] == sudoku[2][0] || sudoku[3][0] == sudoku[1][0] || sudoku[3][0] == sudoku[0][0])
sudoku[i][j] = generateRandNum();
while ( sudoku[i][1] == sudoku[i][0] || sudoku[1][1] == sudoku[0][1] || sudoku[2][1] == sudoku[1][1]
|| sudoku[2][1] == sudoku[0][1] || sudoku[3][1] == sudoku[2][1] || sudoku[3][1] == sudoku[1][1]
|| sudoku[3][1] == sudoku[0][1]) //index 1 to index 0
sudoku[i][j] = generateRandNum();
while ( (sudoku[i][2] == sudoku[i][0]) || (sudoku[i][2] == sudoku[i][1]) || sudoku[1][2] == sudoku[0][2]
|| sudoku[2][2] == sudoku[1][2] || sudoku[2][2] == sudoku[0][2] || sudoku[3][2] == sudoku[2][2]
|| sudoku[3][2] == sudoku[1][2] || sudoku[3][2] == sudoku[0][2])
sudoku[i][j] = generateRandNum();
while ( (sudoku[i][3] == sudoku[i][0]) || (sudoku[i][3] == sudoku[i][1]) || (sudoku[i][3] == sudoku[i][2])) //index 3 to index 2,1,0
sudoku[i][j] = generateRandNum();
}
}
}
Is there more efficient and easy way to generate 2d array with random numbers that is distinct with each column and row like a sudoku? The code works, but execution time is too long, probably caused by so many loops. Also I'm a beginner (first year cs students) so this is the only way I can think of to make it distinct (yeah i know its stupid and inefficient and wrong), as I don't know how to do complex algorithm.
EDIT: generateRandNum:
int generateRandNum()
{
int randNum;
randNum = (rand() % 4)+1;
return randNum;
}
I don't know whether this is helpful but I found a simple algorithm in another thread to generate a complete sudoku puzzle. For more details, check this thread. This is my short implementation of this algorithm:
std::array <unsigned int, 9> seed = {8, 9, 3, 2, 7, 6, 4, 5, 1};
std::array <std::array <unsigned int, 9>, 9> generate(std::array
<unsigned int, 9> seed)
{
unsigned int seedOffset {0};
std::array <std::array <unsigned int, 9>, 9> field;
field.at(0) = seed;
for(unsigned int fieldIndex {1}; fieldIndex < field.size(); ++fieldIndex)
{
seedOffset = (0 == (fieldIndex % 3)) ? 1 : 3;
std::rotate(seed.begin(), seed.begin() + seedOffset, seed.end());
field.at(fieldIndex) = seed;
}
return field;
}
I have an array that holds a 16-bit value with each bit in an array index. What I want to do is perform a "bit-wise" XOR of particular array elements and then shift all the elements over by 1 (with wrapping).
In particular, I want to use XOR at the array elements 2, 3, and 5 with last element, 16.
This code is supposed to be cyclic, such that once it has completed a particular number of cycles (65535), it should return to the original input value.
Here is my code:
#include <iostream>
using namespace std;
void main()
{
//Initial array input
int state_array[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 };
int temp[1] = { 0 };
int array_size = sizeof(state_array) / (sizeof(temp[0]));
for (int i = 0; i<65535; i++)
{
temp[0] = state_array[15];
//XOR Values
for (int j = 0; j<16; j++) {
if ((j == 2 || j == 3 || j == 5) && state_array[15] == 1) {
state_array[j] = !state_array[j];
}
}
//Shift values
for (int j = array_size-1; j>0; j--)
{
if (j == 0) {
state_array[0] = temp[0];
}
else {
state_array[j] = state_array[j-1];
}
}
}
}
What should happen is that after 65535 iterations, the array returns back to value 0000000000000001, but this does not happen and I cannot figure out why. I feel like its a small, obvious thing I am overlooking in my code but, I can't figure it out.
The issue is that you're not indexing correctly. Instead of your statement that does the XORing looking like this:
if ((j == 2 || j == 3 || j == 5) && state_array[15] == 1) {
state_array[j] = !state_array[j];
}
it needs to be 0-indexed, not 1, and should look like this:
if ((j == 1 || j == 2 || j == 4) && state_array[15] == 1) {
state_array[j] = !state_array[j];
}
Ironically, your state_array[15] was correct, it's just 2, 3, and 5 that need to be fixed.
Additionally, your for loop should have the condition j>=0 not just j>0.
In the shift section you will never hit the j == 0 condition as your for loop condition is j > 0
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.
For a homework assignment: I'm supposed to create randomized alphabetial keys, print them to a file, and then hash each of them into a hash table using the function "goodHash", found in my below code.
When I try to run the below code, it says my "goodHash" "identifier isn't found". What's wrong with my code?
#include <iostream>
#include <vector>
#include <cstdlib>
#include "math.h"
#include <fstream>
#include <time.h>
using namespace std;
// "makeKey" function to create an alphabetical key
// based on 8 randomized numbers 0 - 25.
string makeKey() {
int k;
string key = "";
for (k = 0; k < 8; k++) {
int keyNumber = (rand() % 25);
if (keyNumber == 0)
key.append("A");
if (keyNumber == 1)
key.append("B");
if (keyNumber == 2)
key.append("C");
if (keyNumber == 3)
key.append("D");
if (keyNumber == 4)
key.append("E");
if (keyNumber == 5)
key.append("F");
if (keyNumber == 6)
key.append("G");
if (keyNumber == 7)
key.append("H");
if (keyNumber == 8)
key.append("I");
if (keyNumber == 9)
key.append("J");
if (keyNumber == 10)
key.append("K");
if (keyNumber == 11)
key.append("L");
if (keyNumber == 12)
key.append("M");
if (keyNumber == 13)
key.append("N");
if (keyNumber == 14)
key.append("O");
if (keyNumber == 15)
key.append("P");
if (keyNumber == 16)
key.append("Q");
if (keyNumber == 17)
key.append("R");
if (keyNumber == 18)
key.append("S");
if (keyNumber == 19)
key.append("T");
if (keyNumber == 20)
key.append("U");
if (keyNumber == 21)
key.append("V");
if (keyNumber == 22)
key.append("W");
if (keyNumber == 23)
key.append("X");
if (keyNumber == 24)
key.append("Y");
if (keyNumber == 25)
key.append("Z");
}
return key;
}
// "makeFile" function to produce the desired text file.
// Note this only works as intended if you include the ".txt" extension,
// and that a file of the same name doesn't already exist.
void makeFile(string fileName, int n) {
ofstream ourFile;
ourFile.open(fileName);
int k; // For use in below loop to compare with n.
int l; // For use in the loop inside the below loop.
string keyToPassTogoodHash = "";
for (k = 1; k <= n; k++) {
for (l = 0; l < 8; l++) { // For-loop to write to the file ONE key
ourFile << makeKey()[l];
keyToPassTogoodHash += (makeKey()[l]);
}
ourFile << " " << k << "\n";// Writes two spaces and the data value
goodHash(keyToPassTogoodHash); // I think this has to do with the problem
makeKey(); // Call again to make a new key.
}
}
// Primary function to create our desired file!
void mainFunction(string fileName, int n) {
makeKey();
makeFile(fileName, n);
}
// Hash Table for Part 2
struct Node {
int key;
string value;
Node* next;
};
const int hashTableSize = 10;
Node* hashTable[hashTableSize];
// "goodHash" function for Part 2
void goodHash(string key) {
int x = 0;
int y;
int keyConvertedToNumber = 0;
// For-loop to produce a numeric value based on the alphabetic key,
// which is then hashed into hashTable using the hash function
// declared below the loop (hashFunction).
for (y = 0; y < 8; y++) {
if (key[y] == 'A' || 'B' || 'C')
x = 0;
if (key[y] == 'D' || 'E' || 'F')
x = 1;
if (key[y] == 'G' || 'H' || 'I')
x = 2;
if (key[y] == 'J' || 'K' || 'L')
x = 3;
if (key[y] == 'M' || 'N' || 'O')
x = 4;
if (key[y] == 'P' || 'Q' || 'R')
x = 5;
if (key[y] == 'S' || 'T')
x = 6;
if (key[y] == 'U' || 'V')
x = 7;
if (key[y] == 'W' || 'X')
x = 8;
if (key[y] == 'Y' || 'Z')
x = 9;
keyConvertedToNumber = x + keyConvertedToNumber;
}
int hashFunction = keyConvertedToNumber % hashTableSize;
Node *temp;
temp = new Node;
temp->value = key;
temp->next = hashTable[hashFunction];
hashTable[hashFunction] = temp;
}
// First two lines are for Part 1, to call the functions key to Part 1.
int main() {
srand ( time(NULL) ); // To make sure our randomization works.
mainFunction("sandwich.txt", 5); // To test program
cin.get();
return 0;
}
I realize my code is cumbersome in some sections, but I'm a noob at C++ and don't know much to do it better.
I'm guessing another way I could do it is to AFTER writing the alphabetical keys to the file, read them from the file and hash each key as I do that, but I wouldn't know how to go about coding that.
C++ expected everything to be declared in order, so that nothing's used before it's declared.
If you need to refer to a function higher in the file than where it's defined, you need to have a function prototype near the top of the file that declares the function. (Writing prototypes for all functions is a standard practice as a result of this.)
Near the top of the file (after the #includes) simply add
void goodHash(string key);
Definitions
Function declaration: something that declares the name of the function and the types the function takes.
Function definition: something that specifies the actual code of the function.
if you insert
void goodHash(string key);
in the line under "using namespace..." it will work
The issue is that you have to forward declare goodHash or define goodHash before makeFile if you want to use goodHash in makeFile. Otherwise, when the compile is in makeFile, it sees the token goodHash and hasn't found out what it means, which is why you are getting the compile-time error.
EDIT: Here is a good resource on forward declarations
you forgot the function prototype just add this in the top:
void goodHash(string key);
and btw your makeKey() is too long
you can try this instead:
string makeKey() {
int k;
string key = "";
for (k = 0; k < 8; k++) {
int keyNumber = (rand() % 25);
char app[2];
app[0] = keyNumber + 'A';
app[1] = 0;
key.append(app);
}
return key;
}
Question - A Little Elephant from the Zoo of Lviv likes lucky numbers very much. Everybody knows that the lucky numbers are positive integers whose decimal representation contains only the lucky digits 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not.
Let F4(X) be the number of digits 4 in the decimal representation of X, and F7(X) be the number of digits 7 in the decimal representation of X. For example, F4(456) = 1, F4(444) = 3, F7(1) = 0, F7(747) = 2. The Little Elephant wants to know the largest product F4(X) ∙ F7(X), where L ≤ X ≤ R. In other words he wants to know the value
max{F4(X) ∙ F7(X) : L ≤ X ≤ R}.
1 <= L <= R <= 1018
Example:
1) For the range, 1 100 answer will be 1 {47,74}
2) 4199 6000 answer will be 4 {4747, 4477}
I feel my code is correct, but on submitting it's getting the verdict Wrong Answer. Can anybody help me find out exactly what is going wrong?
My algorithm cannot be wrong (it's very straightforward). I've double checked the implementation (it handles all possible cases). It's difficult to believe that it's going wrong for some input.
Here's the C++ code:
#include <cstdio>
#include <cstring>
using namespace std;
char buf1[20],buf2[20];
int *L, *R, *ans, len, ansn;
bool flagL, flagR;
inline int count(int n)
{
int a=0,c=0;
for(;a<len;a++) if(ans[a] == n) c++;
return c;
}
inline int max(int a, int b) { return a>b ? a:b; }
inline int min(int a, int b) { return a<b ? a:b; }
inline void f(int i, int n)
{
int a=0,n4=0,n7=0,t;
for(;a<=i;a++) if(ans[a] == 4) n4++; else if(ans[a] == 7) n7++;
while(n)
{
if(n4 == n7)
{
n4 += n/2;
n7 += (n-n/2);
break;
}
else if(n4 > n7)
{
t = min(n,n4-n7);
n -= t;
n7 += t;
}
else if(n7 > n4)
{
t = min(n,n7-n4);
n -= t;
n4 += t;
}
}
ansn = max(ansn,n4*n7);
}
void solve(int i, bool flagL, bool flagR)
{
while(i<len)
{
if(flagL && !flagR)
{
if(4 > L[i])
{
f(i-1,len-i);
return;
}
if(4 == L[i])
{
ans[i] = 4;
solve(i+1, 1, 0);
ans[i] = 7;
f(i,len-i-1);
return;
}
if(7 > L[i])
{
ans[i] = 7;
f(i,len-i-1);
return;
}
if(7 == L[i])
{
ans[i] = 8;
f(i,len-i-1);
ans[i] = 7;
i++;
continue;
}
// else
ans[i] = 9;
if(ans[i] > L[i])
{
f(i,len-i-1);
return;
}
else
{
i++;
continue;
}
}
if(!flagL && flagR)
{
if(7 < R[i])
{
f(i-1,len-i);
return;
}
if(7 == R[i])
{
ans[i] = 4;
f(i,len-i-1);
ans[i] = 7;
i++;
continue;
}
if(4 < R[i])
{
ans[i] = 4;
f(i,len-i-1);
return;
}
if(4 == R[i])
{
ans[i] = 3;
f(i,len-i-1);
ans[i] = 4;
i++;
continue;
}
// else
ans[i] = 0;
if(ans[i] < R[i])
{
f(i,len-i-1);
return;
}
else
{
i++;
continue;
}
}
if(flagL && flagR)
{
if(R[i] - L[i] == 1)
{
ans[i] = L[i];
solve(i+1,1,0);
ans[i]++;
solve(i+1,0,1);
return;
}
bool four = 4 > L[i] && 4 < R[i];
bool sev = 7 > L[i] && 7 < R[i];
if (four && sev)
{
f(i-1,len-i);
return;
}
else if (four && !sev)
{
ans[i] = 4;
f(i,len-i-1);
}
else if (!four && sev)
{
ans[i] = 7;
f(i,len-i-1);
}
if (L[i] == 4 || L[i] == 7 || R[i] == 4 || R[i] == 7)
{
if(L[i] == R[i]) { ans[i] = L[i]; i++; continue; }
if(L[i] == 4 && R[i] == 7)
{
ans[i] = 4;
solve(i+1,1,0);
ans[i] = 7;
solve(i+1,0,1);
ans[i] = 5;
f(i,len-i-1);
return;
}
if(R[i] - L[i] >= 2)
{
ans[i] = L[i]+1;
f(i,len-i-1);
if(L[i] == 4 || L[i] == 7)
{
ans[i] = L[i];
solve(i+1,1,0);
}
if(R[i] == 4 || R[i] == 7)
{
ans[i] = R[i];
solve(i+1,0,1);
}
return;
}
}
else
{
if (R[i] - L[i] >= 2)
{
ans[i] = L[i]+1;
f(i,len-i-1);
return;
}
ans[i] = L[i];
}
}
i++;
} // end of while
ansn = max(ansn, count(4)*count(7));
}
int main()
{
int a,t; scanf("%d\n",&t);
while(t--) // test cases
{
scanf("%s %s",&buf1,&buf2);
len = strlen(buf2);
L = new int[len];
R = new int[len];
ans = new int[len];
for(a=0;a<len;a++) R[a] = buf2[a]-48;
for(a=0;a<len-strlen(buf1);a++) L[a] = 0;
int b=a;
for(;a<len;a++) L[a] = buf1[a-b]-48;
flagL = flagR = 1; ansn = 0;
solve(0,1,1);
printf("%d\n",ansn);
}
return 0;
}
The algorithm:
Firstly, put the digits of L,R in arrays L[],R[] of length = no. of digits in R. And initialize an array ans[] for keeping track of the answer integer (integer for which F4(ans)*F7(ans) is maximum).
Pad L by 0 on the left, to make it equal to R in length. (so 1,100 becomes 001,100)
This is done in main() itself, before making a call to solve()
The real logic:
Run a loop, for i in range(0,len(R))
For each i, compare L[i] and R[i]
Variables flagL and flagR tell you whether or not, you need to check L and R respectively.
Supposing the L[], R[] is initially:
238 967
First we need to check both of them starting from 0th index (hence solve(0,1,1) or solve(0,true,true) ).
Now 4 and 7 both fall between L[0] and R[0]. So any permutation of {4,7} can be put in the 3 digits, without ans[] going out of range [L,R]. So answer will be 2.
If the range would have been:
238 and 545
Only 4 would fall in between 2 and 5, so we shall put 4 in ans[0], and any permutation of {4,7} can be put in the remaining places. So answer is again 2.
What if the range is:
238 and 410
Neither 4 nor 7 fall in between L[0] and R[0].
But note that R[0] is 4.
So we shall now have 2 choices to put, 4 and L[0]+1 (this is where recursion comes in)
Why L[0]+1 ? Because if we put L[0]+1 in ans[0], ans[0] would fall in between L[0] and R[0] (for this R[0] - L[0] >= 2) and whatever we put in the remaining digits, ans[] would never go out of range. But we also have to check with ans[0] being 4. In the last example, it won't help, but it would if R was >= 477.
So the answer would be 1. (2 if R was >= 477)
Let's discuss another example:
Range: 4500 5700
Because R[0] and L[0] differ by only 1, we will have to check for both, once for ans[i] = L[i], then ans[i] = R[i] (or ans[i]++ )
Now if we check for ans[i] = 4, we won't have to compare ans[i] and R[i] anymore, since ans[0] < R[0], hence ans will always be < R. So we call solve() recursively like this: solve(i+1, true, false)
Next time, when ans[0] = R[0], then we won't have to compare ans with L (since ans > L, whatever we put in the remaining 2 places). Then we call solve() like this: solve(i+1, false, true).
You get the idea of how it's working, and also, if you look at my code, no possible test case is being left out. I don't know why I'm getting a WA.
PS: Andrew pointed out the mistake. The order of conditions was wrong. The if block 4 == L[i] should have come before the if block 7 > L[i]. Now the code works correctly.
if(7 > L[i]) // 7 > 4 ?
{
ans[i] = 7;
f(i,len-i-1);
return;
}
if(4 == L[i]) // how is this ever reachable?
{
ans[i] = 4;
solve(i+1, 1, 0);
ans[i] = 7;
f(i,len-i-1);
return;
}
I think you mean:
- if(7 > L[i])
+ if(7 < L[i])