Skip to content

Instantly share code, notes, and snippets.

@danila-schelkov
Last active March 26, 2023 21:33
Show Gist options
  • Save danila-schelkov/268517d8a411676f1f8b01ff3dd81508 to your computer and use it in GitHub Desktop.
Save danila-schelkov/268517d8a411676f1f8b01ff3dd81508 to your computer and use it in GitHub Desktop.
Скрипт для склонения слов в зависимости от числа перед ним. Тесты прилагаются.
from __future__ import annotations
import sys
from typing import Tuple
try:
if sys.version_info >= (3, 11):
from typing import LiteralString
else:
from typing_extensions import LiteralString
except ImportError as e:
print(
"Cannot import LiteralString. Please update your python version to an actual."
)
raise e
def inflect_with_num(
number: int, forms: Tuple[LiteralString, LiteralString, LiteralString]
) -> str:
"""В русском языке есть особенность, что идущее перед словом число
может его в корни изменить.
Например: 1 год, 2 года, 3 года, 4 года, 5 лет. Формы у групп 1,
2-4, 5-10 отличается. В промежутке с 10 до 20 будут идти именно «лета».
А после результат будет зависеть от цифры в разряде единиц.
И так повторяется с каждой сотней.
Для удобства восприятия назовём группы цифрами:
1. Для единицы (1).
2. Единица 0, от 5 до 9 и от 10 до 20 включительно.
3. Единицы от 2 до 4 включительно.
Массив forms принимает формы в том же порядке.
:param number: Число, предшествующее слову
:param forms: Три заданные формы исчисляемого слова
:return:
"""
units = number % 10
tens = number % 100 - units
if tens == 10 or units >= 5 or units == 0:
needed_form = 1
elif units > 1:
needed_form = 2
else:
needed_form = 0
return forms[needed_form]
from inflector import inflect_with_num
def main() -> None:
"""A kinda test function."""
apple_forms = ("яблоко", "яблок", "яблока")
_assert("яблок", inflect_with_num(0, apple_forms))
_assert("яблоко", inflect_with_num(1, apple_forms))
_assert("яблока", inflect_with_num(2, apple_forms))
_assert("яблок", inflect_with_num(5, apple_forms))
_assert("яблок", inflect_with_num(10, apple_forms))
_assert("яблок", inflect_with_num(13, apple_forms))
_assert("яблок", inflect_with_num(20, apple_forms))
_assert("яблоко", inflect_with_num(21, apple_forms))
_assert("яблок", inflect_with_num(100, apple_forms))
_assert("яблока", inflect_with_num(103, apple_forms))
_assert("яблок", inflect_with_num(110, apple_forms))
year_forms = ("год", "лет", "года")
_assert("лет", inflect_with_num(0, year_forms))
_assert("год", inflect_with_num(1, year_forms))
_assert("года", inflect_with_num(2, year_forms))
_assert("лет", inflect_with_num(5, year_forms))
_assert("лет", inflect_with_num(10, year_forms))
_assert("лет", inflect_with_num(13, year_forms))
_assert("лет", inflect_with_num(20, year_forms))
_assert("год", inflect_with_num(21, year_forms))
_assert("лет", inflect_with_num(100, year_forms))
_assert("года", inflect_with_num(103, year_forms))
_assert("лет", inflect_with_num(110, year_forms))
def _assert(expected: str, actual: str) -> None:
assert actual == expected, f"Unexpected value: {actual} instead of {expected}"
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
exit(-1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment