restructure, slow security solution
This commit is contained in:
111
intset.py
Normal file
111
intset.py
Normal file
@@ -0,0 +1,111 @@
|
||||
class IntSet:
|
||||
def __init__(self, *bounds):
|
||||
"""Bounds must be tuples of the form (a, b),
|
||||
where integers a <= x < b are included in the set.
|
||||
"""
|
||||
|
||||
if not bounds:
|
||||
bounds = [0, 0]
|
||||
|
||||
self.bounds = list(bounds)
|
||||
|
||||
def simplify(self):
|
||||
i = 0
|
||||
while i < len(self.bounds) - 1:
|
||||
if i % 2 == 0:
|
||||
if self.bounds[i] >= self.bounds[i + 1]:
|
||||
del self.bounds[i:i + 2]
|
||||
else:
|
||||
i += 1
|
||||
else:
|
||||
if self.bounds[i] >= self.bounds[i + 1]:
|
||||
if self.bounds[i] >= self.bounds[i + 2]:
|
||||
del self.bounds[i + 1:i + 3]
|
||||
else:
|
||||
del self.bounds[i:i + 2]
|
||||
else:
|
||||
i += 1
|
||||
|
||||
def __or__(self, other):
|
||||
bounds = None
|
||||
j = k = 0
|
||||
|
||||
while j < len(self.bounds) - 1 or k < len(other.bounds) - 1:
|
||||
if k >= len(other.bounds) - 1:
|
||||
a, b = self.bounds[j:j + 2]
|
||||
j += 2
|
||||
elif j >= len(self.bounds) - 1:
|
||||
a, b = other.bounds[k:k + 2]
|
||||
k += 2
|
||||
elif self.bounds[j] < other.bounds[k]:
|
||||
a, b = self.bounds[j:j + 2]
|
||||
j += 2
|
||||
else:
|
||||
a, b = other.bounds[k:k + 2]
|
||||
k += 2
|
||||
|
||||
if a >= b:
|
||||
continue
|
||||
|
||||
if not bounds:
|
||||
bounds = [a, b]
|
||||
continue
|
||||
|
||||
e = bounds[-1]
|
||||
|
||||
if e >= a:
|
||||
if e >= b:
|
||||
continue
|
||||
bounds[-1] = b
|
||||
else:
|
||||
bounds.append(a)
|
||||
bounds.append(b)
|
||||
|
||||
if not bounds:
|
||||
bounds = [0, 0]
|
||||
|
||||
new = IntSet()
|
||||
new.bounds = bounds
|
||||
return new
|
||||
|
||||
def __and__(self, other):
|
||||
bounds = []
|
||||
|
||||
i = j = 0
|
||||
while i < len(self.bounds) - 1 and j < len(other.bounds) - 1:
|
||||
a, b = self.bounds[i:i + 2]
|
||||
c, d = other.bounds[j:j + 2]
|
||||
if b > c and a < d:
|
||||
bounds.append(max(a, c))
|
||||
bounds.append(min(b, d))
|
||||
if b < d:
|
||||
i += 2 # toss a b
|
||||
else:
|
||||
j += 2 # toss c d
|
||||
|
||||
new = IntSet()
|
||||
new.bounds = bounds
|
||||
new.simplify()
|
||||
return new
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.bounds == other.bounds
|
||||
|
||||
def __iter__(self):
|
||||
for a, b in self.pairs:
|
||||
yield from range(a, b)
|
||||
|
||||
def __len__(self):
|
||||
return sum(b - a if b > a else 0 for a, b in self.pairs)
|
||||
|
||||
def __lt__(self, other):
|
||||
return len(self) < len(other)
|
||||
|
||||
@property
|
||||
def pairs(self):
|
||||
it = iter(self.bounds)
|
||||
while True:
|
||||
yield next(it), next(it)
|
||||
|
||||
def __repr__(self):
|
||||
return 'U'.join('[{0},{1})'.format(a, b) for a, b in self.pairs)
|
||||
Reference in New Issue
Block a user