Question text in black, answers in blue.
Scannerto get the digits from the strings -- could there be spaces between the digits?
Yes, that is better, and I have now changed the assignment page.
Indeed we should do that -- apologies that it wasn't in the first version of the assignment. The brown additions to the assignment page should answer your questions, which are good ones. We'll also release a sample driver at some point. (Note added later: The driver was released on the evening of Monday 1 October.)
isBadmethod is supposed to check all nine rows, all nine columns, and all nine boxes whenever it is called. But this seems very wasteful to me. When I call
isBad, it's when I have just changed one cell of a valid
Board. So only one row, one column, and one box could now be bad. Don't I save time by checking only those?
Yes, that is true. The
method does not interact with the outside world so you may write it
how you want. I had envisioned it with no parameters, checking the
Board as you say. But you could have
isBad take two
int parameters for the row
column of the last
Move, and guarantee only to catch
double numbers caused by that move. Or you could overload the
method name and do it both ways. But I don't expect running time to
be an issue with this program -- if you get the backtrack search
right it should be very fast.
There is an excellent general technique called
checkpointing for search problems when you don't know how long
search is supposed to take. Simply add
System.out.println statements that periodically tell you
something about where the program is in its search. You could start
with having it report every move put on or taken off the stack. If
gives you too much information you could put in a counter so it
reports only every thousandth move, or every millionth. If the
sudoku search tells you every time it considers a new number for the
first few open cells, it tells you about reaching the major
subdivisions of the search.
You are solving the puzzle by trial and error. You fill in cells as long as you can with the lowest available number. When you get blocked, you erase the last number you wrote in and increase it by one. The stack is keeping track of the moves you are currently considering, that is, the ones you have made and not yet erased. Making a new move means pushing it onto the stack, and erasing a move means popping it off the stack.
Your search continues until you either find a solution or conclude that there is no solution. (The latter condition happens if your stack becomes empty.) If there is more than one solution, your method should find the first one (in lexicographic order) and return it, never discovering if there are any more.
As you can see from the new driver, the string array is
constructed there. If we had a console application for this class (as
in the Your code uses the string array in the constructor of the
Balanced class from DJW that we discussed today in
lecture), the console application could ask the user for nine strings
and assemble them into a string array. You are supposed to write
three classes, none of which has to build a string array.
Board class, which takes the string array as an
argument. It reads the string, probably with its own
Scanner, and creates the two 2D arrays with the values
given by the strings.
Your code uses the string array in the constructor of the
SudokuSolverobject, with no parameters. What is happening inside this object? Is its only purpose to call
Yes, that is its only purpose. It would be much
the same if
solve were a static method, as in the
PostFixEvaluator class of DJW that we will see Friday.
Balanced class had objects because each such object
had to store the strings of opening and closing characters. But since
there is nothing for a
SudokuSolver object to remember,
it could be replaced by a static method. (Don't do it, though,
because our driver will try to create an object.)
Boardconstructor. You say it gets a
String [ ]argument, but shouldn't it get arguments of type
int [ ] [ ]and
boolean [ ] [ ]because that is what the
Boardobject is supposed to have?
You're right that the
Board object is supposed
to have those two 2D arrays, but the way it gets them is through the
code in the constructor that you must write for
That constructor needs to create the two 2D arrays, then load each
of each 2D array with the correct values. It gets the values by
reading them from the nine strings (one for each row) that come to it
String [ ] object that is its parameter. You can
see what a typical such array looks like by looking at the driver
Scanner is a good way to process a
String, using methods like
PostFixEvaluator code in Section
3.8 of DJW has good examples of how to do this.
BadMoveExceptionclass. Do I need to write that class? I'm sure that my code will never cause the exception.
Yes, you should define the
class and your code should
throw the exception whenever a
Board object is asked to change
a fixed cell. It is possible that our grading driver will test this behavior,
though you are right that the current driver does not.
output2when you meant
output1, and this won't compile because
output2is not yet defined. You also say "second test" in the text output to the console, where you mean "first test".
Fixed about 9:00 Friday morning, thanks.
Yes, very much. We want to do most of the grading automatically, which means we need you to check your solver against our driver. There are several things that might be going wrong for you, besides the bug referred to in Question 2.12 above. If you visit the cells in an order other than the one I expect, you will get a different answer for the first test and will fail the test. If your output string does not exactly match mine for the tests, you will fail the tests -- look carefully for things like extra spaces. You should not get a numerically different solution for the second test, because that puzzle has exactly one solution.
Last modified 5 October 2012