Next / Previous / Contents / Shipman's homepage

13. class Puzzle: The top-level container

kkck
# - - - - -   c l a s s   P u z z l e

class Puzzle(object):
    '''Represents a Kriss Kross puzzle and solving mechanism.

      Exports:
        Puzzle ( inFile ):
          [ inFile is a readable file ->
              if inFile contains a valid puzzle file ->
                return a new Puzzle instance representing that file
              else ->
                raise SyntaxError ]

Exported attributes:

kkck
        .inFile:   [ as passed to constructor, read-only ]
        .size:
          [ the count of rows and columns in the puzzle, as a
            Coords instance ]

Exported methods:

kkck
        .show():
          [ return the current state of the puzzle, in the same
            format as the input framework, as a multi-line string ]
        .whatCell ( coord ):
          [ coord is a Coord instance ->
              if there is a cell at coord ->
                return the Cell instance at that location
              else -> return None ]
        .genCells(): [ generate the cells in self, in ascending order ]
        .whatSlots ( coord ):
          [ coord is a Coord instance ->
              generate all the slots that contain coord, as
              Slot instances, if any ]
        .scan ( j, isV ):
          [ (isV is 0 for horizontal, 1 for vertical) and
            (j is a valid index for dimension isV) ->
              generate the coordinates of row or column j as
              a sequence of Coord instances ]
        .nSlots():
          [ returns the number of slots in self ]
        .genSolutions():
          [ generate a sequence of Puzzle instances representing
            the solutions to self, if any ]

In addition to a WordBank instance that manages the word choices, two internal data structures manage the collections of cells and slots. Both are dictionaries to allow random access.

kkck
      State/Invariants:
        .__wordBank:
          [ a WordBank instance representing the word list and
            the state of solution ]
        .__cellMap:
          [ a dictionary whose keys are (row, column) tuples
            representing the coordinates in self where characters
            can go, and the associated value is a Cell instance
            representing what is at that coordinate ]
        .__slotMap:
          [ a dictionary whose keys are (row, column, isV),
            where (row, column) is the location of the first position
            in a slot in self and isV is 0 for horizontal, 1 for
            vertical, and the associated value is a Slots
            instance representing a slot with that origin and
            orientation ]

The recursive algorithm needs to know the first slot and the successor for each slot.

kkck
        .__firstSlot:
          [ the first slot in self ]
        .__slotSuccessor:
          [ a dictionary whose keys are all the slots in self,
            and each related value is the successor of that slot
            in the sequence, or None for the last slot ]
    '''

There is a subtle point about the indices in .__cellMap and .__slotMap. Initially I was planning to use Coord instances as the indices in .__cellMap. However, if a piece of logic manufactured a different Coordinstance and used it to index .__cellMap, it would get a KeyError. Hence we use tuples to insure that any two coordinates are treated the same.