from __future__ import annotations from dataclasses import dataclass from typing import Iterable import numpy as np @dataclass(frozen=True) class Sequence8: """Пара 8-битных последовательностей: seq0 и инверсная seq1.""" _seq0: np.ndarray # uint8, shape (8,) def __post_init__(self): arr = np.asarray(self._seq0, dtype=np.uint8).reshape(-1) if arr.size != 8: raise ValueError("seq0 должна содержать 8 бит.") if not np.isin(arr, [0, 1]).all(): raise ValueError("seq0 может состоять только из 0 и 1.") object.__setattr__(self, "_seq0", arr) @property def seq0(self) -> np.ndarray: """Последовательность для бита 0.""" return self._seq0 @property def seq1(self) -> np.ndarray: """Инверсия seq0 для бита 1.""" return 1 - self._seq0 def for_bit(self, bit: int) -> np.ndarray: """Вернуть последовательность по значению бита.""" if bit not in (0, 1): raise ValueError("bit должен быть 0 или 1.") return self._seq0 if bit == 0 else (1 - self._seq0) @classmethod def from_string(cls, bits: str) -> "Sequence8": """Создать из строки вида '01010101'.""" if len(bits) != 8 or any(ch not in "01" for ch in bits): raise ValueError("Строка должна быть из 8 символов 0/1.") arr = np.fromiter((int(ch) for ch in bits), dtype=np.uint8, count=8) return cls(arr) @classmethod def from_iterable(cls, bits: Iterable[int]) -> "Sequence8": """Создать из итерируемого набора из 8 бит.""" arr = np.fromiter(bits, dtype=np.uint8, count=8) if arr.size != 8: raise ValueError("Нужно 8 бит.") return cls(arr) def __len__(self) -> int: """Длина последовательности.""" return 8