1 from abc
import ABCMeta
, abstractmethod
2 from functools
import lru_cache
3 from typing
import (AbstractSet
, Any
, Iterable
, Iterator
, Mapping
, MutableSet
,
6 from bigint_presentation_code
.type_util
import Self
, final
8 _T_co
= TypeVar("_T_co", covariant
=True)
20 "trailing_zero_count",
25 class InternedMeta(ABCMeta
):
26 def __init__(self
, *args
, **kwargs
):
27 # type: (*Any, **Any) -> None
28 super().__init
__(*args
, **kwargs
)
29 self
.__INTERN
_TABLE
= {} # type: dict[Any, Any]
31 def __intern(self
, value
):
33 value
= self
.__INTERN
_TABLE
.setdefault(value
, value
)
34 if value
.__dict
__.get("_InternedMeta__interned", False):
36 value
.__dict
__["_InternedMeta__interned"] = True
38 value
.__dict
__["__hash__"] = lambda: hash_v
43 if value
.__class
__ is __o
.__class
__:
46 value
.__dict
__["__eq__"] = __eq__
49 def __call__(self
, *args
, **kwargs
):
50 # type: (*Any, **Any) -> Any
51 return self
.__intern
(super().__call
__(*args
, **kwargs
))
54 class OFSet(AbstractSet
[_T_co
], metaclass
=InternedMeta
):
55 """ ordered frozen set """
56 __slots__
= "__items", "__dict__", "__weakref__"
58 def __init__(self
, items
=()):
59 # type: (Iterable[_T_co]) -> None
61 self
.__items
= {v
: None for v
in items
}
63 def __contains__(self
, x
):
65 return x
in self
.__items
68 # type: () -> Iterator[_T_co]
69 return iter(self
.__items
)
73 return len(self
.__items
)
83 return f
"OFSet({list(self)})"
86 class OSet(MutableSet
[_T
]):
87 """ ordered mutable set """
88 __slots__
= "__items", "__dict__"
90 def __init__(self
, items
=()):
91 # type: (Iterable[_T]) -> None
93 self
.__items
= {v
: None for v
in items
}
95 def __contains__(self
, x
):
97 return x
in self
.__items
100 # type: () -> Iterator[_T]
101 return iter(self
.__items
)
105 return len(self
.__items
)
107 def add(self
, value
):
109 self
.__items
[value
] = None
111 def discard(self
, value
):
113 self
.__items
.pop(value
, None)
119 return f
"OSet({list(self)})"
122 class FMap(Mapping
[_T
, _T_co
], metaclass
=InternedMeta
):
123 """ordered frozen hashable mapping"""
124 __slots__
= "__items", "__hash", "__dict__", "__weakref__"
127 def __init__(self
, items
):
128 # type: (Mapping[_T, _T_co]) -> None
132 def __init__(self
, items
):
133 # type: (Iterable[tuple[_T, _T_co]]) -> None
141 def __init__(self
, items
=()):
142 # type: (Mapping[_T, _T_co] | Iterable[tuple[_T, _T_co]]) -> None
144 self
.__items
= dict(items
) # type: dict[_T, _T_co]
145 self
.__hash
= None # type: None | int
147 def __getitem__(self
, item
):
148 # type: (_T) -> _T_co
149 return self
.__items
[item
]
152 # type: () -> Iterator[_T]
153 return iter(self
.__items
)
157 return len(self
.__items
)
159 def __eq__(self
, other
):
160 # type: (FMap[Any, Any] | Any) -> bool
161 if isinstance(other
, FMap
):
162 return self
.__items
== other
.__items
163 return super().__eq
__(other
)
167 if self
.__hash
is None:
168 self
.__hash
= hash(frozenset(self
.items()))
173 return f
"FMap({self.__items})"
176 def trailing_zero_count(v
, default
=-1):
177 # type: (int, int) -> int
178 without_bit
= v
& (v
- 1) # clear lowest set bit
179 bit
= v
& ~without_bit
# extract lowest set bit
180 return top_set_bit_index(bit
, default
)
183 def top_set_bit_index(v
, default
=-1):
184 # type: (int, int) -> int
187 return v
.bit_length() - 1
191 # added in cpython 3.10
192 bit_count
= int.bit_count
# type: ignore
193 except AttributeError:
196 """returns the number of 1 bits in the absolute value of the input"""
197 return bin(abs(v
)).count('1')
200 class BaseBitSet(AbstractSet
[int]):
201 __slots__
= "__bits", "__dict__", "__weakref__"
210 def _from_bits(cls
, bits
):
211 # type: (int) -> Self
212 return cls(bits
=bits
)
214 def __init__(self
, items
=(), bits
=0):
215 # type: (Iterable[int], int) -> None
217 if isinstance(items
, BaseBitSet
):
222 raise ValueError("can't store negative integers")
225 raise ValueError("can't store an infinite set")
234 def bits(self
, bits
):
235 # type: (int) -> None
237 raise AttributeError("can't write to frozen bitset's bits")
239 raise ValueError("can't store an infinite set")
242 def __contains__(self
, x
):
243 # type: (Any) -> bool
244 if isinstance(x
, int) and x
>= 0:
245 return (1 << x
) & self
.bits
!= 0
249 # type: () -> Iterator[int]
252 index
= trailing_zero_count(bits
)
256 def __reversed__(self
):
257 # type: () -> Iterator[int]
260 index
= top_set_bit_index(bits
)
266 return bit_count(self
.bits
)
271 return f
"{self.__class__.__name__}()"
275 return f
"{self.__class__.__name__}({v})"
276 ranges
= [] # type: list[range]
279 if len(ranges
) != 0 and ranges
[-1].stop
== i
:
281 ranges
[-1].start
, i
+ ranges
[-1].step
, ranges
[-1].step
)
282 elif len(ranges
) != 0 and len(ranges
[-1]) == 1:
283 start
= ranges
[-1][0]
286 ranges
[-1] = range(start
, stop
, step
)
287 elif len(ranges
) != 0 and len(ranges
[-1]) == 2:
288 single
= ranges
[-1][0]
289 start
= ranges
[-1][1]
290 ranges
[-1] = range(single
, single
+ 1)
293 ranges
.append(range(start
, stop
, step
))
295 ranges
.append(range(i
, i
+ 1))
296 if len(ranges
) > MAX_RANGES
:
299 return f
"{self.__class__.__name__}({ranges[0]})"
300 if len(ranges
) <= MAX_RANGES
:
301 range_strs
= [] # type: list[str]
304 range_strs
.append(str(r
[0]))
306 range_strs
.append(f
"*{r}")
307 ranges_str
= ", ".join(range_strs
)
308 return f
"{self.__class__.__name__}([{ranges_str}])"
309 if self
.bits
> 0xFFFFFFFF and len_self
< 10:
311 return f
"{self.__class__.__name__}({v})"
312 return f
"{self.__class__.__name__}(bits={hex(self.bits)})"
314 def __eq__(self
, other
):
315 # type: (Any) -> bool
316 if not isinstance(other
, BaseBitSet
):
317 return super().__eq
__(other
)
318 return self
.bits
== other
.bits
320 def __and__(self
, other
):
321 # type: (Iterable[Any]) -> Self
322 if isinstance(other
, BaseBitSet
):
323 return self
._from
_bits
(self
.bits
& other
.bits
)
326 if isinstance(item
, int) and item
>= 0:
328 return self
._from
_bits
(self
.bits
& bits
)
332 def __or__(self
, other
):
333 # type: (Iterable[Any]) -> Self
334 if isinstance(other
, BaseBitSet
):
335 return self
._from
_bits
(self
.bits | other
.bits
)
338 if isinstance(item
, int) and item
>= 0:
340 return self
._from
_bits
(bits
)
344 def __xor__(self
, other
):
345 # type: (Iterable[Any]) -> Self
346 if isinstance(other
, BaseBitSet
):
347 return self
._from
_bits
(self
.bits ^ other
.bits
)
350 if isinstance(item
, int) and item
>= 0:
352 return self
._from
_bits
(bits
)
356 def __sub__(self
, other
):
357 # type: (Iterable[Any]) -> Self
358 if isinstance(other
, BaseBitSet
):
359 return self
._from
_bits
(self
.bits
& ~other
.bits
)
362 if isinstance(item
, int) and item
>= 0:
364 return self
._from
_bits
(bits
)
366 def __rsub__(self
, other
):
367 # type: (Iterable[Any]) -> Self
368 if isinstance(other
, BaseBitSet
):
369 return self
._from
_bits
(~self
.bits
& other
.bits
)
372 if isinstance(item
, int) and item
>= 0:
374 return self
._from
_bits
(~self
.bits
& bits
)
376 def isdisjoint(self
, other
):
377 # type: (Iterable[Any]) -> bool
378 if isinstance(other
, BaseBitSet
):
379 return self
.bits
& other
.bits
== 0
380 return super().isdisjoint(other
)
383 class BitSet(BaseBitSet
, MutableSet
[int]):
384 """Mutable Bit Set"""
392 def add(self
, value
):
393 # type: (int) -> None
395 raise ValueError("can't store negative integers")
396 self
.bits |
= 1 << value
398 def discard(self
, value
):
399 # type: (int) -> None
401 self
.bits
&= ~
(1 << value
)
407 def __ior__(self
, it
):
408 # type: (AbstractSet[Any]) -> Self
409 if isinstance(it
, BaseBitSet
):
412 return super().__ior
__(it
)
414 def __iand__(self
, it
):
415 # type: (AbstractSet[Any]) -> Self
416 if isinstance(it
, BaseBitSet
):
419 return super().__iand
__(it
)
421 def __ixor__(self
, it
):
422 # type: (AbstractSet[Any]) -> Self
423 if isinstance(it
, BaseBitSet
):
426 return super().__ixor
__(it
)
428 def __isub__(self
, it
):
429 # type: (AbstractSet[Any]) -> Self
430 if isinstance(it
, BaseBitSet
):
431 self
.bits
&= ~it
.bits
433 return super().__isub
__(it
)
436 class FBitSet(BaseBitSet
, metaclass
=InternedMeta
):
447 return super()._hash
()