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))
|