1"""Sorted List
2==============
3
4:doc:`Sorted Containers<index>` is an Apache2 licensed Python sorted
5collections library, written in pure-Python, and fast as C-extensions. The
6:doc:`introduction<introduction>` is the best way to get started.
7
8Sorted list implementations:
9
10.. currentmodule:: sortedcontainers
11
12* :class:`SortedList`
13* :class:`SortedKeyList`
14
15"""
16# pylint: disable=too-many-lines
17from __future__ import print_function
18
19import sys
20import traceback
21
22from bisect import bisect_left, bisect_right, insort
23from itertools import chain, repeat, starmap
24from math import log
25from operator import add, eq, ne, gt, ge, lt, le, iadd
26from textwrap import dedent
27
28###############################################################################
29# BEGIN Python 2/3 Shims
30###############################################################################
31
32try:
33 from collections.abc import Sequence, MutableSequence
34except ImportError:
35 from collections import Sequence, MutableSequence
36
37from functools import wraps
38from sys import hexversion
39
40if hexversion < 0x03000000:
41 from itertools import imap as map # pylint: disable=redefined-builtin
42 from itertools import izip as zip # pylint: disable=redefined-builtin
43 try:
44 from thread import get_ident
45 except ImportError:
46 from dummy_thread import get_ident
47else:
48 from functools import reduce
49 try:
50 from _thread import get_ident
51 except ImportError:
52 from _dummy_thread import get_ident
53
54
55def recursive_repr(fillvalue='...'):
56 "Decorator to make a repr function return fillvalue for a recursive call."
57 # pylint: disable=missing-docstring
58 # Copied from reprlib in Python 3
59 # https://hg.python.org/cpython/file/3.6/Lib/reprlib.py
60
61 def decorating_function(user_function):
62 repr_running = set()
63
64 @wraps(user_function)
65 def wrapper(self):
66 key = id(self), get_ident()
67 if key in repr_running:
68 return fillvalue
69 repr_running.add(key)
70 try:
71 result = user_function(self)
72 finally:
73 repr_running.discard(key)
74 return result
75
76 return wrapper
77
78 return decorating_function
79
80###############################################################################
81# END Python 2/3 Shims
82###############################################################################
83
84
85class SortedList(MutableSequence):
86 """Sorted list is a sorted mutable sequence.
87
88 Sorted list values are maintained in sorted order.
89
90 Sorted list values must be comparable. The total ordering of values must
91 not change while they are stored in the sorted list.
92
93 Methods for adding values:
94
95 * :func:`SortedList.add`
96 * :func:`SortedList.update`
97 * :func:`SortedList.__add__`
98 * :func:`SortedList.__iadd__`
99 * :func:`SortedList.__mul__`
100 * :func:`SortedList.__imul__`
101
102 Methods for removing values:
103
104 * :func:`SortedList.clear`
105 * :func:`SortedList.discard`
106 * :func:`SortedList.remove`
107 * :func:`SortedList.pop`
108 * :func:`SortedList.__delitem__`
109
110 Methods for looking up values:
111
112 * :func:`SortedList.bisect_left`
113 * :func:`SortedList.bisect_right`
114 * :func:`SortedList.count`
115 * :func:`SortedList.index`
116 * :func:`SortedList.__contains__`
117 * :func:`SortedList.__getitem__`
118
119 Methods for iterating values:
120
121 * :func:`SortedList.irange`
122 * :func:`SortedList.islice`
123 * :func:`SortedList.__iter__`
124 * :func:`SortedList.__reversed__`
125
126 Methods for miscellany:
127
128 * :func:`SortedList.copy`
129 * :func:`SortedList.__len__`
130 * :func:`SortedList.__repr__`
131 * :func:`SortedList._check`
132 * :func:`SortedList._reset`
133
134 Sorted lists use lexicographical ordering semantics when compared to other
135 sequences.
136
137 Some methods of mutable sequences are not supported and will raise
138 not-implemented error.
139
140 """
141 DEFAULT_LOAD_FACTOR = 1000
142
143
144 def __init__(self, iterable=None, key=None):
145 """Initialize sorted list instance.
146
147 Optional `iterable` argument provides an initial iterable of values to
148 initialize the sorted list.
149
150 Runtime complexity: `O(n*log(n))`
151
152 >>> sl = SortedList()
153 >>> sl
154 SortedList([])
155 >>> sl = SortedList([3, 1, 2, 5, 4])
156 >>> sl
157 SortedList([1, 2, 3, 4, 5])
158
159 :param iterable: initial values (optional)
160
161 """
162 assert key is None
163 self._len = 0
164 self._load = self.DEFAULT_LOAD_FACTOR
165 self._lists = []
166 self._maxes = []
167 self._index = []
168 self._offset = 0
169
170 if iterable is not None:
171 self._update(iterable)
172
173
174 def __new__(cls, iterable=None, key=None):
175 """Create new sorted list or sorted-key list instance.
176
177 Optional `key`-function argument will return an instance of subtype
178 :class:`SortedKeyList`.
179
180 >>> sl = SortedList()
181 >>> isinstance(sl, SortedList)
182 True
183 >>> sl = SortedList(key=lambda x: -x)
184 >>> isinstance(sl, SortedList)
185 True
186 >>> isinstance(sl, SortedKeyList)
187 True
188
189 :param iterable: initial values (optional)
190 :param key: function used to extract comparison key (optional)
191 :return: sorted list or sorted-key list instance
192
193 """
194 # pylint: disable=unused-argument
195 if key is None:
196 return object.__new__(cls)
197 else:
198 if cls is SortedList:
199 return object.__new__(SortedKeyList)
200 else:
201 raise TypeError('inherit SortedKeyList for key argument')
202
203
204 @property
205 def key(self): # pylint: disable=useless-return
206 """Function used to extract comparison key from values.
207
208 Sorted list compares values directly so the key function is none.
209
210 """
211 return None
212
213
214 def _reset(self, load):
215 """Reset sorted list load factor.
216
217 The `load` specifies the load-factor of the list. The default load
218 factor of 1000 works well for lists from tens to tens-of-millions of
219 values. Good practice is to use a value that is the cube root of the
220 list size. With billions of elements, the best load factor depends on
221 your usage. It's best to leave the load factor at the default until you
222 start benchmarking.
223
224 See :doc:`implementation` and :doc:`performance-scale` for more
225 information.
226
227 Runtime complexity: `O(n)`
228
229 :param int load: load-factor for sorted list sublists
230
231 """
232 values = reduce(iadd, self._lists, [])
233 self._clear()
234 self._load = load
235 self._update(values)
236
237
238 def clear(self):
239 """Remove all values from sorted list.
240
241 Runtime complexity: `O(n)`
242
243 """
244 self._len = 0
245 del self._lists[:]
246 del self._maxes[:]
247 del self._index[:]
248 self._offset = 0
249
250 _clear = clear
251
252
253 def add(self, value):
254 """Add `value` to sorted list.
255
256 Runtime complexity: `O(log(n))` -- approximate.
257
258 >>> sl = SortedList()
259 >>> sl.add(3)
260 >>> sl.add(1)
261 >>> sl.add(2)
262 >>> sl
263 SortedList([1, 2, 3])
264
265 :param value: value to add to sorted list
266
267 """
268 _lists = self._lists
269 _maxes = self._maxes
270
271 if _maxes:
272 pos = bisect_right(_maxes, value)
273
274 if pos == len(_maxes):
275 pos -= 1
276 _lists[pos].append(value)
277 _maxes[pos] = value
278 else:
279 insort(_lists[pos], value)
280
281 self._expand(pos)
282 else:
283 _lists.append([value])
284 _maxes.append(value)
285
286 self._len += 1
287
288
289 def _expand(self, pos):
290 """Split sublists with length greater than double the load-factor.
291
292 Updates the index when the sublist length is less than double the load
293 level. This requires incrementing the nodes in a traversal from the
294 leaf node to the root. For an example traversal see
295 ``SortedList._loc``.
296
297 """
298 _load = self._load
299 _lists = self._lists
300 _index = self._index
301
302 if len(_lists[pos]) > (_load << 1):
303 _maxes = self._maxes
304
305 _lists_pos = _lists[pos]
306 half = _lists_pos[_load:]
307 del _lists_pos[_load:]
308 _maxes[pos] = _lists_pos[-1]
309
310 _lists.insert(pos + 1, half)
311 _maxes.insert(pos + 1, half[-1])
312
313 del _index[:]
314 else:
315 if _index:
316 child = self._offset + pos
317 while child:
318 _index[child] += 1
319 child = (child - 1) >> 1
320 _index[0] += 1
321
322
323 def update(self, iterable):
324 """Update sorted list by adding all values from `iterable`.
325
326 Runtime complexity: `O(k*log(n))` -- approximate.
327
328 >>> sl = SortedList()
329 >>> sl.update([3, 1, 2])
330 >>> sl
331 SortedList([1, 2, 3])
332
333 :param iterable: iterable of values to add
334
335 """
336 _lists = self._lists
337 _maxes = self._maxes
338 values = sorted(iterable)
339
340 if _maxes:
341 if len(values) * 4 >= self._len:
342 _lists.append(values)
343 values = reduce(iadd, _lists, [])
344 values.sort()
345 self._clear()
346 else:
347 _add = self.add
348 for val in values:
349 _add(val)
350 return
351
352 _load = self._load
353 _lists.extend(values[pos:(pos + _load)]
354 for pos in range(0, len(values), _load))
355 _maxes.extend(sublist[-1] for sublist in _lists)
356 self._len = len(values)
357 del self._index[:]
358
359 _update = update
360
361
362 def __contains__(self, value):
363 """Return true if `value` is an element of the sorted list.
364
365 ``sl.__contains__(value)`` <==> ``value in sl``
366
367 Runtime complexity: `O(log(n))`
368
369 >>> sl = SortedList([1, 2, 3, 4, 5])
370 >>> 3 in sl
371 True
372
373 :param value: search for value in sorted list
374 :return: true if `value` in sorted list
375
376 """
377 _maxes = self._maxes
378
379 if not _maxes:
380 return False
381
382 pos = bisect_left(_maxes, value)
383
384 if pos == len(_maxes):
385 return False
386
387 _lists = self._lists
388 idx = bisect_left(_lists[pos], value)
389
390 return _lists[pos][idx] == value
391
392
393 def discard(self, value):
394 """Remove `value` from sorted list if it is a member.
395
396 If `value` is not a member, do nothing.
397
398 Runtime complexity: `O(log(n))` -- approximate.
399
400 >>> sl = SortedList([1, 2, 3, 4, 5])
401 >>> sl.discard(5)
402 >>> sl.discard(0)
403 >>> sl == [1, 2, 3, 4]
404 True
405
406 :param value: `value` to discard from sorted list
407
408 """
409 _maxes = self._maxes
410
411 if not _maxes:
412 return
413
414 pos = bisect_left(_maxes, value)
415
416 if pos == len(_maxes):
417 return
418
419 _lists = self._lists
420 idx = bisect_left(_lists[pos], value)
421
422 if _lists[pos][idx] == value:
423 self._delete(pos, idx)
424
425
426 def remove(self, value):
427 """Remove `value` from sorted list; `value` must be a member.
428
429 If `value` is not a member, raise ValueError.
430
431 Runtime complexity: `O(log(n))` -- approximate.
432
433 >>> sl = SortedList([1, 2, 3, 4, 5])
434 >>> sl.remove(5)
435 >>> sl == [1, 2, 3, 4]
436 True
437 >>> sl.remove(0)
438 Traceback (most recent call last):
439 ...
440 ValueError: 0 not in list
441
442 :param value: `value` to remove from sorted list
443 :raises ValueError: if `value` is not in sorted list
444
445 """
446 _maxes = self._maxes
447
448 if not _maxes:
449 raise ValueError('{0!r} not in list'.format(value))
450
451 pos = bisect_left(_maxes, value)
452
453 if pos == len(_maxes):
454 raise ValueError('{0!r} not in list'.format(value))
455
456 _lists = self._lists
457 idx = bisect_left(_lists[pos], value)
458
459 if _lists[pos][idx] == value:
460 self._delete(pos, idx)
461 else:
462 raise ValueError('{0!r} not in list'.format(value))
463
464
465 def _delete(self, pos, idx):
466 """Delete value at the given `(pos, idx)`.
467
468 Combines lists that are less than half the load level.
469
470 Updates the index when the sublist length is more than half the load
471 level. This requires decrementing the nodes in a traversal from the
472 leaf node to the root. For an example traversal see
473 ``SortedList._loc``.
474
475 :param int pos: lists index
476 :param int idx: sublist index
477
478 """
479 _lists = self._lists
480 _maxes = self._maxes
481 _index = self._index
482
483 _lists_pos = _lists[pos]
484
485 del _lists_pos[idx]
486 self._len -= 1
487
488 len_lists_pos = len(_lists_pos)
489
490 if len_lists_pos > (self._load >> 1):
491 _maxes[pos] = _lists_pos[-1]
492
493 if _index:
494 child = self._offset + pos
495 while child > 0:
496 _index[child] -= 1
497 child = (child - 1) >> 1
498 _index[0] -= 1
499 elif len(_lists) > 1:
500 if not pos:
501 pos += 1
502
503 prev = pos - 1
504 _lists[prev].extend(_lists[pos])
505 _maxes[prev] = _lists[prev][-1]
506
507 del _lists[pos]
508 del _maxes[pos]
509 del _index[:]
510
511 self._expand(prev)
512 elif len_lists_pos:
513 _maxes[pos] = _lists_pos[-1]
514 else:
515 del _lists[pos]
516 del _maxes[pos]
517 del _index[:]
518
519
520 def _loc(self, pos, idx):
521 """Convert an index pair (lists index, sublist index) into a single
522 index number that corresponds to the position of the value in the
523 sorted list.
524
525 Many queries require the index be built. Details of the index are
526 described in ``SortedList._build_index``.
527
528 Indexing requires traversing the tree from a leaf node to the root. The
529 parent of each node is easily computable at ``(pos - 1) // 2``.
530
531 Left-child nodes are always at odd indices and right-child nodes are
532 always at even indices.
533
534 When traversing up from a right-child node, increment the total by the
535 left-child node.
536
537 The final index is the sum from traversal and the index in the sublist.
538
539 For example, using the index from ``SortedList._build_index``::
540
541 _index = 14 5 9 3 2 4 5
542 _offset = 3
543
544 Tree::
545
546 14
547 5 9
548 3 2 4 5
549
550 Converting an index pair (2, 3) into a single index involves iterating
551 like so:
552
553 1. Starting at the leaf node: offset + alpha = 3 + 2 = 5. We identify
554 the node as a left-child node. At such nodes, we simply traverse to
555 the parent.
556
557 2. At node 9, position 2, we recognize the node as a right-child node
558 and accumulate the left-child in our total. Total is now 5 and we
559 traverse to the parent at position 0.
560
561 3. Iteration ends at the root.
562
563 The index is then the sum of the total and sublist index: 5 + 3 = 8.
564
565 :param int pos: lists index
566 :param int idx: sublist index
567 :return: index in sorted list
568
569 """
570 if not pos:
571 return idx
572
573 _index = self._index
574
575 if not _index:
576 self._build_index()
577
578 total = 0
579
580 # Increment pos to point in the index to len(self._lists[pos]).
581
582 pos += self._offset
583
584 # Iterate until reaching the root of the index tree at pos = 0.
585
586 while pos:
587
588 # Right-child nodes are at odd indices. At such indices
589 # account the total below the left child node.
590
591 if not pos & 1:
592 total += _index[pos - 1]
593
594 # Advance pos to the parent node.
595
596 pos = (pos - 1) >> 1
597
598 return total + idx
599
600
601 def _pos(self, idx):
602 """Convert an index into an index pair (lists index, sublist index)
603 that can be used to access the corresponding lists position.
604
605 Many queries require the index be built. Details of the index are
606 described in ``SortedList._build_index``.
607
608 Indexing requires traversing the tree to a leaf node. Each node has two
609 children which are easily computable. Given an index, pos, the
610 left-child is at ``pos * 2 + 1`` and the right-child is at ``pos * 2 +
611 2``.
612
613 When the index is less than the left-child, traversal moves to the
614 left sub-tree. Otherwise, the index is decremented by the left-child
615 and traversal moves to the right sub-tree.
616
617 At a child node, the indexing pair is computed from the relative
618 position of the child node as compared with the offset and the remaining
619 index.
620
621 For example, using the index from ``SortedList._build_index``::
622
623 _index = 14 5 9 3 2 4 5
624 _offset = 3
625
626 Tree::
627
628 14
629 5 9
630 3 2 4 5
631
632 Indexing position 8 involves iterating like so:
633
634 1. Starting at the root, position 0, 8 is compared with the left-child
635 node (5) which it is greater than. When greater the index is
636 decremented and the position is updated to the right child node.
637
638 2. At node 9 with index 3, we again compare the index to the left-child
639 node with value 4. Because the index is the less than the left-child
640 node, we simply traverse to the left.
641
642 3. At node 4 with index 3, we recognize that we are at a leaf node and
643 stop iterating.
644
645 4. To compute the sublist index, we subtract the offset from the index
646 of the leaf node: 5 - 3 = 2. To compute the index in the sublist, we
647 simply use the index remaining from iteration. In this case, 3.
648
649 The final index pair from our example is (2, 3) which corresponds to
650 index 8 in the sorted list.
651
652 :param int idx: index in sorted list
653 :return: (lists index, sublist index) pair
654
655 """
656 if idx < 0:
657 last_len = len(self._lists[-1])
658
659 if (-idx) <= last_len:
660 return len(self._lists) - 1, last_len + idx
661
662 idx += self._len
663
664 if idx < 0:
665 raise IndexError('list index out of range')
666 elif idx >= self._len:
667 raise IndexError('list index out of range')
668
669 if idx < len(self._lists[0]):
670 return 0, idx
671
672 _index = self._index
673
674 if not _index:
675 self._build_index()
676
677 pos = 0
678 child = 1
679 len_index = len(_index)
680
681 while child < len_index:
682 index_child = _index[child]
683
684 if idx < index_child:
685 pos = child
686 else:
687 idx -= index_child
688 pos = child + 1
689
690 child = (pos << 1) + 1
691
692 return (pos - self._offset, idx)
693
694
695 def _build_index(self):
696 """Build a positional index for indexing the sorted list.
697
698 Indexes are represented as binary trees in a dense array notation
699 similar to a binary heap.
700
701 For example, given a lists representation storing integers::
702
703 0: [1, 2, 3]
704 1: [4, 5]
705 2: [6, 7, 8, 9]
706 3: [10, 11, 12, 13, 14]
707
708 The first transformation maps the sub-lists by their length. The
709 first row of the index is the length of the sub-lists::
710
711 0: [3, 2, 4, 5]
712
713 Each row after that is the sum of consecutive pairs of the previous
714 row::
715
716 1: [5, 9]
717 2: [14]
718
719 Finally, the index is built by concatenating these lists together::
720
721 _index = [14, 5, 9, 3, 2, 4, 5]
722
723 An offset storing the start of the first row is also stored::
724
725 _offset = 3
726
727 When built, the index can be used for efficient indexing into the list.
728 See the comment and notes on ``SortedList._pos`` for details.
729
730 """
731 row0 = list(map(len, self._lists))
732
733 if len(row0) == 1:
734 self._index[:] = row0
735 self._offset = 0
736 return
737
738 head = iter(row0)
739 tail = iter(head)
740 row1 = list(starmap(add, zip(head, tail)))
741
742 if len(row0) & 1:
743 row1.append(row0[-1])
744
745 if len(row1) == 1:
746 self._index[:] = row1 + row0
747 self._offset = 1
748 return
749
750 size = 2 ** (int(log(len(row1) - 1, 2)) + 1)
751 row1.extend(repeat(0, size - len(row1)))
752 tree = [row0, row1]
753
754 while len(tree[-1]) > 1:
755 head = iter(tree[-1])
756 tail = iter(head)
757 row = list(starmap(add, zip(head, tail)))
758 tree.append(row)
759
760 reduce(iadd, reversed(tree), self._index)
761 self._offset = size * 2 - 1
762
763
764 def __delitem__(self, index):
765 """Remove value at `index` from sorted list.
766
767 ``sl.__delitem__(index)`` <==> ``del sl[index]``
768
769 Supports slicing.
770
771 Runtime complexity: `O(log(n))` -- approximate.
772
773 >>> sl = SortedList('abcde')
774 >>> del sl[2]
775 >>> sl
776 SortedList(['a', 'b', 'd', 'e'])
777 >>> del sl[:2]
778 >>> sl
779 SortedList(['d', 'e'])
780
781 :param index: integer or slice for indexing
782 :raises IndexError: if index out of range
783
784 """
785 if isinstance(index, slice):
786 start, stop, step = index.indices(self._len)
787
788 if step == 1 and start < stop:
789 if start == 0 and stop == self._len:
790 return self._clear()
791 elif self._len <= 8 * (stop - start):
792 values = self._getitem(slice(None, start))
793 if stop < self._len:
794 values += self._getitem(slice(stop, None))
795 self._clear()
796 return self._update(values)
797
798 indices = range(start, stop, step)
799
800 # Delete items from greatest index to least so
801 # that the indices remain valid throughout iteration.
802
803 if step > 0:
804 indices = reversed(indices)
805
806 _pos, _delete = self._pos, self._delete
807
808 for index in indices:
809 pos, idx = _pos(index)
810 _delete(pos, idx)
811 else:
812 pos, idx = self._pos(index)
813 self._delete(pos, idx)
814
815
816 def __getitem__(self, index):
817 """Lookup value at `index` in sorted list.
818
819 ``sl.__getitem__(index)`` <==> ``sl[index]``
820
821 Supports slicing.
822
823 Runtime complexity: `O(log(n))` -- approximate.
824
825 >>> sl = SortedList('abcde')
826 >>> sl[1]
827 'b'
828 >>> sl[-1]
829 'e'
830 >>> sl[2:5]
831 ['c', 'd', 'e']
832
833 :param index: integer or slice for indexing
834 :return: value or list of values
835 :raises IndexError: if index out of range
836
837 """
838 _lists = self._lists
839
840 if isinstance(index, slice):
841 start, stop, step = index.indices(self._len)
842
843 if step == 1 and start < stop:
844 # Whole slice optimization: start to stop slices the whole
845 # sorted list.
846
847 if start == 0 and stop == self._len:
848 return reduce(iadd, self._lists, [])
849
850 start_pos, start_idx = self._pos(start)
851 start_list = _lists[start_pos]
852 stop_idx = start_idx + stop - start
853
854 # Small slice optimization: start index and stop index are
855 # within the start list.
856
857 if len(start_list) >= stop_idx:
858 return start_list[start_idx:stop_idx]
859
860 if stop == self._len:
861 stop_pos = len(_lists) - 1
862 stop_idx = len(_lists[stop_pos])
863 else:
864 stop_pos, stop_idx = self._pos(stop)
865
866 prefix = _lists[start_pos][start_idx:]
867 middle = _lists[(start_pos + 1):stop_pos]
868 result = reduce(iadd, middle, prefix)
869 result += _lists[stop_pos][:stop_idx]
870
871 return result
872
873 if step == -1 and start > stop:
874 result = self._getitem(slice(stop + 1, start + 1))
875 result.reverse()
876 return result
877
878 # Return a list because a negative step could
879 # reverse the order of the items and this could
880 # be the desired behavior.
881
882 indices = range(start, stop, step)
883 return list(self._getitem(index) for index in indices)
884 else:
885 if self._len:
886 if index == 0:
887 return _lists[0][0]
888 elif index == -1:
889 return _lists[-1][-1]
890 else:
891 raise IndexError('list index out of range')
892
893 if 0 <= index < len(_lists[0]):
894 return _lists[0][index]
895
896 len_last = len(_lists[-1])
897
898 if -len_last < index < 0:
899 return _lists[-1][len_last + index]
900
901 pos, idx = self._pos(index)
902 return _lists[pos][idx]
903
904 _getitem = __getitem__
905
906
907 def __setitem__(self, index, value):
908 """Raise not-implemented error.
909
910 ``sl.__setitem__(index, value)`` <==> ``sl[index] = value``
911
912 :raises NotImplementedError: use ``del sl[index]`` and
913 ``sl.add(value)`` instead
914
915 """
916 message = 'use ``del sl[index]`` and ``sl.add(value)`` instead'
917 raise NotImplementedError(message)
918
919
920 def __iter__(self):
921 """Return an iterator over the sorted list.
922
923 ``sl.__iter__()`` <==> ``iter(sl)``
924
925 Iterating the sorted list while adding or deleting values may raise a
926 :exc:`RuntimeError` or fail to iterate over all values.
927
928 """
929 return chain.from_iterable(self._lists)
930
931
932 def __reversed__(self):
933 """Return a reverse iterator over the sorted list.
934
935 ``sl.__reversed__()`` <==> ``reversed(sl)``
936
937 Iterating the sorted list while adding or deleting values may raise a
938 :exc:`RuntimeError` or fail to iterate over all values.
939
940 """
941 return chain.from_iterable(map(reversed, reversed(self._lists)))
942
943
944 def reverse(self):
945 """Raise not-implemented error.
946
947 Sorted list maintains values in ascending sort order. Values may not be
948 reversed in-place.
949
950 Use ``reversed(sl)`` for an iterator over values in descending sort
951 order.
952
953 Implemented to override `MutableSequence.reverse` which provides an
954 erroneous default implementation.
955
956 :raises NotImplementedError: use ``reversed(sl)`` instead
957
958 """
959 raise NotImplementedError('use ``reversed(sl)`` instead')
960
961
962 def islice(self, start=None, stop=None, reverse=False):
963 """Return an iterator that slices sorted list from `start` to `stop`.
964
965 The `start` and `stop` index are treated inclusive and exclusive,
966 respectively.
967
968 Both `start` and `stop` default to `None` which is automatically
969 inclusive of the beginning and end of the sorted list.
970
971 When `reverse` is `True` the values are yielded from the iterator in
972 reverse order; `reverse` defaults to `False`.
973
974 >>> sl = SortedList('abcdefghij')
975 >>> it = sl.islice(2, 6)
976 >>> list(it)
977 ['c', 'd', 'e', 'f']
978
979 :param int start: start index (inclusive)
980 :param int stop: stop index (exclusive)
981 :param bool reverse: yield values in reverse order
982 :return: iterator
983
984 """
985 _len = self._len
986
987 if not _len:
988 return iter(())
989
990 start, stop, _ = slice(start, stop).indices(self._len)
991
992 if start >= stop:
993 return iter(())
994
995 _pos = self._pos
996
997 min_pos, min_idx = _pos(start)
998
999 if stop == _len:
1000 max_pos = len(self._lists) - 1
1001 max_idx = len(self._lists[-1])
1002 else:
1003 max_pos, max_idx = _pos(stop)
1004
1005 return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)
1006
1007
1008 def _islice(self, min_pos, min_idx, max_pos, max_idx, reverse):
1009 """Return an iterator that slices sorted list using two index pairs.
1010
1011 The index pairs are (min_pos, min_idx) and (max_pos, max_idx), the
1012 first inclusive and the latter exclusive. See `_pos` for details on how
1013 an index is converted to an index pair.
1014
1015 When `reverse` is `True`, values are yielded from the iterator in
1016 reverse order.
1017
1018 """
1019 _lists = self._lists
1020
1021 if min_pos > max_pos:
1022 return iter(())
1023
1024 if min_pos == max_pos:
1025 if reverse:
1026 indices = reversed(range(min_idx, max_idx))
1027 return map(_lists[min_pos].__getitem__, indices)
1028
1029 indices = range(min_idx, max_idx)
1030 return map(_lists[min_pos].__getitem__, indices)
1031
1032 next_pos = min_pos + 1
1033
1034 if next_pos == max_pos:
1035 if reverse:
1036 min_indices = range(min_idx, len(_lists[min_pos]))
1037 max_indices = range(max_idx)
1038 return chain(
1039 map(_lists[max_pos].__getitem__, reversed(max_indices)),
1040 map(_lists[min_pos].__getitem__, reversed(min_indices)),
1041 )
1042
1043 min_indices = range(min_idx, len(_lists[min_pos]))
1044 max_indices = range(max_idx)
1045 return chain(
1046 map(_lists[min_pos].__getitem__, min_indices),
1047 map(_lists[max_pos].__getitem__, max_indices),
1048 )
1049
1050 if reverse:
1051 min_indices = range(min_idx, len(_lists[min_pos]))
1052 sublist_indices = range(next_pos, max_pos)
1053 sublists = map(_lists.__getitem__, reversed(sublist_indices))
1054 max_indices = range(max_idx)
1055 return chain(
1056 map(_lists[max_pos].__getitem__, reversed(max_indices)),
1057 chain.from_iterable(map(reversed, sublists)),
1058 map(_lists[min_pos].__getitem__, reversed(min_indices)),
1059 )
1060
1061 min_indices = range(min_idx, len(_lists[min_pos]))
1062 sublist_indices = range(next_pos, max_pos)
1063 sublists = map(_lists.__getitem__, sublist_indices)
1064 max_indices = range(max_idx)
1065 return chain(
1066 map(_lists[min_pos].__getitem__, min_indices),
1067 chain.from_iterable(sublists),
1068 map(_lists[max_pos].__getitem__, max_indices),
1069 )
1070
1071
1072 def irange(self, minimum=None, maximum=None, inclusive=(True, True),
1073 reverse=False):
1074 """Create an iterator of values between `minimum` and `maximum`.
1075
1076 Both `minimum` and `maximum` default to `None` which is automatically
1077 inclusive of the beginning and end of the sorted list.
1078
1079 The argument `inclusive` is a pair of booleans that indicates whether
1080 the minimum and maximum ought to be included in the range,
1081 respectively. The default is ``(True, True)`` such that the range is
1082 inclusive of both minimum and maximum.
1083
1084 When `reverse` is `True` the values are yielded from the iterator in
1085 reverse order; `reverse` defaults to `False`.
1086
1087 >>> sl = SortedList('abcdefghij')
1088 >>> it = sl.irange('c', 'f')
1089 >>> list(it)
1090 ['c', 'd', 'e', 'f']
1091
1092 :param minimum: minimum value to start iterating
1093 :param maximum: maximum value to stop iterating
1094 :param inclusive: pair of booleans
1095 :param bool reverse: yield values in reverse order
1096 :return: iterator
1097
1098 """
1099 _maxes = self._maxes
1100
1101 if not _maxes:
1102 return iter(())
1103
1104 _lists = self._lists
1105
1106 # Calculate the minimum (pos, idx) pair. By default this location
1107 # will be inclusive in our calculation.
1108
1109 if minimum is None:
1110 min_pos = 0
1111 min_idx = 0
1112 else:
1113 if inclusive[0]:
1114 min_pos = bisect_left(_maxes, minimum)
1115
1116 if min_pos == len(_maxes):
1117 return iter(())
1118
1119 min_idx = bisect_left(_lists[min_pos], minimum)
1120 else:
1121 min_pos = bisect_right(_maxes, minimum)
1122
1123 if min_pos == len(_maxes):
1124 return iter(())
1125
1126 min_idx = bisect_right(_lists[min_pos], minimum)
1127
1128 # Calculate the maximum (pos, idx) pair. By default this location
1129 # will be exclusive in our calculation.
1130
1131 if maximum is None:
1132 max_pos = len(_maxes) - 1
1133 max_idx = len(_lists[max_pos])
1134 else:
1135 if inclusive[1]:
1136 max_pos = bisect_right(_maxes, maximum)
1137
1138 if max_pos == len(_maxes):
1139 max_pos -= 1
1140 max_idx = len(_lists[max_pos])
1141 else:
1142 max_idx = bisect_right(_lists[max_pos], maximum)
1143 else:
1144 max_pos = bisect_left(_maxes, maximum)
1145
1146 if max_pos == len(_maxes):
1147 max_pos -= 1
1148 max_idx = len(_lists[max_pos])
1149 else:
1150 max_idx = bisect_left(_lists[max_pos], maximum)
1151
1152 return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)
1153
1154
1155 def __len__(self):
1156 """Return the size of the sorted list.
1157
1158 ``sl.__len__()`` <==> ``len(sl)``
1159
1160 :return: size of sorted list
1161
1162 """
1163 return self._len
1164
1165
1166 def bisect_left(self, value):
1167 """Return an index to insert `value` in the sorted list.
1168
1169 If the `value` is already present, the insertion point will be before
1170 (to the left of) any existing values.
1171
1172 Similar to the `bisect` module in the standard library.
1173
1174 Runtime complexity: `O(log(n))` -- approximate.
1175
1176 >>> sl = SortedList([10, 11, 12, 13, 14])
1177 >>> sl.bisect_left(12)
1178 2
1179
1180 :param value: insertion index of value in sorted list
1181 :return: index
1182
1183 """
1184 _maxes = self._maxes
1185
1186 if not _maxes:
1187 return 0
1188
1189 pos = bisect_left(_maxes, value)
1190
1191 if pos == len(_maxes):
1192 return self._len
1193
1194 idx = bisect_left(self._lists[pos], value)
1195 return self._loc(pos, idx)
1196
1197
1198 def bisect_right(self, value):
1199 """Return an index to insert `value` in the sorted list.
1200
1201 Similar to `bisect_left`, but if `value` is already present, the
1202 insertion point will be after (to the right of) any existing values.
1203
1204 Similar to the `bisect` module in the standard library.
1205
1206 Runtime complexity: `O(log(n))` -- approximate.
1207
1208 >>> sl = SortedList([10, 11, 12, 13, 14])
1209 >>> sl.bisect_right(12)
1210 3
1211
1212 :param value: insertion index of value in sorted list
1213 :return: index
1214
1215 """
1216 _maxes = self._maxes
1217
1218 if not _maxes:
1219 return 0
1220
1221 pos = bisect_right(_maxes, value)
1222
1223 if pos == len(_maxes):
1224 return self._len
1225
1226 idx = bisect_right(self._lists[pos], value)
1227 return self._loc(pos, idx)
1228
1229 bisect = bisect_right
1230 _bisect_right = bisect_right
1231
1232
1233 def count(self, value):
1234 """Return number of occurrences of `value` in the sorted list.
1235
1236 Runtime complexity: `O(log(n))` -- approximate.
1237
1238 >>> sl = SortedList([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])
1239 >>> sl.count(3)
1240 3
1241
1242 :param value: value to count in sorted list
1243 :return: count
1244
1245 """
1246 _maxes = self._maxes
1247
1248 if not _maxes:
1249 return 0
1250
1251 pos_left = bisect_left(_maxes, value)
1252
1253 if pos_left == len(_maxes):
1254 return 0
1255
1256 _lists = self._lists
1257 idx_left = bisect_left(_lists[pos_left], value)
1258 pos_right = bisect_right(_maxes, value)
1259
1260 if pos_right == len(_maxes):
1261 return self._len - self._loc(pos_left, idx_left)
1262
1263 idx_right = bisect_right(_lists[pos_right], value)
1264
1265 if pos_left == pos_right:
1266 return idx_right - idx_left
1267
1268 right = self._loc(pos_right, idx_right)
1269 left = self._loc(pos_left, idx_left)
1270 return right - left
1271
1272
1273 def copy(self):
1274 """Return a shallow copy of the sorted list.
1275
1276 Runtime complexity: `O(n)`
1277
1278 :return: new sorted list
1279
1280 """
1281 return self.__class__(self)
1282
1283 __copy__ = copy
1284
1285
1286 def append(self, value):
1287 """Raise not-implemented error.
1288
1289 Implemented to override `MutableSequence.append` which provides an
1290 erroneous default implementation.
1291
1292 :raises NotImplementedError: use ``sl.add(value)`` instead
1293
1294 """
1295 raise NotImplementedError('use ``sl.add(value)`` instead')
1296
1297
1298 def extend(self, values):
1299 """Raise not-implemented error.
1300
1301 Implemented to override `MutableSequence.extend` which provides an
1302 erroneous default implementation.
1303
1304 :raises NotImplementedError: use ``sl.update(values)`` instead
1305
1306 """
1307 raise NotImplementedError('use ``sl.update(values)`` instead')
1308
1309
1310 def insert(self, index, value):
1311 """Raise not-implemented error.
1312
1313 :raises NotImplementedError: use ``sl.add(value)`` instead
1314
1315 """
1316 raise NotImplementedError('use ``sl.add(value)`` instead')
1317
1318
1319 def pop(self, index=-1):
1320 """Remove and return value at `index` in sorted list.
1321
1322 Raise :exc:`IndexError` if the sorted list is empty or index is out of
1323 range.
1324
1325 Negative indices are supported.
1326
1327 Runtime complexity: `O(log(n))` -- approximate.
1328
1329 >>> sl = SortedList('abcde')
1330 >>> sl.pop()
1331 'e'
1332 >>> sl.pop(2)
1333 'c'
1334 >>> sl
1335 SortedList(['a', 'b', 'd'])
1336
1337 :param int index: index of value (default -1)
1338 :return: value
1339 :raises IndexError: if index is out of range
1340
1341 """
1342 if not self._len:
1343 raise IndexError('pop index out of range')
1344
1345 _lists = self._lists
1346
1347 if index == 0:
1348 val = _lists[0][0]
1349 self._delete(0, 0)
1350 return val
1351
1352 if index == -1:
1353 pos = len(_lists) - 1
1354 loc = len(_lists[pos]) - 1
1355 val = _lists[pos][loc]
1356 self._delete(pos, loc)
1357 return val
1358
1359 if 0 <= index < len(_lists[0]):
1360 val = _lists[0][index]
1361 self._delete(0, index)
1362 return val
1363
1364 len_last = len(_lists[-1])
1365
1366 if -len_last < index < 0:
1367 pos = len(_lists) - 1
1368 loc = len_last + index
1369 val = _lists[pos][loc]
1370 self._delete(pos, loc)
1371 return val
1372
1373 pos, idx = self._pos(index)
1374 val = _lists[pos][idx]
1375 self._delete(pos, idx)
1376 return val
1377
1378
1379 def index(self, value, start=None, stop=None):
1380 """Return first index of value in sorted list.
1381
1382 Raise ValueError if `value` is not present.
1383
1384 Index must be between `start` and `stop` for the `value` to be
1385 considered present. The default value, None, for `start` and `stop`
1386 indicate the beginning and end of the sorted list.
1387
1388 Negative indices are supported.
1389
1390 Runtime complexity: `O(log(n))` -- approximate.
1391
1392 >>> sl = SortedList('abcde')
1393 >>> sl.index('d')
1394 3
1395 >>> sl.index('z')
1396 Traceback (most recent call last):
1397 ...
1398 ValueError: 'z' is not in list
1399
1400 :param value: value in sorted list
1401 :param int start: start index (default None, start of sorted list)
1402 :param int stop: stop index (default None, end of sorted list)
1403 :return: index of value
1404 :raises ValueError: if value is not present
1405
1406 """
1407 _len = self._len
1408
1409 if not _len:
1410 raise ValueError('{0!r} is not in list'.format(value))
1411
1412 if start is None:
1413 start = 0
1414 if start < 0:
1415 start += _len
1416 if start < 0:
1417 start = 0
1418
1419 if stop is None:
1420 stop = _len
1421 if stop < 0:
1422 stop += _len
1423 if stop > _len:
1424 stop = _len
1425
1426 if stop <= start:
1427 raise ValueError('{0!r} is not in list'.format(value))
1428
1429 _maxes = self._maxes
1430 pos_left = bisect_left(_maxes, value)
1431
1432 if pos_left == len(_maxes):
1433 raise ValueError('{0!r} is not in list'.format(value))
1434
1435 _lists = self._lists
1436 idx_left = bisect_left(_lists[pos_left], value)
1437
1438 if _lists[pos_left][idx_left] != value:
1439 raise ValueError('{0!r} is not in list'.format(value))
1440
1441 stop -= 1
1442 left = self._loc(pos_left, idx_left)
1443
1444 if start <= left:
1445 if left <= stop:
1446 return left
1447 else:
1448 right = self._bisect_right(value) - 1
1449
1450 if start <= right:
1451 return start
1452
1453 raise ValueError('{0!r} is not in list'.format(value))
1454
1455
1456 def __add__(self, other):
1457 """Return new sorted list containing all values in both sequences.
1458
1459 ``sl.__add__(other)`` <==> ``sl + other``
1460
1461 Values in `other` do not need to be in sorted order.
1462
1463 Runtime complexity: `O(n*log(n))`
1464
1465 >>> sl1 = SortedList('bat')
1466 >>> sl2 = SortedList('cat')
1467 >>> sl1 + sl2
1468 SortedList(['a', 'a', 'b', 'c', 't', 't'])
1469
1470 :param other: other iterable
1471 :return: new sorted list
1472
1473 """
1474 values = reduce(iadd, self._lists, [])
1475 values.extend(other)
1476 return self.__class__(values)
1477
1478 __radd__ = __add__
1479
1480
1481 def __iadd__(self, other):
1482 """Update sorted list with values from `other`.
1483
1484 ``sl.__iadd__(other)`` <==> ``sl += other``
1485
1486 Values in `other` do not need to be in sorted order.
1487
1488 Runtime complexity: `O(k*log(n))` -- approximate.
1489
1490 >>> sl = SortedList('bat')
1491 >>> sl += 'cat'
1492 >>> sl
1493 SortedList(['a', 'a', 'b', 'c', 't', 't'])
1494
1495 :param other: other iterable
1496 :return: existing sorted list
1497
1498 """
1499 self._update(other)
1500 return self
1501
1502
1503 def __mul__(self, num):
1504 """Return new sorted list with `num` shallow copies of values.
1505
1506 ``sl.__mul__(num)`` <==> ``sl * num``
1507
1508 Runtime complexity: `O(n*log(n))`
1509
1510 >>> sl = SortedList('abc')
1511 >>> sl * 3
1512 SortedList(['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'])
1513
1514 :param int num: count of shallow copies
1515 :return: new sorted list
1516
1517 """
1518 values = reduce(iadd, self._lists, []) * num
1519 return self.__class__(values)
1520
1521 __rmul__ = __mul__
1522
1523
1524 def __imul__(self, num):
1525 """Update the sorted list with `num` shallow copies of values.
1526
1527 ``sl.__imul__(num)`` <==> ``sl *= num``
1528
1529 Runtime complexity: `O(n*log(n))`
1530
1531 >>> sl = SortedList('abc')
1532 >>> sl *= 3
1533 >>> sl
1534 SortedList(['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'])
1535
1536 :param int num: count of shallow copies
1537 :return: existing sorted list
1538
1539 """
1540 values = reduce(iadd, self._lists, []) * num
1541 self._clear()
1542 self._update(values)
1543 return self
1544
1545
1546 def __make_cmp(seq_op, symbol, doc):
1547 "Make comparator method."
1548 def comparer(self, other):
1549 "Compare method for sorted list and sequence."
1550 if not isinstance(other, Sequence):
1551 return NotImplemented
1552
1553 self_len = self._len
1554 len_other = len(other)
1555
1556 if self_len != len_other:
1557 if seq_op is eq:
1558 return False
1559 if seq_op is ne:
1560 return True
1561
1562 for alpha, beta in zip(self, other):
1563 if alpha != beta:
1564 return seq_op(alpha, beta)
1565
1566 return seq_op(self_len, len_other)
1567
1568 seq_op_name = seq_op.__name__
1569 comparer.__name__ = '__{0}__'.format(seq_op_name)
1570 doc_str = """Return true if and only if sorted list is {0} `other`.
1571
1572 ``sl.__{1}__(other)`` <==> ``sl {2} other``
1573
1574 Comparisons use lexicographical order as with sequences.
1575
1576 Runtime complexity: `O(n)`
1577
1578 :param other: `other` sequence
1579 :return: true if sorted list is {0} `other`
1580
1581 """
1582 comparer.__doc__ = dedent(doc_str.format(doc, seq_op_name, symbol))
1583 return comparer
1584
1585
1586 __eq__ = __make_cmp(eq, '==', 'equal to')
1587 __ne__ = __make_cmp(ne, '!=', 'not equal to')
1588 __lt__ = __make_cmp(lt, '<', 'less than')
1589 __gt__ = __make_cmp(gt, '>', 'greater than')
1590 __le__ = __make_cmp(le, '<=', 'less than or equal to')
1591 __ge__ = __make_cmp(ge, '>=', 'greater than or equal to')
1592 __make_cmp = staticmethod(__make_cmp)
1593
1594
1595 def __reduce__(self):
1596 values = reduce(iadd, self._lists, [])
1597 return (type(self), (values,))
1598
1599
1600 @recursive_repr()
1601 def __repr__(self):
1602 """Return string representation of sorted list.
1603
1604 ``sl.__repr__()`` <==> ``repr(sl)``
1605
1606 :return: string representation
1607
1608 """
1609 return '{0}({1!r})'.format(type(self).__name__, list(self))
1610
1611
1612 def _check(self):
1613 """Check invariants of sorted list.
1614
1615 Runtime complexity: `O(n)`
1616
1617 """
1618 try:
1619 assert self._load >= 4
1620 assert len(self._maxes) == len(self._lists)
1621 assert self._len == sum(len(sublist) for sublist in self._lists)
1622
1623 # Check all sublists are sorted.
1624
1625 for sublist in self._lists:
1626 for pos in range(1, len(sublist)):
1627 assert sublist[pos - 1] <= sublist[pos]
1628
1629 # Check beginning/end of sublists are sorted.
1630
1631 for pos in range(1, len(self._lists)):
1632 assert self._lists[pos - 1][-1] <= self._lists[pos][0]
1633
1634 # Check _maxes index is the last value of each sublist.
1635
1636 for pos in range(len(self._maxes)):
1637 assert self._maxes[pos] == self._lists[pos][-1]
1638
1639 # Check sublist lengths are less than double load-factor.
1640
1641 double = self._load << 1
1642 assert all(len(sublist) <= double for sublist in self._lists)
1643
1644 # Check sublist lengths are greater than half load-factor for all
1645 # but the last sublist.
1646
1647 half = self._load >> 1
1648 for pos in range(0, len(self._lists) - 1):
1649 assert len(self._lists[pos]) >= half
1650
1651 if self._index:
1652 assert self._len == self._index[0]
1653 assert len(self._index) == self._offset + len(self._lists)
1654
1655 # Check index leaf nodes equal length of sublists.
1656
1657 for pos in range(len(self._lists)):
1658 leaf = self._index[self._offset + pos]
1659 assert leaf == len(self._lists[pos])
1660
1661 # Check index branch nodes are the sum of their children.
1662
1663 for pos in range(self._offset):
1664 child = (pos << 1) + 1
1665 if child >= len(self._index):
1666 assert self._index[pos] == 0
1667 elif child + 1 == len(self._index):
1668 assert self._index[pos] == self._index[child]
1669 else:
1670 child_sum = self._index[child] + self._index[child + 1]
1671 assert child_sum == self._index[pos]
1672 except:
1673 traceback.print_exc(file=sys.stdout)
1674 print('len', self._len)
1675 print('load', self._load)
1676 print('offset', self._offset)
1677 print('len_index', len(self._index))
1678 print('index', self._index)
1679 print('len_maxes', len(self._maxes))
1680 print('maxes', self._maxes)
1681 print('len_lists', len(self._lists))
1682 print('lists', self._lists)
1683 raise
1684
1685
1686def identity(value):
1687 "Identity function."
1688 return value
1689
1690
1691class SortedKeyList(SortedList):
1692 """Sorted-key list is a subtype of sorted list.
1693
1694 The sorted-key list maintains values in comparison order based on the
1695 result of a key function applied to every value.
1696
1697 All the same methods that are available in :class:`SortedList` are also
1698 available in :class:`SortedKeyList`.
1699
1700 Additional methods provided:
1701
1702 * :attr:`SortedKeyList.key`
1703 * :func:`SortedKeyList.bisect_key_left`
1704 * :func:`SortedKeyList.bisect_key_right`
1705 * :func:`SortedKeyList.irange_key`
1706
1707 Some examples below use:
1708
1709 >>> from operator import neg
1710 >>> neg
1711 <built-in function neg>
1712 >>> neg(1)
1713 -1
1714
1715 """
1716 def __init__(self, iterable=None, key=identity):
1717 """Initialize sorted-key list instance.
1718
1719 Optional `iterable` argument provides an initial iterable of values to
1720 initialize the sorted-key list.
1721
1722 Optional `key` argument defines a callable that, like the `key`
1723 argument to Python's `sorted` function, extracts a comparison key from
1724 each value. The default is the identity function.
1725
1726 Runtime complexity: `O(n*log(n))`
1727
1728 >>> from operator import neg
1729 >>> skl = SortedKeyList(key=neg)
1730 >>> skl
1731 SortedKeyList([], key=<built-in function neg>)
1732 >>> skl = SortedKeyList([3, 1, 2], key=neg)
1733 >>> skl
1734 SortedKeyList([3, 2, 1], key=<built-in function neg>)
1735
1736 :param iterable: initial values (optional)
1737 :param key: function used to extract comparison key (optional)
1738
1739 """
1740 self._key = key
1741 self._len = 0
1742 self._load = self.DEFAULT_LOAD_FACTOR
1743 self._lists = []
1744 self._keys = []
1745 self._maxes = []
1746 self._index = []
1747 self._offset = 0
1748
1749 if iterable is not None:
1750 self._update(iterable)
1751
1752
1753 def __new__(cls, iterable=None, key=identity):
1754 return object.__new__(cls)
1755
1756
1757 @property
1758 def key(self):
1759 "Function used to extract comparison key from values."
1760 return self._key
1761
1762
1763 def clear(self):
1764 """Remove all values from sorted-key list.
1765
1766 Runtime complexity: `O(n)`
1767
1768 """
1769 self._len = 0
1770 del self._lists[:]
1771 del self._keys[:]
1772 del self._maxes[:]
1773 del self._index[:]
1774
1775 _clear = clear
1776
1777
1778 def add(self, value):
1779 """Add `value` to sorted-key list.
1780
1781 Runtime complexity: `O(log(n))` -- approximate.
1782
1783 >>> from operator import neg
1784 >>> skl = SortedKeyList(key=neg)
1785 >>> skl.add(3)
1786 >>> skl.add(1)
1787 >>> skl.add(2)
1788 >>> skl
1789 SortedKeyList([3, 2, 1], key=<built-in function neg>)
1790
1791 :param value: value to add to sorted-key list
1792
1793 """
1794 _lists = self._lists
1795 _keys = self._keys
1796 _maxes = self._maxes
1797
1798 key = self._key(value)
1799
1800 if _maxes:
1801 pos = bisect_right(_maxes, key)
1802
1803 if pos == len(_maxes):
1804 pos -= 1
1805 _lists[pos].append(value)
1806 _keys[pos].append(key)
1807 _maxes[pos] = key
1808 else:
1809 idx = bisect_right(_keys[pos], key)
1810 _lists[pos].insert(idx, value)
1811 _keys[pos].insert(idx, key)
1812
1813 self._expand(pos)
1814 else:
1815 _lists.append([value])
1816 _keys.append([key])
1817 _maxes.append(key)
1818
1819 self._len += 1
1820
1821
1822 def _expand(self, pos):
1823 """Split sublists with length greater than double the load-factor.
1824
1825 Updates the index when the sublist length is less than double the load
1826 level. This requires incrementing the nodes in a traversal from the
1827 leaf node to the root. For an example traversal see
1828 ``SortedList._loc``.
1829
1830 """
1831 _lists = self._lists
1832 _keys = self._keys
1833 _index = self._index
1834
1835 if len(_keys[pos]) > (self._load << 1):
1836 _maxes = self._maxes
1837 _load = self._load
1838
1839 _lists_pos = _lists[pos]
1840 _keys_pos = _keys[pos]
1841 half = _lists_pos[_load:]
1842 half_keys = _keys_pos[_load:]
1843 del _lists_pos[_load:]
1844 del _keys_pos[_load:]
1845 _maxes[pos] = _keys_pos[-1]
1846
1847 _lists.insert(pos + 1, half)
1848 _keys.insert(pos + 1, half_keys)
1849 _maxes.insert(pos + 1, half_keys[-1])
1850
1851 del _index[:]
1852 else:
1853 if _index:
1854 child = self._offset + pos
1855 while child:
1856 _index[child] += 1
1857 child = (child - 1) >> 1
1858 _index[0] += 1
1859
1860
1861 def update(self, iterable):
1862 """Update sorted-key list by adding all values from `iterable`.
1863
1864 Runtime complexity: `O(k*log(n))` -- approximate.
1865
1866 >>> from operator import neg
1867 >>> skl = SortedKeyList(key=neg)
1868 >>> skl.update([3, 1, 2])
1869 >>> skl
1870 SortedKeyList([3, 2, 1], key=<built-in function neg>)
1871
1872 :param iterable: iterable of values to add
1873
1874 """
1875 _lists = self._lists
1876 _keys = self._keys
1877 _maxes = self._maxes
1878 values = sorted(iterable, key=self._key)
1879
1880 if _maxes:
1881 if len(values) * 4 >= self._len:
1882 _lists.append(values)
1883 values = reduce(iadd, _lists, [])
1884 values.sort(key=self._key)
1885 self._clear()
1886 else:
1887 _add = self.add
1888 for val in values:
1889 _add(val)
1890 return
1891
1892 _load = self._load
1893 _lists.extend(values[pos:(pos + _load)]
1894 for pos in range(0, len(values), _load))
1895 _keys.extend(list(map(self._key, _list)) for _list in _lists)
1896 _maxes.extend(sublist[-1] for sublist in _keys)
1897 self._len = len(values)
1898 del self._index[:]
1899
1900 _update = update
1901
1902
1903 def __contains__(self, value):
1904 """Return true if `value` is an element of the sorted-key list.
1905
1906 ``skl.__contains__(value)`` <==> ``value in skl``
1907
1908 Runtime complexity: `O(log(n))`
1909
1910 >>> from operator import neg
1911 >>> skl = SortedKeyList([1, 2, 3, 4, 5], key=neg)
1912 >>> 3 in skl
1913 True
1914
1915 :param value: search for value in sorted-key list
1916 :return: true if `value` in sorted-key list
1917
1918 """
1919 _maxes = self._maxes
1920
1921 if not _maxes:
1922 return False
1923
1924 key = self._key(value)
1925 pos = bisect_left(_maxes, key)
1926
1927 if pos == len(_maxes):
1928 return False
1929
1930 _lists = self._lists
1931 _keys = self._keys
1932
1933 idx = bisect_left(_keys[pos], key)
1934
1935 len_keys = len(_keys)
1936 len_sublist = len(_keys[pos])
1937
1938 while True:
1939 if _keys[pos][idx] != key:
1940 return False
1941 if _lists[pos][idx] == value:
1942 return True
1943 idx += 1
1944 if idx == len_sublist:
1945 pos += 1
1946 if pos == len_keys:
1947 return False
1948 len_sublist = len(_keys[pos])
1949 idx = 0
1950
1951
1952 def discard(self, value):
1953 """Remove `value` from sorted-key list if it is a member.
1954
1955 If `value` is not a member, do nothing.
1956
1957 Runtime complexity: `O(log(n))` -- approximate.
1958
1959 >>> from operator import neg
1960 >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
1961 >>> skl.discard(1)
1962 >>> skl.discard(0)
1963 >>> skl == [5, 4, 3, 2]
1964 True
1965
1966 :param value: `value` to discard from sorted-key list
1967
1968 """
1969 _maxes = self._maxes
1970
1971 if not _maxes:
1972 return
1973
1974 key = self._key(value)
1975 pos = bisect_left(_maxes, key)
1976
1977 if pos == len(_maxes):
1978 return
1979
1980 _lists = self._lists
1981 _keys = self._keys
1982 idx = bisect_left(_keys[pos], key)
1983 len_keys = len(_keys)
1984 len_sublist = len(_keys[pos])
1985
1986 while True:
1987 if _keys[pos][idx] != key:
1988 return
1989 if _lists[pos][idx] == value:
1990 self._delete(pos, idx)
1991 return
1992 idx += 1
1993 if idx == len_sublist:
1994 pos += 1
1995 if pos == len_keys:
1996 return
1997 len_sublist = len(_keys[pos])
1998 idx = 0
1999
2000
2001 def remove(self, value):
2002 """Remove `value` from sorted-key list; `value` must be a member.
2003
2004 If `value` is not a member, raise ValueError.
2005
2006 Runtime complexity: `O(log(n))` -- approximate.
2007
2008 >>> from operator import neg
2009 >>> skl = SortedKeyList([1, 2, 3, 4, 5], key=neg)
2010 >>> skl.remove(5)
2011 >>> skl == [4, 3, 2, 1]
2012 True
2013 >>> skl.remove(0)
2014 Traceback (most recent call last):
2015 ...
2016 ValueError: 0 not in list
2017
2018 :param value: `value` to remove from sorted-key list
2019 :raises ValueError: if `value` is not in sorted-key list
2020
2021 """
2022 _maxes = self._maxes
2023
2024 if not _maxes:
2025 raise ValueError('{0!r} not in list'.format(value))
2026
2027 key = self._key(value)
2028 pos = bisect_left(_maxes, key)
2029
2030 if pos == len(_maxes):
2031 raise ValueError('{0!r} not in list'.format(value))
2032
2033 _lists = self._lists
2034 _keys = self._keys
2035 idx = bisect_left(_keys[pos], key)
2036 len_keys = len(_keys)
2037 len_sublist = len(_keys[pos])
2038
2039 while True:
2040 if _keys[pos][idx] != key:
2041 raise ValueError('{0!r} not in list'.format(value))
2042 if _lists[pos][idx] == value:
2043 self._delete(pos, idx)
2044 return
2045 idx += 1
2046 if idx == len_sublist:
2047 pos += 1
2048 if pos == len_keys:
2049 raise ValueError('{0!r} not in list'.format(value))
2050 len_sublist = len(_keys[pos])
2051 idx = 0
2052
2053
2054 def _delete(self, pos, idx):
2055 """Delete value at the given `(pos, idx)`.
2056
2057 Combines lists that are less than half the load level.
2058
2059 Updates the index when the sublist length is more than half the load
2060 level. This requires decrementing the nodes in a traversal from the
2061 leaf node to the root. For an example traversal see
2062 ``SortedList._loc``.
2063
2064 :param int pos: lists index
2065 :param int idx: sublist index
2066
2067 """
2068 _lists = self._lists
2069 _keys = self._keys
2070 _maxes = self._maxes
2071 _index = self._index
2072 keys_pos = _keys[pos]
2073 lists_pos = _lists[pos]
2074
2075 del keys_pos[idx]
2076 del lists_pos[idx]
2077 self._len -= 1
2078
2079 len_keys_pos = len(keys_pos)
2080
2081 if len_keys_pos > (self._load >> 1):
2082 _maxes[pos] = keys_pos[-1]
2083
2084 if _index:
2085 child = self._offset + pos
2086 while child > 0:
2087 _index[child] -= 1
2088 child = (child - 1) >> 1
2089 _index[0] -= 1
2090 elif len(_keys) > 1:
2091 if not pos:
2092 pos += 1
2093
2094 prev = pos - 1
2095 _keys[prev].extend(_keys[pos])
2096 _lists[prev].extend(_lists[pos])
2097 _maxes[prev] = _keys[prev][-1]
2098
2099 del _lists[pos]
2100 del _keys[pos]
2101 del _maxes[pos]
2102 del _index[:]
2103
2104 self._expand(prev)
2105 elif len_keys_pos:
2106 _maxes[pos] = keys_pos[-1]
2107 else:
2108 del _lists[pos]
2109 del _keys[pos]
2110 del _maxes[pos]
2111 del _index[:]
2112
2113
2114 def irange(self, minimum=None, maximum=None, inclusive=(True, True),
2115 reverse=False):
2116 """Create an iterator of values between `minimum` and `maximum`.
2117
2118 Both `minimum` and `maximum` default to `None` which is automatically
2119 inclusive of the beginning and end of the sorted-key list.
2120
2121 The argument `inclusive` is a pair of booleans that indicates whether
2122 the minimum and maximum ought to be included in the range,
2123 respectively. The default is ``(True, True)`` such that the range is
2124 inclusive of both minimum and maximum.
2125
2126 When `reverse` is `True` the values are yielded from the iterator in
2127 reverse order; `reverse` defaults to `False`.
2128
2129 >>> from operator import neg
2130 >>> skl = SortedKeyList([11, 12, 13, 14, 15], key=neg)
2131 >>> it = skl.irange(14.5, 11.5)
2132 >>> list(it)
2133 [14, 13, 12]
2134
2135 :param minimum: minimum value to start iterating
2136 :param maximum: maximum value to stop iterating
2137 :param inclusive: pair of booleans
2138 :param bool reverse: yield values in reverse order
2139 :return: iterator
2140
2141 """
2142 min_key = self._key(minimum) if minimum is not None else None
2143 max_key = self._key(maximum) if maximum is not None else None
2144 return self._irange_key(
2145 min_key=min_key, max_key=max_key,
2146 inclusive=inclusive, reverse=reverse,
2147 )
2148
2149
2150 def irange_key(self, min_key=None, max_key=None, inclusive=(True, True),
2151 reverse=False):
2152 """Create an iterator of values between `min_key` and `max_key`.
2153
2154 Both `min_key` and `max_key` default to `None` which is automatically
2155 inclusive of the beginning and end of the sorted-key list.
2156
2157 The argument `inclusive` is a pair of booleans that indicates whether
2158 the minimum and maximum ought to be included in the range,
2159 respectively. The default is ``(True, True)`` such that the range is
2160 inclusive of both minimum and maximum.
2161
2162 When `reverse` is `True` the values are yielded from the iterator in
2163 reverse order; `reverse` defaults to `False`.
2164
2165 >>> from operator import neg
2166 >>> skl = SortedKeyList([11, 12, 13, 14, 15], key=neg)
2167 >>> it = skl.irange_key(-14, -12)
2168 >>> list(it)
2169 [14, 13, 12]
2170
2171 :param min_key: minimum key to start iterating
2172 :param max_key: maximum key to stop iterating
2173 :param inclusive: pair of booleans
2174 :param bool reverse: yield values in reverse order
2175 :return: iterator
2176
2177 """
2178 _maxes = self._maxes
2179
2180 if not _maxes:
2181 return iter(())
2182
2183 _keys = self._keys
2184
2185 # Calculate the minimum (pos, idx) pair. By default this location
2186 # will be inclusive in our calculation.
2187
2188 if min_key is None:
2189 min_pos = 0
2190 min_idx = 0
2191 else:
2192 if inclusive[0]:
2193 min_pos = bisect_left(_maxes, min_key)
2194
2195 if min_pos == len(_maxes):
2196 return iter(())
2197
2198 min_idx = bisect_left(_keys[min_pos], min_key)
2199 else:
2200 min_pos = bisect_right(_maxes, min_key)
2201
2202 if min_pos == len(_maxes):
2203 return iter(())
2204
2205 min_idx = bisect_right(_keys[min_pos], min_key)
2206
2207 # Calculate the maximum (pos, idx) pair. By default this location
2208 # will be exclusive in our calculation.
2209
2210 if max_key is None:
2211 max_pos = len(_maxes) - 1
2212 max_idx = len(_keys[max_pos])
2213 else:
2214 if inclusive[1]:
2215 max_pos = bisect_right(_maxes, max_key)
2216
2217 if max_pos == len(_maxes):
2218 max_pos -= 1
2219 max_idx = len(_keys[max_pos])
2220 else:
2221 max_idx = bisect_right(_keys[max_pos], max_key)
2222 else:
2223 max_pos = bisect_left(_maxes, max_key)
2224
2225 if max_pos == len(_maxes):
2226 max_pos -= 1
2227 max_idx = len(_keys[max_pos])
2228 else:
2229 max_idx = bisect_left(_keys[max_pos], max_key)
2230
2231 return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)
2232
2233 _irange_key = irange_key
2234
2235
2236 def bisect_left(self, value):
2237 """Return an index to insert `value` in the sorted-key list.
2238
2239 If the `value` is already present, the insertion point will be before
2240 (to the left of) any existing values.
2241
2242 Similar to the `bisect` module in the standard library.
2243
2244 Runtime complexity: `O(log(n))` -- approximate.
2245
2246 >>> from operator import neg
2247 >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
2248 >>> skl.bisect_left(1)
2249 4
2250
2251 :param value: insertion index of value in sorted-key list
2252 :return: index
2253
2254 """
2255 return self._bisect_key_left(self._key(value))
2256
2257
2258 def bisect_right(self, value):
2259 """Return an index to insert `value` in the sorted-key list.
2260
2261 Similar to `bisect_left`, but if `value` is already present, the
2262 insertion point will be after (to the right of) any existing values.
2263
2264 Similar to the `bisect` module in the standard library.
2265
2266 Runtime complexity: `O(log(n))` -- approximate.
2267
2268 >>> from operator import neg
2269 >>> skl = SortedList([5, 4, 3, 2, 1], key=neg)
2270 >>> skl.bisect_right(1)
2271 5
2272
2273 :param value: insertion index of value in sorted-key list
2274 :return: index
2275
2276 """
2277 return self._bisect_key_right(self._key(value))
2278
2279 bisect = bisect_right
2280
2281
2282 def bisect_key_left(self, key):
2283 """Return an index to insert `key` in the sorted-key list.
2284
2285 If the `key` is already present, the insertion point will be before (to
2286 the left of) any existing keys.
2287
2288 Similar to the `bisect` module in the standard library.
2289
2290 Runtime complexity: `O(log(n))` -- approximate.
2291
2292 >>> from operator import neg
2293 >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
2294 >>> skl.bisect_key_left(-1)
2295 4
2296
2297 :param key: insertion index of key in sorted-key list
2298 :return: index
2299
2300 """
2301 _maxes = self._maxes
2302
2303 if not _maxes:
2304 return 0
2305
2306 pos = bisect_left(_maxes, key)
2307
2308 if pos == len(_maxes):
2309 return self._len
2310
2311 idx = bisect_left(self._keys[pos], key)
2312
2313 return self._loc(pos, idx)
2314
2315 _bisect_key_left = bisect_key_left
2316
2317
2318 def bisect_key_right(self, key):
2319 """Return an index to insert `key` in the sorted-key list.
2320
2321 Similar to `bisect_key_left`, but if `key` is already present, the
2322 insertion point will be after (to the right of) any existing keys.
2323
2324 Similar to the `bisect` module in the standard library.
2325
2326 Runtime complexity: `O(log(n))` -- approximate.
2327
2328 >>> from operator import neg
2329 >>> skl = SortedList([5, 4, 3, 2, 1], key=neg)
2330 >>> skl.bisect_key_right(-1)
2331 5
2332
2333 :param key: insertion index of key in sorted-key list
2334 :return: index
2335
2336 """
2337 _maxes = self._maxes
2338
2339 if not _maxes:
2340 return 0
2341
2342 pos = bisect_right(_maxes, key)
2343
2344 if pos == len(_maxes):
2345 return self._len
2346
2347 idx = bisect_right(self._keys[pos], key)
2348
2349 return self._loc(pos, idx)
2350
2351 bisect_key = bisect_key_right
2352 _bisect_key_right = bisect_key_right
2353
2354
2355 def count(self, value):
2356 """Return number of occurrences of `value` in the sorted-key list.
2357
2358 Runtime complexity: `O(log(n))` -- approximate.
2359
2360 >>> from operator import neg
2361 >>> skl = SortedKeyList([4, 4, 4, 4, 3, 3, 3, 2, 2, 1], key=neg)
2362 >>> skl.count(2)
2363 2
2364
2365 :param value: value to count in sorted-key list
2366 :return: count
2367
2368 """
2369 _maxes = self._maxes
2370
2371 if not _maxes:
2372 return 0
2373
2374 key = self._key(value)
2375 pos = bisect_left(_maxes, key)
2376
2377 if pos == len(_maxes):
2378 return 0
2379
2380 _lists = self._lists
2381 _keys = self._keys
2382 idx = bisect_left(_keys[pos], key)
2383 total = 0
2384 len_keys = len(_keys)
2385 len_sublist = len(_keys[pos])
2386
2387 while True:
2388 if _keys[pos][idx] != key:
2389 return total
2390 if _lists[pos][idx] == value:
2391 total += 1
2392 idx += 1
2393 if idx == len_sublist:
2394 pos += 1
2395 if pos == len_keys:
2396 return total
2397 len_sublist = len(_keys[pos])
2398 idx = 0
2399
2400
2401 def copy(self):
2402 """Return a shallow copy of the sorted-key list.
2403
2404 Runtime complexity: `O(n)`
2405
2406 :return: new sorted-key list
2407
2408 """
2409 return self.__class__(self, key=self._key)
2410
2411 __copy__ = copy
2412
2413
2414 def index(self, value, start=None, stop=None):
2415 """Return first index of value in sorted-key list.
2416
2417 Raise ValueError if `value` is not present.
2418
2419 Index must be between `start` and `stop` for the `value` to be
2420 considered present. The default value, None, for `start` and `stop`
2421 indicate the beginning and end of the sorted-key list.
2422
2423 Negative indices are supported.
2424
2425 Runtime complexity: `O(log(n))` -- approximate.
2426
2427 >>> from operator import neg
2428 >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
2429 >>> skl.index(2)
2430 3
2431 >>> skl.index(0)
2432 Traceback (most recent call last):
2433 ...
2434 ValueError: 0 is not in list
2435
2436 :param value: value in sorted-key list
2437 :param int start: start index (default None, start of sorted-key list)
2438 :param int stop: stop index (default None, end of sorted-key list)
2439 :return: index of value
2440 :raises ValueError: if value is not present
2441
2442 """
2443 _len = self._len
2444
2445 if not _len:
2446 raise ValueError('{0!r} is not in list'.format(value))
2447
2448 if start is None:
2449 start = 0
2450 if start < 0:
2451 start += _len
2452 if start < 0:
2453 start = 0
2454
2455 if stop is None:
2456 stop = _len
2457 if stop < 0:
2458 stop += _len
2459 if stop > _len:
2460 stop = _len
2461
2462 if stop <= start:
2463 raise ValueError('{0!r} is not in list'.format(value))
2464
2465 _maxes = self._maxes
2466 key = self._key(value)
2467 pos = bisect_left(_maxes, key)
2468
2469 if pos == len(_maxes):
2470 raise ValueError('{0!r} is not in list'.format(value))
2471
2472 stop -= 1
2473 _lists = self._lists
2474 _keys = self._keys
2475 idx = bisect_left(_keys[pos], key)
2476 len_keys = len(_keys)
2477 len_sublist = len(_keys[pos])
2478
2479 while True:
2480 if _keys[pos][idx] != key:
2481 raise ValueError('{0!r} is not in list'.format(value))
2482 if _lists[pos][idx] == value:
2483 loc = self._loc(pos, idx)
2484 if start <= loc <= stop:
2485 return loc
2486 elif loc > stop:
2487 break
2488 idx += 1
2489 if idx == len_sublist:
2490 pos += 1
2491 if pos == len_keys:
2492 raise ValueError('{0!r} is not in list'.format(value))
2493 len_sublist = len(_keys[pos])
2494 idx = 0
2495
2496 raise ValueError('{0!r} is not in list'.format(value))
2497
2498
2499 def __add__(self, other):
2500 """Return new sorted-key list containing all values in both sequences.
2501
2502 ``skl.__add__(other)`` <==> ``skl + other``
2503
2504 Values in `other` do not need to be in sorted-key order.
2505
2506 Runtime complexity: `O(n*log(n))`
2507
2508 >>> from operator import neg
2509 >>> skl1 = SortedKeyList([5, 4, 3], key=neg)
2510 >>> skl2 = SortedKeyList([2, 1, 0], key=neg)
2511 >>> skl1 + skl2
2512 SortedKeyList([5, 4, 3, 2, 1, 0], key=<built-in function neg>)
2513
2514 :param other: other iterable
2515 :return: new sorted-key list
2516
2517 """
2518 values = reduce(iadd, self._lists, [])
2519 values.extend(other)
2520 return self.__class__(values, key=self._key)
2521
2522 __radd__ = __add__
2523
2524
2525 def __mul__(self, num):
2526 """Return new sorted-key list with `num` shallow copies of values.
2527
2528 ``skl.__mul__(num)`` <==> ``skl * num``
2529
2530 Runtime complexity: `O(n*log(n))`
2531
2532 >>> from operator import neg
2533 >>> skl = SortedKeyList([3, 2, 1], key=neg)
2534 >>> skl * 2
2535 SortedKeyList([3, 3, 2, 2, 1, 1], key=<built-in function neg>)
2536
2537 :param int num: count of shallow copies
2538 :return: new sorted-key list
2539
2540 """
2541 values = reduce(iadd, self._lists, []) * num
2542 return self.__class__(values, key=self._key)
2543
2544
2545 def __reduce__(self):
2546 values = reduce(iadd, self._lists, [])
2547 return (type(self), (values, self.key))
2548
2549
2550 @recursive_repr()
2551 def __repr__(self):
2552 """Return string representation of sorted-key list.
2553
2554 ``skl.__repr__()`` <==> ``repr(skl)``
2555
2556 :return: string representation
2557
2558 """
2559 type_name = type(self).__name__
2560 return '{0}({1!r}, key={2!r})'.format(type_name, list(self), self._key)
2561
2562
2563 def _check(self):
2564 """Check invariants of sorted-key list.
2565
2566 Runtime complexity: `O(n)`
2567
2568 """
2569 try:
2570 assert self._load >= 4
2571 assert len(self._maxes) == len(self._lists) == len(self._keys)
2572 assert self._len == sum(len(sublist) for sublist in self._lists)
2573
2574 # Check all sublists are sorted.
2575
2576 for sublist in self._keys:
2577 for pos in range(1, len(sublist)):
2578 assert sublist[pos - 1] <= sublist[pos]
2579
2580 # Check beginning/end of sublists are sorted.
2581
2582 for pos in range(1, len(self._keys)):
2583 assert self._keys[pos - 1][-1] <= self._keys[pos][0]
2584
2585 # Check _keys matches _key mapped to _lists.
2586
2587 for val_sublist, key_sublist in zip(self._lists, self._keys):
2588 assert len(val_sublist) == len(key_sublist)
2589 for val, key in zip(val_sublist, key_sublist):
2590 assert self._key(val) == key
2591
2592 # Check _maxes index is the last value of each sublist.
2593
2594 for pos in range(len(self._maxes)):
2595 assert self._maxes[pos] == self._keys[pos][-1]
2596
2597 # Check sublist lengths are less than double load-factor.
2598
2599 double = self._load << 1
2600 assert all(len(sublist) <= double for sublist in self._lists)
2601
2602 # Check sublist lengths are greater than half load-factor for all
2603 # but the last sublist.
2604
2605 half = self._load >> 1
2606 for pos in range(0, len(self._lists) - 1):
2607 assert len(self._lists[pos]) >= half
2608
2609 if self._index:
2610 assert self._len == self._index[0]
2611 assert len(self._index) == self._offset + len(self._lists)
2612
2613 # Check index leaf nodes equal length of sublists.
2614
2615 for pos in range(len(self._lists)):
2616 leaf = self._index[self._offset + pos]
2617 assert leaf == len(self._lists[pos])
2618
2619 # Check index branch nodes are the sum of their children.
2620
2621 for pos in range(self._offset):
2622 child = (pos << 1) + 1
2623 if child >= len(self._index):
2624 assert self._index[pos] == 0
2625 elif child + 1 == len(self._index):
2626 assert self._index[pos] == self._index[child]
2627 else:
2628 child_sum = self._index[child] + self._index[child + 1]
2629 assert child_sum == self._index[pos]
2630 except:
2631 traceback.print_exc(file=sys.stdout)
2632 print('len', self._len)
2633 print('load', self._load)
2634 print('offset', self._offset)
2635 print('len_index', len(self._index))
2636 print('index', self._index)
2637 print('len_maxes', len(self._maxes))
2638 print('maxes', self._maxes)
2639 print('len_keys', len(self._keys))
2640 print('keys', self._keys)
2641 print('len_lists', len(self._lists))
2642 print('lists', self._lists)
2643 raise
2644
2645
2646SortedListWithKey = SortedKeyList