167 lines
7.3 KiB
Python
167 lines
7.3 KiB
Python
"""
|
||
https://stepik.org/lesson/701990/step/8?unit=702091
|
||
|
||
Ваша задача написать программу поиска слова в строке. Задача усложняется тем, что слово должно определяться в разных его формах. Например, слово:
|
||
программирование
|
||
может иметь следующие формы:
|
||
программирование, программированию, программированием, программировании, программирования, программированиям, программированиями, программированиях
|
||
|
||
Для решения этой задачи необходимо объявить класс Morph (морфология), объекты которого создаются командой:
|
||
mw = Morph(word1, word2, ..., wordN)
|
||
где word1, word2, ..., wordN - возможные формы слова.
|
||
|
||
В классе Morph реализовать методы:
|
||
add_word(self, word) - добавление нового слова (если его нет в списке слов объекта класса Morph);
|
||
get_words(self) - получение кортежа форм слов.
|
||
|
||
Также с объектами класса Morph должны выполняться следующие операторы сравнения:
|
||
mw1 == "word" # True, если объект mv1 содержит слово "word" (без учета регистра)
|
||
mw1 != "word" # True, если объект mv1 не содержит слово "word" (без учета регистра)
|
||
И аналогичная пара сравнений:
|
||
"word" == mw1
|
||
"word" != mw1
|
||
|
||
После создания класса Morph, формируется список dict_words из объектов этого класса, для следующих слов с их словоформами:
|
||
- связь, связи, связью, связей, связям, связями, связях
|
||
- формула, формулы, формуле, формулу, формулой, формул, формулам, формулами, формулах
|
||
- вектор, вектора, вектору, вектором, векторе, векторы, векторов, векторам, векторами, векторах
|
||
- эффект, эффекта, эффекту, эффектом, эффекте, эффекты, эффектов, эффектам, эффектами, эффектах
|
||
- день, дня, дню, днем, дне, дни, дням, днями, днях
|
||
|
||
Затем, прочитайте строку из входного потока командой:
|
||
text = input()
|
||
Найдите все вхождения слов из списка dict_words (используя операторы сравнения) в строке text (без учета регистра, знаков пунктуаций и их словоформы). Выведите на экран полученное число.
|
||
"""
|
||
import sys
|
||
import subprocess
|
||
|
||
sys.stdin.reconfigure(encoding="utf-8")
|
||
|
||
|
||
def run_test(request, expected, num=0, count=0):
|
||
test_id = "" if num == 0 else f" #{num}" + (f"of {count}" if count else "")
|
||
|
||
p = subprocess.run(
|
||
[sys.executable, __file__],
|
||
input=f"{request}\n",
|
||
encoding="utf-8",
|
||
text=True,
|
||
capture_output=True,
|
||
)
|
||
if p.stderr:
|
||
print("StdErr:\n", p.stderr, file=sys.stderr)
|
||
p.check_returncode()
|
||
|
||
answer = (p.stderr + p.stdout).strip()
|
||
assert (
|
||
answer == expected
|
||
), f"""\nFailed test{test_id}. Wrong answer
|
||
|
||
This is a sample test from the problem statement!
|
||
|
||
Test input:
|
||
{request}
|
||
|
||
Correct output:
|
||
{expected}
|
||
|
||
|
||
Your code output:
|
||
{answer}
|
||
"""
|
||
|
||
|
||
def stdin_tests():
|
||
tests = [
|
||
("Мы будем устанавливать связь завтра днем.", "2"),
|
||
("Завтра после полудня мы установим контакт.", "0"),
|
||
("Напишите формулу L1-нормы вектора.", "2"),
|
||
("Ф:о@рм-у-л.а за формулой, д.е.н.ь за днем", "4"),
|
||
]
|
||
for i, test in enumerate(tests):
|
||
run_test(*test, i, len(tests))
|
||
|
||
|
||
if sys.argv[-1] == "test":
|
||
stdin_tests()
|
||
exit()
|
||
# ---------
|
||
|
||
from functools import total_ordering
|
||
|
||
|
||
@total_ordering
|
||
class Morph:
|
||
def __init__(self, *words):
|
||
self.words = set(map(str.lower, words))
|
||
# тесты просят сохранять порядок и дубликаты для get_words
|
||
# но только для исходных данных
|
||
# немножко возражаю, хочу set!
|
||
self.words_for_tests = list(map(str.lower, words))
|
||
|
||
def __repr__(self):
|
||
return f"{self.__class__.__name__}({', '.join(map(repr, self.words))})"
|
||
|
||
def add_word(self, word):
|
||
l0 = len(self)
|
||
self.words.add(word.lower())
|
||
if len(self) > l0:
|
||
self.words_for_tests.append(word.lower())
|
||
|
||
def get_words(self):
|
||
return tuple(self.words_for_tests)
|
||
|
||
def __len__(self):
|
||
return len(self.words)
|
||
|
||
def __radd__(self, other):
|
||
return self + other
|
||
|
||
def __add__(self, other):
|
||
if hasattr(other, "words"):
|
||
return self.__class__(*self.words, *other.words)
|
||
if isinstance(other, str):
|
||
return self.__class__(*self.words, *other.split())
|
||
return NotImplemented
|
||
|
||
def __contains__(self, other):
|
||
return self == other
|
||
|
||
def __eq__(self, other):
|
||
if hasattr(other, "words"):
|
||
return self.words == other.words
|
||
if isinstance(other, str):
|
||
return other.lower() in self.words
|
||
return NotImplemented
|
||
|
||
def __lt__(self, other):
|
||
if hasattr(other, "words"):
|
||
return self.words < other.words
|
||
if isinstance(other, str):
|
||
return other.lower() in self.words
|
||
return NotImplemented
|
||
|
||
def __gt__(self, other):
|
||
if hasattr(other, "words"):
|
||
return self.words > other.words
|
||
if isinstance(other, str):
|
||
return False
|
||
return NotImplemented
|
||
|
||
|
||
data = """\
|
||
- связь, связи, связью, связей, связям, связями, связях
|
||
- формула, формулы, формуле, формулу, формулой, формул, формулам, формулами, формулах
|
||
- вектор, вектора, вектору, вектором, векторе, векторы, векторов, векторам, векторами, векторах
|
||
- эффект, эффекта, эффекту, эффектом, эффекте, эффекты, эффектов, эффектам, эффектами, эффектах
|
||
- день, дня, дню, днем, дне, дни, дням, днями, днях\
|
||
"""
|
||
sanitizer = str.maketrans({k: "" for k in "–?!,.:;()+-*^%$#@№/\\<>"})
|
||
dict_words = [*map(lambda x: Morph(*x.translate(sanitizer).split()), data.split("\n"))]
|
||
all_words = sum(dict_words, Morph())
|
||
|
||
text = input() # эту строчку не менять
|
||
|
||
words = [*map(lambda x: x.translate(sanitizer), text.split())]
|
||
print(sum(word in all_words for word in words))
|