== Задание 1.
Дана строка string и шаблон pattern (также строка). Необходимо реализовать функцию match, которая
проверяет string на совпадение с pattern, то есть возвращает true, если string соответствует pattern,
и false в противном случае.
Соответствие с шаблоном проверяется следующим образом. Во-первых, количество символов шаблона должно
совпадать с количеством символов строки. Далее, если в шаблоне на i-ой позиции находится символ ‘d’,
то в строке на той же позиции должна находиться цифра 0 - 9. Аналогично, символ ‘a’ в шаблоне
обозначает строчную латинскую букву (т.е. a - z), символ ‘*’ - цифру или латинскую строчную букву,
пробел ‘ ’ обозначает сам себя. Другие символы в шаблоне запрещены, при их обнаружении функция должна
генерировать исключение.
Примеры:
- строка ‘xyz 123’ соответствует шаблону ‘aa* dd*’
- строка ‘1xy’ не соответствует шаблону ‘aaa’ (не сопадает по первому символу)
== Задание 2.
Дано дерево задач с одним корнем. Узлами дерева являются группы задач, листьми - сами задачи. Внутри
группы могут содержаться либо другие группы, либо задачи, но не то и другое одновременно. Каждый элемент
дерева имеет уникальный идентификатор id (неотрицательное целое число) и название name (строка).
Дополнительно задачи имеют приоритет priority (неотрицательное целое число), а группы задач приоритета
не имеют. Необходимо реализовать функцию findTaskHavingMaxPriorityInGroup, в которую передается дерево
задач и идентификатор группы. Она должна найти задачу с наибольшим приоритетом среди всех из этой
группы (включая те из них, которые находятся во вложенных группах). Если не удалось найти группу с
указанным идентификатором, функция должна генерировать исключение. Если в группе нет ни одной задачи,
должно возвращаться неопределенное значение (undefined в JavaScript, None в Python, nullptr в C++ и null в
Kotlin).
Пример:
Допустим, имеется дерево задач
* id = 0, name = “Все задачи”
* id = 1, name = “Разработка”
* id = 2, name = “Планирование разработок”, priority = 1
* id = 3, name = “Подготовка релиза”, priority = 4
* id = 4, name = “Аналитика”
Отступами обозначается вложенность групп задач. Это дерево содержит три группы (“Все задачи”, “Разработка”
и “Аналитика”), а также две задачи (“Планирование разработок” и “Подготовка релиза”). Для этого дерева
вызов функции findTaskHavingMaxPriorityInGroup c номером группы
* 0 - должен вернуть задачу “Подготовка релиза” (имеет максимальный приоритет 4)
* 3 - сгенерировать исключение (не является группой)
* 5 - сгенерировать исключение (группа не существует)
- 4 - вернуть неопределенное значение (в группе нет ни одной задачи)
== Требования к решению.
Если обе задачи
решены правильно, то программа выведет в консоль текст:
PASSED: Test #1 of match
PASSED: Test #2 of match
PASSED: Test #3 of match
PASSED: Test #4 of match
PASSED: Test #5 of match
PASSED: Test #6 of match
PASSED: Test #7 of match
PASSED: Test #8 of match
PASSED: Test #1 of findTaskHavingMaxPriorityInGroup
PASSED: Test #2 of findTaskHavingMaxPriorityInGroup
PASSED: Test #3 of findTaskHavingMaxPriorityInGroup
PASSED: Test #4 of findTaskHavingMaxPriorityInGroup
PASSED: Test #5 of findTaskHavingMaxPriorityInGroup
PASSED: Test #6 of findTaskHavingMaxPriorityInGroup
Если хотя бы одна строка начинается со слова FAILED, значит решение содержит ошибки. Тесты собраны
в функциях testMatch и testFindTaskHavingMaxPriorityInGroup. В них
- expectTrue (expectFalse) означает, что результатом выполнения выражения должно быть true (false)
- expectException - что в результате выполнения выражения должно быть сгенерировано исключение
== Заготовки решений
На Python --------------------------------------------------------------------------------------------------- import traceback class TestRunner(object): def __init__(self, name): self.name = name self.testNo = 1 def expectTrue(self, cond): try: if cond(): self._pass() else: self._fail() except Exception as e: self._fail(e) def expectFalse(self, cond): self.expectTrue(lambda: not cond()) def expectException(self, block): try: block() self._fail() except: self._pass() def _fail(self, e=None): print(f'FAILED: Test # {self.testNo} of {self.name}') self.testNo += 1 if e is not None: traceback.print_tb(e.__traceback__) def _pass(self): print(f'PASSED: Test # {self.testNo} of {self.name}') self.testNo += 1 ## ЭТО УЖЕ САМ МЕТОД РЕШЕНИЕ 1 ЗАДАЧИ ====================== def match(string, pattern): if [type(string),type(pattern)]!=[str]*2:raise TypeError if len(string)!=len(pattern)or set(pattern)-set('ad* '):raise ValueError m,r=[0]*len(string),1 for i in range(len(string)):m[i]=bool((pattern[i]=='a'and string[i]in[chr(i)for i in range(97,123)])or(pattern[i]=='d'and string[i]in[chr(i)for i in range(48,58)])or(pattern[i]==string[i]==' ')or(pattern[i]=='*'and string[i]in([' ']+[chr(i)for i in range(48,58)]+[chr(i)for i in range(97,123)]))) for i in m:r*=i return bool(r) ##================================================== def testMatch(): runner = TestRunner('match') runner.expectFalse(lambda: match('xy', 'a')) runner.expectFalse(lambda: match('x', 'd')) runner.expectFalse(lambda: match('0', 'a')) runner.expectFalse(lambda: match('*', ' ')) runner.expectFalse(lambda: match(' ', 'a')) runner.expectTrue(lambda: match('01 xy', 'dd aa')) runner.expectTrue(lambda: match('1x', '**')) runner.expectException(lambda: match('x', 'w')) tasks = { 'id': 0, 'name': 'Все задачи', 'children': [ { 'id': 1, 'name': 'Разработка', 'children': [ {'id': 2, 'name': 'Планирование разработок', 'priority': 1}, {'id': 3, 'name': 'Подготовка релиза', 'priority': 4}, {'id': 4, 'name': 'Оптимизация', 'priority': 2}, ], }, { 'id': 5, 'name': 'Тестирование', 'children': [ { 'id': 6, 'name': 'Ручное тестирование', 'children': [ {'id': 7, 'name': 'Составление тест-планов', 'priority': 3}, {'id': 8, 'name': 'Выполнение тестов', 'priority': 6}, ], }, { 'id': 9, 'name': 'Автоматическое тестирование', 'children': [ {'id': 10, 'name': 'Составление тест-планов', 'priority': 3}, {'id': 11, 'name': 'Написание тестов', 'priority': 3}, ], }, ], }, {'id': 12, 'name': 'Аналитика', 'children': []}, ], } def findTaskHavingMaxPriorityInGroup(tasks, groupId): def search_group(id, tasks): if tasks['id'] == id: search_max(tasks) return 1 search_group2(id, tasks) def search_group2(id, tasks): if 'children' in tasks: _ = tasks['children'] for pot in _: if pot['id'] == id: search_max(pot) return 0 if 'children' in pot: search_group2(id, pot) def search_max(tasks): global flag if 'priority' in tasks: raise Exception("not a group") if tasks['children'] == []: flag = None return 0 search_max2(tasks) def search_max2(tasks): if 'children' in tasks: _ = tasks['children'] for pot in _: if 'priority' in pot: if pot['priority'] > max['priority']: max['priority'] = pot['priority'] max['name'] = pot['name'] max['id'] = pot['id'] if 'children' in pot: search_max2(pot) max = {'id': 0, 'name':'', 'priority':0,} global flag flag = 1 search_group(groupId, tasks) if flag == None: return None if max['name'] == '': raise Exception("not a group") return max[/size] def taskEquals(a, b): return ( not 'children' in a and not 'children' in b and a['id'] == b['id'] and a['name'] == b['name'] and a['priority'] == b['priority'] ) ## РЕШЕНИЕ ВТОРОЙ ЗАДАЧИ ================================= def testFindTaskHavingMaxPriorityInGroup(): runner = TestRunner('findTaskHavingMaxPriorityInGroup') runner.expectException(lambda: findTaskHavingMaxPriorityInGroup(tasks, 13)) runner.expectException(lambda: findTaskHavingMaxPriorityInGroup(tasks, 2)) runner.expectTrue(lambda: findTaskHavingMaxPriorityInGroup(tasks, 12) is None) runner.expectTrue(lambda: taskEquals(findTaskHavingMaxPriorityInGroup(tasks, 0), { 'id': 8, 'name': 'Выполнение тестов', 'priority': 6, })) runner.expectTrue(lambda: taskEquals(findTaskHavingMaxPriorityInGroup(tasks, 1), { 'id': 3, 'name': 'Подготовка релиза', 'priority': 4, })) runner.expectTrue(lambda: findTaskHavingMaxPriorityInGroup(tasks, 9)['priority'] == 3) #============================ testMatch() testFindTaskHavingMaxPriorityInGroup() -------------------------------------------------------------------------------------------------