The algorithms described in the previous sections need two subtle features:
The cyclic reduction algorithm (see Section 4.5, “Cyclic reduction”) needs to know when a pass through all the slots has not eliminated any choices, so that it will not loop endlessly.
The recursive algorithm (see Section 4.6, “The recursive algorithm”) needs a backtracking mechanism, so that choices removed from slots due to earlier assumptions can be reinstated.
Accordingly, we define a class
that contains these mechanisms.
An instance of this class is primarily a container for the word list.
This instance is the logical place to hold the current list of word choices for each slot. We can keep a running count of the total number of choices for the entire puzzle. When this count is exactly the same as the number of slots, we know that there is only one choice per slot, hence the puzzle is solved. The obvious data structure here is a dictionary whose keys are slot instances, and each related value is a list of the word choices for that slot.
Furthermore, the cyclic reduction algorithm can record the value of this running count before each pass through the set of slots, and then check it again after the pass. If the value has not changed, we know we have reached the point where we are no longer eliminating choices.
Building and reducing the list of choices for each
slot will be done by calling methods on this
the instance that a given word may be the solution to
a given slot; method
the instance that a given word is not the solution
to a given slot.
Applying the unique-slot test (see Section 4.5, “Cyclic reduction”) means that we need to know the set of slots that include a given word in their choices. This will be implemented by a dictionary whose keys are the words in the puzzle, and each corresponding value is a list of the slots for which this word is still one of the choices.