The method of elimination is derived directly from the rule of sudoku :
- Row Elimination : No cells in the same row are allowed to contain duplicate digits
- Column Elimination : No cells in the same column are allowed to contain duplicate digits
- Region Elimination : No cells in a region are allowed to contain duplicate digits
For simple puzzle solvable by the method of elimination, the sudoku solver can quit immediately.
The following is a puzzle solvable by elimination only :
//
String puzzle= ".4.61..9."+
".7..5...."+
"1.3948..."+
"961.....2"+
"..58261.."+
"8.....365"+
"...3792.4"+
"....8..5."+
".8..65.3.";
And the solution is :
After all eliminations: 2 |4 |8 |6 |1 |7 |5 |9 |3 6 |7 |9 |2 |5 |3 |4 |1 |8 1 |5 |3 |9 |4 |8 |7 |2 |6 9 |6 |1 |5 |3 |4 |8 |7 |2 7 |3 |5 |8 |2 |6 |1 |4 |9 8 |2 |4 |7 |9 |1 |3 |6 |5 5 |1 |6 |3 |7 |9 |2 |8 |4 3 |9 |7 |4 |8 |2 |6 |5 |1 4 |8 |2 |1 |6 |5 |9 |3 |7
The following is a puzzle not solvable by elimination alone :
//
String puzzle= "9.1..4..."+
"......296"+
".8....4.7"+
"21...6..."+
"..6.23..4"+
".5.94...."+
".....8.4."+
"....7..3."+
"....316.5";
The result after all eliminations is :
After all eliminations: 9 |2367 |1 |23678 |68 |4 |358 |58 |38 347 |347 |347 |1378 |18 |5 |2 |9 |6 356 |8 |235 |1236 |169 |29 |4 |15 |7 2 |1 |34789 |58 |58 |6 |35789 |578 |389 78 |79 |6 |158 |2 |3 |15789 |1578 |4 38 |5 |38 |9 |4 |7 |138 |1268 |1238 13567 |23679 |23579 |256 |569 |8 |179 |4 |129 14568 |2469 |24589 |2456 |7 |29 |189 |3 |1289 478 |2479 |24789 |24 |3 |1 |6 |278 |5 Puzzle solvable by method of eliminations : false
Checking puzzle states
For the above simplified puzzle, it can be solved by a recursive "trial and error" algorithm.
Before entering the recursive search routine, we need to check whether the puzzle had already been solved by the method of eliminations.
A straight forward way is just to count the number of possible values in every cell, if all of them have only one possible value, then all cells are solved cells.
// check whether the puzzle is solved
public boolean isSolved()
{
boolean solved=true;
for (int i=0;i<81;i++)
{
if (cells[i].size()!=1) { solved=false; break; }
}
return solved;
}
Method of Recursion
This method is based on trial an error. The algorithm of the Recursive Solver is :- Find next unsolved cell in the puzzle (cell with more than one possible values)
- We will name this cell as 'X'. Fill cell X with one of the possible value(a trial)
- call solveByElimination()
- If the puzzle is solved, return true
- check for conflict (a puzzle is in conflict state if the elimination process eliminates all possible values of some cells)
- If the puzzle is not solved and not in conflict state, call the recursive solver to do a trial and error on the next unsolved cell
- If the puzzle is not solved, fill cell X with next possible value, then go to step 3
- If all possible values of cell X is tried, return false, this tells the parent that the puzzle cannot be solved
//
public boolean solveByRecursion()
{
// before doing anything, backup the puzzle first
ArrayList<Integer>[] backupCells=new ArrayList[81];
for (int i=0;i<81;i++) // allocate back structure
{
backupCells[i]=new ArrayList();
}
cellCopy(cells, backupCells); // backup
// get next unsolved cell
int unsolvedCellIndex=-1;
for (int i=0;i<81;i++)
{
if (cells[i].size()>1) { unsolvedCellIndex=i; break; }
}
// no unsolved cell, the puzzle is solved
if (unsolvedCellIndex==-1) return true;
for (int j=0;j<cells[unsolvedCellIndex].size();j++) // try all possible digits
{
Integer digit = cells[unsolvedCellIndex].get(j);
cells[unsolvedCellIndex].clear(); // clear all values
cells[unsolvedCellIndex].add(digit); // then fill it with only one value
solveByElimination();
if (isSolved()) return true; // solved
if (!isConflict())
{
// The unsolved cell is filled with a trial value, but the puzzle is not solved,
// call myself recursively to do a trial and error on another unsolved cell.
if (solveByRecursion()) return true; // solved
}
// the trial digit cannot solve the puzzle
cellCopy(backupCells,cells); // restore from backup, try next digit
}
// all values of a cell have been tried
return false; // cannot solve this way.
}
The solution of the sample puzzle presented above is :
9 |2 |1 |7 |6 |4 |3 |5 |8 4 |3 |7 |8 |1 |5 |2 |9 |6 6 |8 |5 |3 |9 |2 |4 |1 |7 2 |1 |4 |5 |8 |6 |9 |7 |3 7 |9 |6 |1 |2 |3 |5 |8 |4 3 |5 |8 |9 |4 |7 |1 |6 |2 1 |6 |3 |2 |5 |8 |7 |4 |9 5 |4 |2 |6 |7 |9 |8 |3 |1 8 |7 |9 |4 |3 |1 |6 |2 |5 Puzzle solvable by method of recursion : trueMore sample puzzles here :
// sample puzzle 1
String puzzle= ".9..76.1."+
".374....."+
".......57"+
".2..54..."+
"....6.9.5"+
".1.9.3..."+
".5.31..4."+
"..4..2..."+
"1.9....8.";
// sample puzzle 2
String puzzle= "........."+
".13.94..8"+
"8..5.2..."+
".498..2.7"+
".....1.83"+
"13......5"+
"2...7...6"+
".6......."+
"..72.53..";
The full source code can be view here : SudokuSolver.java
Thanks for reading. Comments are welcome.
No comments:
Post a Comment