## 38. `Puzzle.__cyclicReduction()`: Eliminate choices at slot intersections

kkck
```# - - -   P u z z l e . _ _ c y c l i c R e d u c t i o n

def __cyclicReduction ( self ):
'''Eliminate choices wherever two slots intersect.

[ if cyclic reduction solves self ->
self  :=  self in solved state
return True
else -> return False ]
'''
#-- 1 --
while 1:
```

For the general outline, see Section 4.5, “Cyclic reduction”.

kkck
```            #-- 1 body --
# [ if comparison of all intersecting slots does not
#   reduce the total set of choices in self.__wordBank ->
#     return False
#   else if removing those choices solves the puzzle ->
#     return True
#   else -> I ]
```

To determine whether a round of cyclic reduction has made any progress toward a solution, we rely on Section 69, “`WordBank.totalChoices()`: How many total choices are in the current state?”. Every choice we eliminate will decrement this count. See also Section 36, “`Puzzle.nSlots()`: How many slots are there?”: when the choice count equals the slot count, it's a solution.

kkck
```            #-- 1.1 --
beforeCount = self.__wordBank.totalChoices()

#-- 1.2 --
# [ self.__wordBank  :=  self.__wordBank - (choices
#       eliminated at slot intersections, if any) ]
self.__reduceCycle()
if VERBOSE:
print self.show()

#-- 1.3 --
# [ if the total number of slot choices equals the
#   number of slots ->
#     return True
#   else -> I ]
totalChoices = self.__wordBank.totalChoices()
print ( "=== Cyclic reduction: %d choices for %d slots" %
(totalChoices, self.nSlots()) )
if totalChoices == self.nSlots():
return True

#-- 1.4 --
if beforeCount <= totalChoices:
return False
```