# coding=utf-8
#*****************************************************************************
#       Copyright (C) 2009 Franco Saliola <saliola@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#                  http://www.gnu.org/licenses/
#*****************************************************************************

To define a new class of words, one should inherit from Words_all (or any
class that inherits from it) and implement the following methods.

    - self.alphabet() -- return the alphabet (by default, self._alphabet)

    - size_of_alphabet -- number of letters in the underlying alphabet (can
      by Infinity)

    - cmp_letters(x,y) -- a function to compare letters in the alphabet;
      should behave like Python's cmp function (that is, it returns -1, 0
      or 1, if x < y, x == y, x > y, respectively). By default, this points
      to Python's cmp function.

    - has_letter(x) -- returns True or False according to whether the
      alphabet contains x or not. Default implementation: x in self._alphabet.

By implementing the above methods, almost anything can be used as an
alphabet.

EXAMPLE 1: Using a list for the alphabet.

    self._alphabet = [0,1,2,3]

    def size_of_alphabet(self):
        return len(self._alphabet)

    def cmp_letters(self,x,y):
        return cmp(self._alphabet.index(x), self._alphabet.index(y))

EXAMPLE 2: Using a CombinatorialClass as an alphabet.

    self._alphabet = Partitions(3)

    def size_of_alphabet(self):
        return self._alphabet.cardinality()

    def cmp_letters(self, letter1, letter2):
        return self._alphabet.rank(letter1) - self._alphabet.rank(letter2)

EXAMPLE 3: Integers.

    self._alphabet = ZZ

    def size_of_alphabet(self):
        return Infinity

    def cmp_letters(self, letter1, letter2):
        return letter1 - letter2

