<s> '''<STR_LIT>''' <EOL> import collections <EOL> import numbers <EOL> import types <EOL> import itertools <EOL> import random <EOL> from combi . _python_toolbox import math_tools <EOL> from combi . _python_toolbox import caching <EOL> from combi . _python_toolbox import misc_tools <EOL> infinity = float ( '<STR_LIT>' ) <EOL> class UnorderedIterableException ( Exception ) : <EOL> '''<STR_LIT>''' <EOL> def are_equal_regardless_of_order ( seq1 , seq2 ) : <EOL> '''<STR_LIT>''' <EOL> from combi . _python_toolbox import nifty_collections <EOL> return nifty_collections . Bag ( seq1 ) == nifty_collections . Bag ( seq2 ) <EOL> def flatten ( iterable ) : <EOL> '''<STR_LIT>''' <EOL> iterator = iter ( iterable ) <EOL> try : <EOL> return sum ( iterator , next ( iterator ) ) <EOL> except StopIteration : <EOL> return [ ] <EOL> class NO_FILL_VALUE ( misc_tools . NonInstantiable ) : <EOL> '''<STR_LIT>''' <EOL> @ misc_tools . limit_positional_arguments ( <NUM_LIT:2> ) <EOL> def partitions ( sequence , partition_size = None , n_partitions = None , <EOL> allow_remainder = True , larger_on_remainder = False , <EOL> fill_value = NO_FILL_VALUE ) : <EOL> '''<STR_LIT>''' <EOL> sequence = ensure_iterable_is_sequence ( sequence ) <EOL> sequence_length = len ( sequence ) <EOL> if ( partition_size is None ) + ( n_partitions is None ) != <NUM_LIT:1> : <EOL> raise Exception ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> remainder_length = sequence_length % ( partition_size if partition_size <EOL> is not None else n_partitions ) <EOL> if not allow_remainder and remainder_length > <NUM_LIT:0> : <EOL> raise Exception ( "<STR_LIT>" <EOL> "<STR_LIT>" % remainder_length ) <EOL> if partition_size is None : <EOL> floored_partition_size , modulo = divmod ( sequence_length , <EOL> n_partitions ) <EOL> if modulo : <EOL> if larger_on_remainder : <EOL> partition_size = floored_partition_size <EOL> n_partitions += <NUM_LIT:1> <EOL> else : <EOL> partition_size = floored_partition_size + <NUM_LIT:1> <EOL> else : <EOL> partition_size = floored_partition_size <EOL> if n_partitions is None : <EOL> n_partitions = math_tools . ceil_div ( sequence_length , partition_size ) <EOL> naive_length = partition_size * n_partitions <EOL> blocks = [ sequence [ i : i + partition_size ] for i in <EOL> range ( <NUM_LIT:0> , naive_length , partition_size ) ] <EOL> if naive_length != sequence_length : <EOL> assert blocks <EOL> if larger_on_remainder : <EOL> if len ( blocks ) >= <NUM_LIT:2> : <EOL> small_block_to_append_back = blocks [ - <NUM_LIT:1> ] <EOL> del blocks [ - <NUM_LIT:1> ] <EOL> blocks [ - <NUM_LIT:1> ] += small_block_to_append_back <EOL> elif fill_value != NO_FILL_VALUE : <EOL> filler = itertools . repeat ( fill_value , <EOL> naive_length - sequence_length ) <EOL> blocks [ - <NUM_LIT:1> ] . extend ( filler ) <EOL> return blocks <EOL> def is_immutable_sequence ( thing ) : <EOL> '''<STR_LIT>''' <EOL> return isinstance ( thing , collections . Sequence ) and not isinstance ( thing , collections . MutableSequence ) <EOL> def to_tuple ( single_or_sequence , item_type = None , item_test = None ) : <EOL> '''<STR_LIT>''' <EOL> if ( item_type is not None ) and ( item_test is not None ) : <EOL> raise Exception ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> if item_test is not None : <EOL> actual_item_test = item_test <EOL> elif item_type is not None : <EOL> actual_item_test = lambda candidate : isinstance ( candidate , item_type ) <EOL> else : <EOL> actual_item_test = None <EOL> if actual_item_test is None : <EOL> if isinstance ( single_or_sequence , collections . Sequence ) : <EOL> return tuple ( single_or_sequence ) <EOL> elif single_or_sequence is None : <EOL> return tuple ( ) <EOL> else : <EOL> return ( single_or_sequence , ) <EOL> else : <EOL> if actual_item_test ( single_or_sequence ) : <EOL> return ( single_or_sequence , ) <EOL> elif single_or_sequence is None : <EOL> return ( ) <EOL> else : <EOL> return tuple ( single_or_sequence ) <EOL> def pop_until ( sequence , condition = bool ) : <EOL> '''<STR_LIT>''' <EOL> from combi . _python_toolbox import cute_iter_tools <EOL> for item in cute_iter_tools . iterate_pop ( sequence ) : <EOL> if condition ( item ) : <EOL> return item <EOL> def get_recurrences ( sequence ) : <EOL> '''<STR_LIT>''' <EOL> from combi . _python_toolbox import nifty_collections <EOL> return dict ( <EOL> ( item , n_recurrences ) for item , n_recurrences in <EOL> nifty_collections . Bag ( sequence ) . most_common ( ) if n_recurrences >= <NUM_LIT:2> <EOL> ) <EOL> def ensure_iterable_is_immutable_sequence ( iterable , default_type = tuple , <EOL> unallowed_types = ( ) , <EOL> allow_unordered = True ) : <EOL> '''<STR_LIT>''' <EOL> from combi . _python_toolbox import nifty_collections <EOL> assert isinstance ( iterable , collections . Iterable ) <EOL> if not allow_unordered and isinstance ( iterable , nifty_collections . DefinitelyUnordered ) : <EOL> raise UnorderedIterableException <EOL> if isinstance ( iterable , collections . MutableSequence ) or isinstance ( iterable , unallowed_types ) or not isinstance ( iterable , collections . Sequence ) : <EOL> return default_type ( iterable ) <EOL> else : <EOL> return iterable <EOL> def ensure_iterable_is_sequence ( iterable , default_type = tuple , <EOL> unallowed_types = ( bytes , ) , <EOL> allow_unordered = True ) : <EOL> '''<STR_LIT>''' <EOL> assert isinstance ( iterable , collections . Iterable ) <EOL> if not allow_unordered and isinstance ( iterable , ( set , frozenset ) ) : <EOL> raise UnorderedIterableException <EOL> if isinstance ( iterable , collections . Sequence ) and not isinstance ( iterable , unallowed_types ) : <EOL> return iterable <EOL> else : <EOL> return default_type ( iterable ) <EOL> class CuteSequenceMixin ( misc_tools . AlternativeLengthMixin ) : <EOL> '''<STR_LIT>''' <EOL> def take_random ( self ) : <EOL> '''<STR_LIT>''' <EOL> return self [ random . randint ( <NUM_LIT:0> , get_length ( self ) - <NUM_LIT:1> ) ] <EOL> def __contains__ ( self , item ) : <EOL> try : self . index ( item ) <EOL> except ValueError : return False <EOL> else : return True <EOL> class CuteSequence ( CuteSequenceMixin , collections . Sequence ) : <EOL> '''<STR_LIT>''' <EOL> def get_length ( sequence ) : <EOL> '''<STR_LIT>''' <EOL> return sequence . length if hasattr ( sequence , '<STR_LIT>' ) else len ( sequence ) <EOL> def divide_to_slices ( sequence , n_slices ) : <EOL> '''<STR_LIT>''' <EOL> from combi . _python_toolbox import cute_iter_tools <EOL> assert isinstance ( n_slices , numbers . Integral ) <EOL> assert n_slices >= <NUM_LIT:1> <EOL> sequence_length = get_length ( sequence ) <EOL> base_slice_length , remainder = divmod ( sequence_length , n_slices ) <EOL> indices = [ <NUM_LIT:0> ] <EOL> for i in range ( n_slices ) : <EOL> indices . append ( indices [ - <NUM_LIT:1> ] + base_slice_length + ( remainder > i ) ) <EOL> assert len ( indices ) == n_slices + <NUM_LIT:1> <EOL> assert indices [ <NUM_LIT:0> ] == <NUM_LIT:0> <EOL> assert indices [ - <NUM_LIT:1> ] == sequence_length <EOL> return [ sequence [ x : y ] for x , y in <EOL> cute_iter_tools . iterate_overlapping_subsequences ( indices ) ] </s>
