| 
001002
 003
 004
 005
 006
 007
 008
 009
 010
 011
 012
 013
 014
 015
 016
 017
 018
 019
 020
 021
 022
 023
 024
 025
 026
 027
 028
 029
 030
 031
 032
 033
 034
 035
 036
 037
 038
 039
 040
 041
 042
 043
 044
 045
 046
 047
 048
 049
 050
 051
 052
 053
 054
 055
 056
 057
 058
 059
 060
 061
 062
 063
 064
 065
 066
 067
 068
 069
 070
 071
 072
 073
 074
 075
 076
 077
 078
 079
 080
 081
 082
 083
 084
 085
 086
 087
 088
 089
 090
 091
 092
 093
 094
 095
 096
 097
 098
 099
 100
 101
 102
 103
 104
 105
 
 | package algs13.xbacktrack.xframework;
import algs13.Stack;
import stdlib.StdOut;
/**
 * The driver for the backtracking framework. In order to run the driver,
 * this class must be instantiated and the solve method on the instance of this
 * class must be called.
 *
 * Find the TODOs in this file and implement them. There are also TODOs in
 * xbacktrack.xsudoku.MySudoku (MySudoku.java) for you to complete.
 *
 * This framework is adapted from Timothy Budd: Classic Data Structures in C++,
 * Addison-Wesley, 1994. The design is modernized to use object composition
 * rather than inheritance. It can be used to model any kind of backtracking
 * problem.
 *
 * @param <T> The type of the choices made in the backtracking problem.
 */
public final class MyBacktrackDriver<T> {
    // A reference to the problem instance
    private final XBacktrackProblem<T> problem;
    // The stack used to track the choices we attempt in solving
    // the problem. If the framework solves the problem, the
    // stack will contain the choices that were made in the search
    // for a solution.
    private final Stack<T> theStack = new Stack<>();
    // A counter to track how many times we backtrack.
    private long backtrackCount;
    // A boolean indicating whether the backtracking problem is solved.
    // The setDone() method will set this flag to true.
    private boolean done = false;
    // Constructor for the driver, which orchestrates finding a solution
    // for the problem given.
    public MyBacktrackDriver(XBacktrackProblem<T> problem) {
        if(problem == null) throw new IllegalArgumentException("Backtracking problem must not be null");
        backtrackCount = 0;
        this.problem = problem;
    }
    // Set the done flag to true. This signals to the run method that it stop
    // the backtracking loop.
    public void setDone() {
        this.done = true;
    }
    // Track a choice made representing a search area.
    public void track(T choice) {
        if(choice == null) throw new IllegalArgumentException("Cannot track a null choice");
        // TODO: Track the choice in the stack.
    }
    // Backtrack - throw away the most recent choice and back up to a previous choice to
    // see if a different choice can be made in order to make progress.
    private void backtrack() {
        backtrackCount++;
        // TODO: Backtrack: throw away the most recent choice and go back to the immediate
        // previous choice we made to see if we can make a different choice.
    }
    // TODO: Implement this method.
    private void run() {
        // Run the main backtracking loop. You will need to create a loop.
        
        // Until the done flag is flipped to true:
        // If there is no way we can build on the most recent choice we made (i.e. the
        // element that is at the top of the stack), stop and return.
        // If there is a choice at the top of the stack, see if we can make progress after
        // having made that choice. As we are checking, we need to look at it, not remove
        // it from the stack, and pass it to the advance method on the backtracking problem.
        // If we can advance, keep going, unless the problem implementation
        // flipped the done flag to true. If we cannot advance, we must call driver.backtrack();
    }
    /**
     * A method to solve the problem.
     * @return a result representing the solution
     */
    public XBacktrackResult solve() {
        problem.initialize(this);
        run();
        StdOut.format("Backtracked %,d times\n", backtrackCount);
        if(!done || theStack.isEmpty()) return new XBacktrackFailure();
        // Reverse the order of the choices from the stack.
        Stack<T> s = new Stack<>();
        while(!theStack.isEmpty()) {
            s.push(theStack.pop());
        }
        return new XBacktrackSuccess<>(s);
    }
}
 |