blob: 8f3f6a3fe35ffea711796e6f7c2a19f5add1342d [file] [log] [blame]
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001"""Bisection algorithms."""
2
3def insort_right(a, x, lo=0, hi=None):
4 """Insert item x in list a, and keep it sorted assuming a is sorted.
5
6 If x is already in a, insert it to the right of the rightmost x.
7
8 Optional args lo (default 0) and hi (default len(a)) bound the
9 slice of a to be searched.
10 """
11
12 lo = bisect_right(a, x, lo, hi)
13 a.insert(lo, x)
14
15def bisect_right(a, x, lo=0, hi=None):
16 """Return the index where to insert item x in list a, assuming a is sorted.
17
18 The return value i is such that all e in a[:i] have e <= x, and all e in
19 a[i:] have e > x. So if x already appears in the list, a.insert(x) will
20 insert just after the rightmost x already there.
21
22 Optional args lo (default 0) and hi (default len(a)) bound the
23 slice of a to be searched.
24 """
25
26 if lo < 0:
27 raise ValueError('lo must be non-negative')
28 if hi is None:
29 hi = len(a)
30 while lo < hi:
31 mid = (lo+hi)//2
32 # Use __lt__ to match the logic in list.sort() and in heapq
33 if x < a[mid]: hi = mid
34 else: lo = mid+1
35 return lo
36
37def insort_left(a, x, lo=0, hi=None):
38 """Insert item x in list a, and keep it sorted assuming a is sorted.
39
40 If x is already in a, insert it to the left of the leftmost x.
41
42 Optional args lo (default 0) and hi (default len(a)) bound the
43 slice of a to be searched.
44 """
45
46 lo = bisect_left(a, x, lo, hi)
47 a.insert(lo, x)
48
49
50def bisect_left(a, x, lo=0, hi=None):
51 """Return the index where to insert item x in list a, assuming a is sorted.
52
53 The return value i is such that all e in a[:i] have e < x, and all e in
54 a[i:] have e >= x. So if x already appears in the list, a.insert(x) will
55 insert just before the leftmost x already there.
56
57 Optional args lo (default 0) and hi (default len(a)) bound the
58 slice of a to be searched.
59 """
60
61 if lo < 0:
62 raise ValueError('lo must be non-negative')
63 if hi is None:
64 hi = len(a)
65 while lo < hi:
66 mid = (lo+hi)//2
67 # Use __lt__ to match the logic in list.sort() and in heapq
68 if a[mid] < x: lo = mid+1
69 else: hi = mid
70 return lo
71
72# Overwrite above definitions with a fast C implementation
73try:
74 from _bisect import *
75except ImportError:
76 pass
77
78# Create aliases
79bisect = bisect_right
80insort = insort_right