AnnouncementsAnnouncements
This Wednesday, Class and Labs are cancelled!
The last lab is due this Wednesday … how many people are planning on doing it?
Finally posted Exam 2 and solution on the website.
BacktrackingBacktrackingSudoku
BacktrackingBacktrackingProblems seen so far:
◦N Queens Problem◦Magic Number Square◦HW #5 – Tentaizu◦Recitation #9 - Maze
BacktrackingBacktrackingFor the maze problem, what do we
need?◦Basically you need a nxn board that stores
the empty spots and the wall spots.◦Then an nxn board that keeps track of
what’s been used. Unlike the N Queens problem you don’t need to
know what’s been “placed”, so the board and a used matrix will be sufficient.
◦Then you basically just move forward through the maze and keep moving until you hit a dead end (hit a wall, or run off the board) or finish.
SudokuSudokuSudoku has the following constraints:
◦ The rows must contain the numbers 1-9 with no repeats.
◦ The columns must contain the numbers 1-9 with no repeats.
◦ The boxes must contain the numbers 1-9 with no repeats.
8 4 2 63 4 9 1
9 6 8 42 1 6
3 5 78 4 7 5
2 6 1 39 7 1 4
SudokuSudokuWhat will we need to
keep track of?◦ Our current board
int[][] answer◦ Our available options
for each square boolean[][][] options
Once we read in the initial board,◦ We can update our
options. If there is a number
there, everything is set to false other than that number.
If there is not a number there everything is true.
8 4 2 63 4 9 1
9 6 8 42 1 6
3 5 78 4 7 5
2 6 1 39 7 1 4
public class sudoku {private int[][] answer;private boolean[][][] options;
// Constructor that sets up our answer board and our set of options.public sudoku(int[][] initBoard) { answer = new int[SIZE][SIZE]; options = new boolean[SIZE][SIZE][SIZE];
for (int i=0; i<SIZE; i++) { for (int j=0; j<SIZE; j++) {
answer[i][j] = initBoard[i][j];
// This is given to us on the initial board.if (initBoard[i][j] > 0) { // Set all options to false. for (int k=0; k<SIZE; k++)
options[i][j][k] = false;// and the correct one to true.options[i][j][initBoard[i][j] - 1] = true;
}// Open square for right now.else { for (int k=0; k<SIZE; k++)
options[i][j][k] = true;}
} // end j} // end i
}
• answer[][] will hold our current board.• options[][][] will hold the options available for each
cell.
Read in the current answer board.
If there is already a number there, all options are set to false except for the number at that spot.
If BLANK, all options are true.
SudokuSudoku Now that we have our answer
board and our options, how will we solve the Sudoku puzzle using backtracking?◦ We need to check our current
board to see if it is valid Are the rows ok? Are the columns
ok? Are the boxes ok? If any are invalid, then we can return
false.
◦ We also need to reduce our options. Currently our options are only based
on the initial board we filled in. We want to further reduce our
options by looking at what is in each row, column and box.
◦ After all of that is done, we want to fill in the next “best” choice to make a guess. What cell would be the best cell to
make a guess at?
8 4 2 63 4 9 1
9 6 8 42 1 6
3 5 78 4 7 5
2 6 1 39 7 1 4
public boolean go() {
int myRows = checkRows();
int myCols = checkCols();
int myBoxes = checkBoxes();
// Base case: given a completed puzzle.
if (myRows == SOLVED && myCols == SOLVED && myBoxes == SOLVED)
return true;
// Base case: given an invalid puzzle.
else if (myRows == INVALID || myCols == INVALID || myBoxes == INVALID)
return false;
// Redo our options here.
reset();
reduceChoiceRows();
reduceChoiceCols();
reduceChoiceBoxes();
// Choose the next square to "guess" at.
int getNextBestSq = getBest();
int nextRow = getNextBestSq/SIZE;
int nextCol = getNextBestSq%SIZE;
Determine whether any of the rowshave been completely solved ORviolate the constraints.
Then we reset our options here based on our current answer board.
At this point we have checked all rows, and none of them violated our constraint.
See if the puzzle is already solved.
OR if any constraints are violated.
for (int i=0; i<SIZE; i++) {
if (options[nextRow][nextCol][i]) {
// Try this answer.
answer[nextRow][nextCol] = i+1;
// See what happens here.
boolean result = go();
// If it works, immediately return true!
if (result)
return true;
// If we get here, it didn't work, reset to 0 and try again.
answer[nextRow][nextCol] = 0;
// When we undo a choice, we have to redo our options.
reset();
reduceChoiceRows();
reduceChoiceCols();
reduceChoiceBoxes();
}
}
// If none of our options worked, well, it's not solvable!
return false;
Now we check each available option,for the nextRow, nextCol
If that choice worked, we’re done!
If none of our options worked, thenit’s not solvable!
If it’s possible, set the answer to the next available option
Recursively solve the puzzle
Otherwise, undo that choice and redo our options.
SudokuSudokuNow that we have the basic
algorithm, we still have to fill in the following methods:◦CheckRows(), CheckCols(), CheckBoxes()
these will check if any of the rows, columns or boxes have been violated.
◦ReduceChoiceRows(), ReduceChoicCols(), ReduceChoiceBoxes() these will update our options matrix to reduce
the number of possible numbers that can be used in each cell.
◦getBest() will find the next box to fill in, it will return the
one with the lease available options.
public int checkRows() {
boolean seenZero = false;
// Go through each row.
for (int row=0; row<SIZE; row++) {
// At first, we've seen nothing.
boolean[] done = new boolean[SIZE];
for (int k=0; k<SIZE; k++)
done[k] = false;
// Now go through each number in this row.
for (int col=0; col<SIZE; col++) {
if (answer[row][col] == 0)
seenZero = true;
else if (done[answer[row][col] - 1])
return INVALID;
else
done[answer[row][col] - 1] = true;
}
} // end row
// If we saw a zero, the puzzle isn't yet solved.
if (seenZero)
return VALID;
// The rows are solved properly, if we get here.
return SOLVED;
}
Checks if the answer rows are consistent.
Returns INVALID if not, VALID if so but there are empty squares
and SOLVED if all the rows are consistent and SOLVED.
If it’s zero, mark that the row is unfinished.
If we saw a zero, the rows aren’t solved.
Which of the numbers 1 – 9 have been used in this row? Before we start looking they’re all false.
If the current number has already been seen, there’s a duplicate!
Otherwise, just mark that we’ve seen this number already.
Otherwise, the rows are solved!
SudokuSudokureduceChoiceRows() – reduce the
options for each cell, based upon what the current answer of each row is.◦Go through each row
For each row, Store which squares are open (at first they will all be open)
Then, see if any are set to a value, if so mark it as closed.
NOW, go through each square in this row that ISN’T set and put in the only appropriate options based upon what has been used already.
public void reduceChoiceRows()
SudukoSudukogetBest() – returns the square with
the fewest number of options◦Goes through all rows and columns◦If a square is found that is not filled in
(i.e. 0) Then determine how many choices are in that
cell, and see if that beats our current choice. The spot will be returned as SIZE*row + col
so that we can return a single int.
public int getBest()
Optional Homework Optional Homework ProblemProblemFill in the Sudoku shell posted
online and turn in a completed Sudoku solver.
ReferencesReferencesSlides adapted from Arup Guha’s
Computer Science II Lecture notes: http://www.cs.ucf.edu/~dmarino/ucf/cop3503/lectures/
Additional material from the textbook:Data Structures and Algorithm Analysis in
Java (Second Edition) by Mark Allen WeissAdditional images:
www.wikipedia.comxkcd.com