Update assistant features and docs
This commit is contained in:
43
app/core/roman.py
Normal file
43
app/core/roman.py
Normal file
@@ -0,0 +1,43 @@
|
||||
"""Roman numeral parsing helpers."""
|
||||
|
||||
import re
|
||||
|
||||
_ROMAN_VALID_RE = re.compile(
|
||||
r"^M{0,3}(CM|CD|D?C{0,3})"
|
||||
r"(XC|XL|L?X{0,3})"
|
||||
r"(IX|IV|V?I{0,3})$"
|
||||
)
|
||||
_ROMAN_TOKEN_RE = re.compile(r"(?<![A-Za-zА-Яа-яЁё0-9])[IVXLCDMivxlcdm]+(?![A-Za-zА-Яа-яЁё0-9])")
|
||||
_ROMAN_VALUES = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000}
|
||||
|
||||
|
||||
def roman_to_int(token: str) -> int | None:
|
||||
if not token:
|
||||
return None
|
||||
|
||||
roman = token.strip().upper()
|
||||
if not roman or not _ROMAN_VALID_RE.fullmatch(roman):
|
||||
return None
|
||||
|
||||
total = 0
|
||||
prev = 0
|
||||
for char in reversed(roman):
|
||||
value = _ROMAN_VALUES[char]
|
||||
if value < prev:
|
||||
total -= value
|
||||
else:
|
||||
total += value
|
||||
prev = value
|
||||
return total
|
||||
|
||||
|
||||
def replace_roman_numerals(text: str) -> str:
|
||||
if not text:
|
||||
return text
|
||||
|
||||
def _repl(match: re.Match) -> str:
|
||||
token = match.group(0)
|
||||
value = roman_to_int(token)
|
||||
return str(value) if value is not None else token
|
||||
|
||||
return _ROMAN_TOKEN_RE.sub(_repl, text)
|
||||
Reference in New Issue
Block a user