@@ -193,12 +193,12 @@ def __init__(self, iterable_or_length, domain=None, *, n_elements=None,
193193
194194 self .n_elements = self .sequence_length if (n_elements is None ) \
195195 else n_elements
196- if not 0 <= self .n_elements <= self . sequence_length :
197- raise Exception (
198- '` n_elements` must be between 0 and %s, you gave %s' %
199- ( self . sequence_length , self . n_elements )
200- )
201- self .is_partial = (self .n_elements < self .sequence_length )
196+ if not isinstance ( self .n_elements , int ) :
197+ raise TypeError ( '`n_elements` must be an `int`.' )
198+ if not self . n_elements >= 0 :
199+ raise TypeError ( '`n_elements` must be positive or zero.' )
200+
201+ self .is_partial = (self .n_elements != self .sequence_length )
202202
203203 self .indices = sequence_tools .CuteRange (self .n_elements )
204204
@@ -365,6 +365,8 @@ def _unsliced_length(self):
365365 This is used as an interim step in calculating the actual length of the
366366 space with the slice taken into account.
367367 '''
368+ if self .n_elements > self .sequence_length :
369+ return 0
368370 if self .is_degreed :
369371 assert not self .is_recurrent and not self .is_partial and \
370372 not self .is_combination
@@ -503,7 +505,9 @@ def __getitem__(self, i):
503505 return self .perm_type (self .undapplied [i ], perm_space = self )
504506 elif self .is_degreed :
505507 if self .is_rapplied :
506- assert not self .is_recurrent
508+ assert not self .is_recurrent and \
509+ not self .is_partial and not self .is_combination and \
510+ not self .is_dapplied and not self .is_sliced
507511 return self .perm_type (map (self .sequence .__getitem__ ,
508512 self .unrapplied [i ]),
509513 perm_space = self )
@@ -585,62 +589,29 @@ def __getitem__(self, i):
585589 for unused_value in nifty_collections .OrderedSet ((
586590 value for value in available_values if not
587591 ((value in reserved_values and available_values .count (value )
588- == reserved_values .count (value )) or value in shit_set )
592+ == reserved_values .count (value )) or value in shit_set )
589593
590594 )):
591595 wip_perm_sequence_dict [j ] = unused_value
592-
593- ###########################################################
594- # #
595- # Tricky thing here: Trying to put as much as we can in a
596- # sequence head that'll shorten the sequence we'll give to
597- # the candidate space instead of using a fixed map, if
598- # possible. This is crucial for `CombSpace` which can't use
599- # `fixed_map`.
600- head = []
601- fixed_map_to_use = dict (wip_perm_sequence_dict )
602- n_elements_to_use = self .n_elements
603- for k in sequence_tools .CuteRange (infinity ):
604- try :
605- head .append (wip_perm_sequence_dict [k ])
606- except KeyError :
607- break
608- else :
609- del fixed_map_to_use [k ]
610- n_elements_to_use -= 1
611- sequence_to_use = list (self .sequence )
612- for item in head :
613- if self .is_combination :
614- sequence_to_use = sequence_to_use [
615- sequence_to_use .index (item ) + 1 :
616- ]
617- else :
618- sequence_to_use .remove (item )
619-
620- sequence_to_use = [x for x in sequence_to_use if x not in
621- shit_set ]
622-
623- fixed_map_to_use = {key - len (head ): value for key , value
624- in fixed_map_to_use .items ()}
625-
626- if len (sequence_to_use ) < n_elements_to_use :
627- class O : length = 0
628- candidate_sub_perm_space = O ()
596+ sequence = [item for item in self .sequence
597+ if item not in shit_set ]
598+ if any (value in shit_set for value
599+ in wip_perm_sequence_dict .values ()):
600+ candidate_sub_perm_space_length = 0
629601 else :
630- candidate_sub_perm_space = PermSpace (
631- sequence_to_use ,
632- n_elements = n_elements_to_use ,
633- fixed_map = fixed_map_to_use ,
602+ candidate_sub_perm_space_length = \
603+ PermSpace ._create_with_cut_prefix (
604+ sequence ,
605+ n_elements = self .n_elements ,
606+ fixed_map = wip_perm_sequence_dict ,
634607 is_combination = self .is_combination
635- )
636- # #
637- ###########################################################
608+ ).length
638609
639- if wip_i < candidate_sub_perm_space . length :
610+ if wip_i < candidate_sub_perm_space_length :
640611 available_values .remove (unused_value )
641612 break
642613 else :
643- wip_i -= candidate_sub_perm_space . length
614+ wip_i -= candidate_sub_perm_space_length
644615 if self .is_combination :
645616 shit_set .add (wip_perm_sequence_dict [j ])
646617 del wip_perm_sequence_dict [j ]
@@ -944,6 +915,59 @@ def _coerce_perm(self, perm):
944915 '''Coerce `perm` to be a permutation of this space.'''
945916 return Perm (perm , self )
946917
918+ prefix = None
919+
920+ @classmethod
921+ def _create_with_cut_prefix (cls , sequence , domain = None , * ,
922+ n_elements = None , fixed_map = None , degrees = None , is_combination = False ,
923+ slice_ = None ):
924+
925+ # Tricky thing here: Trying to put as much as we can in a
926+ # sequence head that'll shorten the sequence we'll give to
927+ # the candidate space instead of using a fixed map, if
928+ # possible. This is crucial for `CombSpace` which can't use
929+ # `fixed_map`.
930+
931+ if degrees is not None :
932+ raise NotImplementedError
933+
934+
935+ prefix = []
936+ fixed_map = dict (fixed_map )
937+ for i in sequence_tools .CuteRange (infinity ):
938+ try :
939+ prefix .append (fixed_map [i ])
940+ except KeyError :
941+ break
942+ else :
943+ del fixed_map [i ]
944+ n_elements -= 1
945+
946+
947+ sequence = list (sequence )
948+ for item in prefix :
949+ if is_combination :
950+ sequence = sequence [sequence .index (item ) + 1 :]
951+ else :
952+ sequence [sequence .index (item )] = misc .MISSING_ELEMENT
953+ # More efficient than removing the element, we filter these out
954+ # later.
955+ if not is_combination :
956+ sequence = [item for item in sequence
957+ if (item is not misc .MISSING_ELEMENT )]
958+
959+ fixed_map = {key - len (prefix ): value
960+ for key , value in fixed_map .items ()}
961+
962+ perm_space = cls (
963+ sequence , n_elements = n_elements , fixed_map = fixed_map ,
964+ is_combination = is_combination , slice_ = slice_ ,
965+ )
966+ perm_space .prefix = tuple (prefix )
967+ return perm_space
968+
969+
970+
947971
948972
949973
0 commit comments