'''This module implements specialized container datatypes providing
alternatives to Python's general purpose built-in containers, dict,
list, set, and tuple.

* namedtuple   factory function for creating tuple subclasses with named fields
* deque        list-like container with fast appends and pops on either end
* ChainMap     dict-like class for creating a single view of multiple mappings
* Counter      dict subclass for counting hashable objects
* OrderedDict  dict subclass that remembers the order entries were added
* defaultdict  dict subclass that calls a factory function to supply missing values
* UserDict     wrapper around dictionary objects for easier dict subclassing
* UserList     wrapper around list objects for easier list subclassing
* UserString   wrapper around string objects for easier string subclassing

'''

################################################################################
### OrderedDict

    # An inherited dict maps keys to values.
    # The inherited dict provides __getitem__, __len__, __contains__, and get.
    # The remaining methods are order-aware.
    # Big-O running times for all methods are the same as regular dictionaries.

    # The internal self.__map dict maps keys to links in a doubly linked list.
    # The circular doubly linked list starts and ends with a sentinel element.
    # The sentinel element never gets deleted (this simplifies the algorithm).
    # The sentinel is in self.__hardroot with a weakref proxy in self.__root.
    # The prev links are weakref proxies (to prevent circular references).
    # Individual links are kept alive by the hard reference in self.__map.
    # Those hard references disappear when a key is deleted from an OrderedDict.

"Create the ordered dict object and set up the underlying structures."

'''Initialize an ordered dictionary.  The signature is the same as
        regular dictionaries.  Keyword argument order is preserved.
        '''

        # Setting a new item creates a new link at the end of the linked list,
        # and the inherited dictionary is updated with the new key/value pair.
        
        # Deleting an existing item uses self.__map to find the link which gets
        # removed by updating the links in the predecessor and successor nodes.
        
'''Remove and return a (key, value) pair from the dictionary.

        Pairs are returned in LIFO order if last is true or FIFO order if false.
        '''

'''Move an existing element to the end (or beginning if last is false).

        Raise KeyError if the element does not exist.
        '''

'''od.pop(k[,d]) -> v, remove specified key and return the corresponding
        value.  If key is not found, d is returned if given, otherwise KeyError
        is raised.

        '''

'''Insert key with a value of default if key is not in the dictionary.

        Return the value for key if key is in the dictionary, else default.
        '''

'''Create a new ordered dictionary with keys from iterable and values set to value.
        '''

'''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
        while comparison to a regular mapping is order-insensitive.

        '''

### namedtuple

"""Returns a new subclass of tuple with named fields.

    >>> Point = namedtuple('Point', ['x', 'y'])
    >>> Point.__doc__                   # docstring for the new class
    'Point(x, y)'
    >>> p = Point(11, y=22)             # instantiate with positional args or keywords
    >>> p[0] + p[1]                     # indexable like a plain tuple
    33
    >>> x, y = p                        # unpack like a regular tuple
    >>> x, y
    (11, 22)
    >>> p.x + p.y                       # fields also accessible by name
    33
    >>> d = p._asdict()                 # convert to a dictionary
    >>> d['x']
    11
    >>> Point(**d)                      # convert from a dictionary
    Point(x=11, y=22)
    >>> p._replace(x=100)               # _replace() is like str.replace() but targets named fields
    Point(x=100, y=22)

    """

    # Validate the field names.  At the user's option, either generate an error
    # message or automatically replace the field name with a valid name.
    
    # Create all the named tuple methods to be added to the class namespace

    # Modify function metadata to help with introspection and debugging
    
    # Build-up the class namespace dictionary
    # and use type() to build the result class
    
    # For pickling to work, the __module__ variable needs to be set to the frame
    # where the named tuple is created.  Bypass this step in environments where
    # sys._getframe is not defined (Jython for example) or sys._getframe is not
    # defined for arguments greater than 0 (IronPython), or where the user has
    # specified a particular module.
    
########################################################################
###  Counter

                                    # Load C helper function if available

'''Dict subclass for counting hashable items.  Sometimes called a bag
    or multiset.  Elements are stored as dictionary keys and their counts
    are stored as dictionary values.

    >>> c = Counter('abcdeabcdabcaba')  # count elements from a string

    >>> c.most_common(3)                # three most common elements
    [('a', 5), ('b', 4), ('c', 3)]
    >>> sorted(c)                       # list all unique elements
    ['a', 'b', 'c', 'd', 'e']
    >>> ''.join(sorted(c.elements()))   # list elements with repetitions
    'aaaaabbbbcccdde'
    >>> sum(c.values())                 # total of all counts
    15

    >>> c['a']                          # count of letter 'a'
    5
    >>> for elem in 'shazam':           # update counts from an iterable
    ...     c[elem] += 1                # by adding 1 to each element's count
    >>> c['a']                          # now there are seven 'a'
    7
    >>> del c['b']                      # remove all 'b'
    >>> c['b']                          # now there are zero 'b'
    0

    >>> d = Counter('simsalabim')       # make another counter
    >>> c.update(d)                     # add in the second counter
    >>> c['a']                          # now there are nine 'a'
    9

    >>> c.clear()                       # empty the counter
    >>> c
    Counter()

    Note:  If a count is set to zero or reduced to zero, it will remain
    in the counter until the entry is deleted or the counter is cleared:

    >>> c = Counter('aaabbc')
    >>> c['b'] -= 2                     # reduce the count of 'b' by two
    >>> c.most_common()                 # 'b' is still in, but its count is zero
    [('a', 3), ('c', 1), ('b', 0)]

    '''

    # References:
    #   http://en.wikipedia.org/wiki/Multiset
    #   http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
    #   http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
    #   http://code.activestate.com/recipes/259174/
    #   Knuth, TAOCP Vol. II section 4.6.3

'''Create a new, empty Counter object.  And if given, count elements
        from an input iterable.  Or, initialize the count from another mapping
        of elements to their counts.

        >>> c = Counter()                           # a new, empty counter
        >>> c = Counter('gallahad')                 # a new counter from an iterable
        >>> c = Counter({'a': 4, 'b': 2})           # a new counter from a mapping
        >>> c = Counter(a=4, b=2)                   # a new counter from keyword args

        '''

        # Needed so that self[missing_item] does not raise KeyError
        
'''List the n most common elements and their counts from the most
        common to the least.  If n is None, then list all element counts.

        >>> Counter('abracadabra').most_common(3)
        [('a', 5), ('b', 2), ('r', 2)]

        '''

'''Iterator over elements repeating each as many times as its count.

        >>> c = Counter('ABCABC')
        >>> sorted(c.elements())
        ['A', 'A', 'B', 'B', 'C', 'C']

        # Knuth's example for prime factors of 1836:  2**2 * 3**3 * 17**1
        >>> import math
        >>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
        >>> math.prod(prime_factors.elements())
        1836

        Note, if an element's count has been set to zero or is a negative
        number, elements() will ignore it.

        '''

        # Emulate Bag.do from Smalltalk and Multiset.begin from C++.
        
        # There is no equivalent method for counters because the semantics
        # would be ambiguous in cases such as Counter.fromkeys('aaabbc', v=2).
        # Initializing counters to zero values isn't necessary because zero
        # is already the default value for counter lookups.  Initializing
        # to one is easily accomplished with Counter(set(iterable)).  For
        # more exotic cases, create a dictionary first using a dictionary
        # comprehension or dict.fromkeys().
        
'Counter.fromkeys() is undefined.  Use Counter(iterable) instead.'

'''Like dict.update() but add counts instead of replacing them.

        Source can be an iterable, a dictionary, or another Counter instance.

        >>> c = Counter('which')
        >>> c.update('witch')           # add elements from another iterable
        >>> d = Counter('watch')
        >>> c.update(d)                 # add elements from another counter
        >>> c['h']                      # four 'h' in which, witch, and watch
        4

        '''

        # The regular dict.update() operation makes no sense here because the
        # replace behavior results in the some of original untouched counts
        # being mixed-in with all of the other counts for a mismash that
        # doesn't have a straight-forward interpretation in most counting
        # contexts.  Instead, we implement straight-addition.  Both the inputs
        # and outputs are allowed to contain zero and negative counts.

                    # fast path when counter is empty
                    
'''Like dict.update() but subtracts counts instead of replacing them.
        Counts can be reduced below zero.  Both the inputs and outputs are
        allowed to contain zero and negative counts.

        >>> c.subtract('witch')             # subtract elements from another iterable
        >>> c.subtract(Counter('watch'))    # subtract elements from another counter
        >>> c['h']                          # 2 in which, minus 1 in witch, minus 1 in watch
        0
        >>> c['w']                          # 1 in which, minus 1 in witch, minus 1 in watch
        -1

        '''

'Like dict.__delitem__() but does not raise KeyError for missing values.'

            # dict() preserves the ordering returned by most_common()
            
            # handle case where values are not orderable
            
    # Multiset-style mathematical operations discussed in:
    #       Knuth TAOCP Volume II section 4.6.3 exercise 19
    #       and at http://en.wikipedia.org/wiki/Multiset
    #
    # Outputs guaranteed to only include positive counts.
    #
    # To strip negative and zero counts, add-in an empty counter:
    #       c += Counter()
    #
    # Results are ordered according to when an element is first
    # encountered in the left operand and then by the order
    # encountered in the right operand.
    #
    # When the multiplicities are all zero or one, multiset operations
    # are guaranteed to be equivalent to the corresponding operations
    # for regular sets.
    #     Given counter multisets such as:
    #         cp = Counter(a=1, b=0, c=1)
    #         cq = Counter(c=1, d=0, e=1)
    #     The corresponding regular sets would be:
    #         sp = {'a', 'c'}
    #         sq = {'c', 'e'}
    #     All of the following relations would hold:
    #         set(cp + cq) == sp | sq
    #         set(cp - cq) == sp - sq
    #         set(cp | cq) == sp | sq
    #         set(cp & cq) == sp & sq
    #         (cp == cq) == (sp == sq)
    #         (cp != cq) == (sp != sq)
    #         (cp <= cq) == (sp <= sq)
    #         (cp < cq) == (sp < sq)
    #         (cp >= cq) == (sp >= sq)
    #         (cp > cq) == (sp > sq)

'True if any counts disagree. Missing counts are treated as zero.'

'True if all counts in self are a proper subset of those in other.'

'True if all counts in self are a proper superset of those in other.'

'''Add counts from two counters.

        >>> Counter('abbb') + Counter('bcc')
        Counter({'b': 4, 'c': 2, 'a': 1})

        '''

''' Subtract count, but keep only results with positive counts.

        >>> Counter('abbbc') - Counter('bccd')
        Counter({'b': 2, 'a': 1})

        '''

'''Union is the maximum of value in either of the input counters.

        >>> Counter('abbb') | Counter('bcc')
        Counter({'b': 3, 'c': 2, 'a': 1})

        '''

''' Intersection is the minimum of corresponding counts.

        >>> Counter('abbb') & Counter('bcc')
        Counter({'b': 1})

        '''

'Adds an empty counter, effectively stripping negative and zero counts'

'''Subtracts from an empty counter.  Strips positive and zero counts,
        and flips the sign on negative counts.

        '''

'''Internal method to strip elements with a negative or zero count'''

'''Inplace add from another counter, keeping only positive counts.

        >>> c = Counter('abbb')
        >>> c += Counter('bcc')
        >>> c

        '''

'''Inplace subtract counter, but keep only results with positive counts.

        >>> c = Counter('abbbc')
        >>> c -= Counter('bccd')
        >>> c

        '''

'''Inplace union is the maximum of value from either counter.

        >>> c |= Counter('bcc')
        >>> c

        '''

'''Inplace intersection is the minimum of corresponding counts.

        >>> c &= Counter('bcc')
        >>> c

        '''

###  ChainMap

''' A ChainMap groups multiple dicts (or other mappings) together
    to create a single, updateable view.

    The underlying mappings are stored in a list.  That list is public and can
    be accessed or updated using the *maps* attribute.  There is no other
    state.

    Lookups search the underlying mappings successively until a key is found.
    In contrast, writes, updates, and deletions only operate on the first
    mapping.

    '''

'''Initialize a ChainMap by setting *maps* to the given mappings.
        If no mappings are provided, a single empty dictionary is used.

        '''

'Create a ChainMap with a single dict created from the iterable.'

'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'

'''New ChainMap with a new map followed by all previous maps.
        If no map is provided, an empty dict is used.
        Keyword arguments update the map or new empty dict.
        '''

'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'

'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'

### UserDict

    # Modify __contains__ to work correctly when __missing__ is present
    
    # Now, add the methods in dicts but not in MutableMapping
    
        # Create a copy and avoid triggering descriptors
        
### UserList

"""A more or less complete user-defined wrapper around list objects."""

            # XXX should this accept an arbitrary sequence?
            
### UserString

    # the following methods are defined in alphabetical order:
    
        "Create the ordered dict object and set up the underlying structures."

        '''Initialize an ordered dictionary.  The signature is the same as

                    dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):

        '''Remove and return a (key, value) pair from the dictionary.

        '''Move an existing element to the end (or beginning if last is false).

        n = len(self) + 1                       # number of links including root

        size = sizeof(self.__dict__)            # instance dictionary

        size += sizeof(self.__map) * 2          # internal dict and inherited dict

        size += sizeof(self.__root) * n         # proxy objects

        "D.keys() -> a set-like object providing a view on D's keys"

        "D.items() -> a set-like object providing a view on D's items"

        "D.values() -> an object providing a view on D's values"

        '''od.pop(k[,d]) -> v, remove specified key and return the corresponding

        '''Insert key with a value of default if key is not in the dictionary.

        return '%s(%r)' % (self.__class__.__name__, list(self.items()))

        return self.__class__, (), state, None, iter(self.items())

        '''Create a new ordered dictionary with keys from iterable and values set to value.

        '''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive

            return dict.__eq__(self, other) and all(map(_eq, self, other))

    _tuplegetter = lambda index, doc: property(_itemgetter(index), doc=doc)

def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None):

            raise TypeError('Type names and field names must be strings')

            raise ValueError('Type names and field names must be valid '

            raise ValueError('Type names and field names cannot be a '

            raise ValueError('Field names cannot start with an underscore: '

            raise ValueError(f'Encountered duplicate field name: {name!r}')

            raise TypeError('Got more default values than field names')

        field_defaults = dict(reversed(list(zip(reversed(field_names),

                                                reversed(defaults)))))

    repr_fmt = '(' + ', '.join(f'{name}=%r' for name in field_names) + ')'

    _dict, _tuple, _len, _map, _zip = dict, tuple, len, map, zip

    code = f'lambda _cls, {arg_list}: _tuple_new(_cls, ({arg_list}))'

    __new__.__doc__ = f'Create new instance of {typename}({arg_list})'

            raise TypeError(f'Expected {num_fields} arguments, got {len(result)}')

    _make.__func__.__doc__ = (f'Make a new {typename} object from a sequence '

            raise ValueError(f'Got unexpected field names: {list(kwds)!r}')

    _replace.__doc__ = (f'Return a new {typename} object replacing specified '

        'Return a new dict which maps field names to their values.'

        'Return self as a plain tuple.  Used by copy and pickle.'

            module = _sys._getframe(1).f_globals.get('__name__', '__main__')

try:                                    # Load C helper function if available

    '''Dict subclass for counting hashable items.  Sometimes called a bag

        '''Create a new, empty Counter object.  And if given, count elements

        '''List the n most common elements and their counts from the most

            return sorted(self.items(), key=_itemgetter(1), reverse=True)

        return heapq.nlargest(n, self.items(), key=_itemgetter(1))

        '''Iterator over elements repeating each as many times as its count.

        return _chain.from_iterable(_starmap(_repeat, self.items()))

            'Counter.fromkeys() is undefined.  Use Counter(iterable) instead.')

        '''Like dict.update() but add counts instead of replacing them.

        '''Like dict.update() but subtracts counts instead of replacing them.

        'Like dict.__delitem__() but does not raise KeyError for missing values.'

        'True if all counts agree. Missing counts are treated as zero.'

        return all(self[e] == other[e] for c in (self, other) for e in c)

        'True if any counts disagree. Missing counts are treated as zero.'

        'True if all counts in self are a subset of those in other.'

        return all(self[e] <= other[e] for c in (self, other) for e in c)

        'True if all counts in self are a proper subset of those in other.'

        'True if all counts in self are a superset of those in other.'

        return all(self[e] >= other[e] for c in (self, other) for e in c)

        'True if all counts in self are a proper superset of those in other.'

        ''' Subtract count, but keep only results with positive counts.

        '''Union is the maximum of value in either of the input counters.

            newcount = other_count if count < other_count else count

        ''' Intersection is the minimum of corresponding counts.

            newcount = count if count < other_count else other_count

        'Adds an empty counter, effectively stripping negative and zero counts'

        '''Subtracts from an empty counter.  Strips positive and zero counts,

        '''Internal method to strip elements with a negative or zero count'''

        nonpositive = [elem for elem, count in self.items() if not count > 0]

        '''Inplace add from another counter, keeping only positive counts.

        '''Inplace subtract counter, but keep only results with positive counts.

        '''Inplace union is the maximum of value from either counter.

        '''Inplace intersection is the minimum of corresponding counts.

    ''' A ChainMap groups multiple dicts (or other mappings) together

        '''Initialize a ChainMap by setting *maps* to the given mappings.

        self.maps = list(maps) or [{}]          # always at least one map

                return mapping[key]             # can't use 'key in mapping' with defaultdict

        return self.__missing__(key)            # support subclasses that define __missing__

        return len(set().union(*self.maps))     # reuses stored hash values if possible

            d.update(dict.fromkeys(mapping))    # reuses stored hash values if possible

        return f'{self.__class__.__name__}({", ".join(map(repr, self.maps))})'

        'Create a ChainMap with a single dict created from the iterable.'

        'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'

        return self.__class__(self.maps[0].copy(), *self.maps[1:])

    def new_child(self, m=None, **kwargs):      # like Django's Context.push()

        '''New ChainMap with a new map followed by all previous maps.

    def parents(self):                          # like Django's Context.pop()

            raise KeyError(f'Key not found in the first mapping: {key!r}')

        'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'

            raise KeyError('No keys found in the first mapping.')

        'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'

    """A more or less complete user-defined wrapper around list objects."""

        return other.data if isinstance(other, UserList) else other

        return self.__class__(self.data.replace(old, new, maxsplit))