"""One solution. Try the exercise first."""

DIGIT_WORDS = {"zero": "0", "oh": "0", "one": "1", "two": "2", "three": "3", "four": "4",
               "five": "5", "six": "6", "seven": "7", "eight": "8", "nine": "9"}


def blame(errors_rec1: set[str], errors_rec2: set[str]) -> dict[str, set[str]]:
    return {"voice": errors_rec1 & errors_rec2, "recognizer": errors_rec1 ^ errors_rec2}


def _canonical(text: str) -> str:
    text = text.lower().replace("-", " ")
    text = "".join(ch for ch in text if ch.isalnum() or ch.isspace())   # "p.m." -> "pm"
    out = []
    for token in text.split():
        if token.isdigit():
            out.extend(token)                     # "0358" -> 0 3 5 8
        else:
            out.append(DIGIT_WORDS.get(token, token))
    return " ".join(out)


def reading_ok(heard: str, accepted: list[str]) -> bool:
    h = _canonical(heard)
    return any(_canonical(a) == h for a in accepted)


def leading_silence(samples: list[float], sample_rate: int, threshold: float = 0.02) -> float:
    for i, s in enumerate(samples):
        if abs(s) > threshold:
            return i / sample_rate
    return len(samples) / sample_rate


def time_to_first_speech(ttfb_s: float, samples: list[float], sample_rate: int) -> float:
    return ttfb_s + leading_silence(samples, sample_rate)
