diff --git a/mod_oop/3.5_08_morph.py b/mod_oop/3.5_08_morph.py new file mode 100644 index 0000000..f0ad8f2 --- /dev/null +++ b/mod_oop/3.5_08_morph.py @@ -0,0 +1,166 @@ +""" + 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))