2025-07-01 21:08:39 +10:00
|
|
|
from collections.abc import Iterable
|
2025-07-01 15:33:24 +10:00
|
|
|
from itertools import chain, combinations
|
|
|
|
|
|
2025-06-26 00:20:13 +10:00
|
|
|
def clamp(n: int, min: int, max: int) -> int:
|
|
|
|
|
if n < min:
|
|
|
|
|
return min
|
|
|
|
|
elif n > max:
|
|
|
|
|
return max
|
|
|
|
|
return n
|
|
|
|
|
|
|
|
|
|
def clamp_max(n: int, max: int) -> int:
|
|
|
|
|
return max if n > max else n
|
|
|
|
|
|
|
|
|
|
def clamp_min(n: int, max: int) -> int:
|
|
|
|
|
return min if n < min else n
|
|
|
|
|
|
2025-06-24 16:42:17 +10:00
|
|
|
def digits(n: int) -> int:
|
|
|
|
|
return len(str(n))
|
2025-06-27 03:09:17 +10:00
|
|
|
|
|
|
|
|
# NOTE: assumes A and B are equal length
|
|
|
|
|
def xor_bytes(A: bytes, B: bytes) -> bytes:
|
|
|
|
|
return b''.join([(a ^ b).to_bytes() for (a, b) in zip(A, B)])
|
|
|
|
|
def xor_str(A: str, B: str) -> str:
|
|
|
|
|
return ''.join([chr(ord(a) ^ ord(b)) for (a, b) in zip(A, B)])
|
|
|
|
|
|
2025-07-01 23:27:28 +10:00
|
|
|
|
2025-07-01 21:08:39 +10:00
|
|
|
def powerset(iterable: Iterable) -> Iterable:
|
2025-07-01 15:33:24 +10:00
|
|
|
s = list(iterable)
|
|
|
|
|
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
|