Решите задачи, приведённые ниже. Код каждой задачи разместите в отдельном файле, название которого соответствует указанному в условии задачи. В качестве ответа на это задание загрузите архив (ZIP) с решениями. Архив должен содержать только файлы с решениями, файл test.py и вспомогательные файлы, необходимые для отдельных задач (не должно быть папок). Напишите тесты для решённых задач с использованием фреймворка pytest, разместите их в файле test.py. Для каждой задачи достаточно рассмотреть принципиально различные ситуации (входные данные). Всего должно быть написано не менее 60 тестов. В отличие от предыдущего домашнего задания, в данном задании предполагается, что решение каждой задачи будет представлено в виде функции (если не сказано иного), которую вам необходимо импортировать в файле test.py для последующего тестирования (т. е. в тестах должны непосредственно вызываться тестируемые функции). При импорте функций не должно выполняться ничего лишнего. При необходимости выполнить какие-либо действия при запуске файла с программой (например, запросить пользовательский ввод, осуществить замер времени выполнения функции т. д.) не забудьте заключить их в условие `if __name__ == '__main__':`. При обнаружении ошибок или неточностей в формулировках задач свяжитесь с преподавателем. ## 1) Вычисление факториала Реализуйте рекурсивную (fact_rec) и итерационную (fact_it) функции вычисления факториала целого положительного числа n. Сравните скорость работы реализованных функций, результат сравнения приведите в комментарии в файле с программой. Для измерения времени выполнения можно использовать модули `time` или `timeit`. Функцией math.factorial пользоваться нельзя. **Ограничения:** - 1 ⩽ n ⩽ 10⁵ **Название файла:** fact.py ## 2) Данные сотрудника Реализуйте функцию show_employee, принимающую в качестве аргументов имя сотрудника (name) и величину его заработной платы (salary) и возвращающую строку с данными в следующем формате: "Иванов Иван Иванович: 30000 ₽". В случае, если значение заработной платы не было передано при вызове функции, установить его равным 100000. **Название файла:** show_employee.py ## 3) Сумма и разность Реализуйте функцию sum_and_sub, которая принимает в качестве аргументов два действительных числа (a и b) и возвращает их сумму и разность. **Название файла:** sum_and_sub.py ## 4) Обработка списка В файле process_list.py приведён код функции обработки данных списка (arr). Перепишите приведённую функцию с использованием list comprehension. Реализуйте функцию-генератор с аналогичной функциональностью (process_list_gen). Сравните скорость работы реализованных функций, результат сравнения приведите в комментарии в файле с программой. **Ограничения:** - 1 ⩽ len(arr) ⩽ 10³ **Название файла:** process_list.py ## 5) Функция сложения с произвольным количеством аргументов Реализуйте функцию my_sum, принимающую произвольное количество аргументов (действительных чисел) и возвращающую их сумму. **Название файла:** my_sum.py ## 6) Аргументы командной строки Перепишите программу из 5-й задачи таким образом, чтобы числа для сложения передавались при вызове программы как аргументы командной строки, а результат выводился на стандартный поток вывода. **Название файла:** my_sum_argv.py **Пример вызова:** python3 my_sum_argv.py 1 2 3 4 5 **Пример вывода:** ``` 15 ``` ## 7) Сортировка файлов Напишите программу, которая в качестве аргумента командной строки принимает путь до некоторой директории и выводит список всех файлов в этой директории, упорядоченных в лексикографическом порядке и сгруппированных по расширению. Имена вложенных подкаталогов выводить не нужно. Например, если в директории находятся файлы a.py, a.txt, b.py, b.txt, c.py, c.txt, они должны быть выведены в следующем порядке: ``` a.py b.py c.py a.txt b.txt c.txt ``` **Подсказка:** для того, чтобы отличить строку с именем файла от строки с именем подкаталога можно использовать функции os.path.isfile или os.path.isdir. **Название файла:** files_sort.py ## 8) Рекурсивный поиск файла Напишите программу, которая в качестве аргумента командной строки принимает имя файла и осуществляет рекурсивный поиск указанного файла относительно директории, в которой находится файл с программой. Если файл найден -- вывести первые 5 строк, в противном случае -- вывести сообщение "Файл {название_файла} не найден". **Подсказка:** если вы пишете рекурсивную функцию, то после рекурсивного вызова нужно возвращаться в родительский каталог при помощи os.chdir(".."). Другой вариант решения задачи: воспользоваться функцией os.walk. **Название файла:** file_search.py ## 9) Валидация адресов электронной почты Вам дается целое число N, за которым следуют N адресов электронной почты. Ваша задача -- вывести список, содержащий только корректные адреса электронной почты в лексикографическом порядке. Корректные адреса электронной почты должны соответствовать следующим правилам: - Он должен иметь формат username@websitename.extension. - Имя пользователя может содержать только цифры, латинские буквы, тире и подчеркивания. - Название веб-сайта может содержать только цифры и латинские буквы. - Расширение может содержать только латинские буквы. - Максимальная длина расширения составляет 3. Допишите функцию fun, которая прилагается к заданию, чтобы она возвращала True для корректных адресов, а для остальных -- False. **Формат ввода:** Первая строка ввода -- целое число, количество адресов электронной почты. Далее следуют N строк, каждая из которых содержит адрес электронной почты. **Ограничения:** Не может быть введено пустых значений. **Пример ввода:** ``` 3 lara@mospolytech.ru brian-23@mospolytech.ru britts_54@mospolytech.ru ``` **Пример вывода:** ``` ['brian-23@mospolytech.ru', 'britts_54@mospolytech.ru', 'lara@mospolytech.ru'] ``` **Название файла:** email_validation.py ## 10) Числа Фибоначчи Дополните код, приведённый в файле fibonacci.py. Вы должны сгенерировать список первых n чисел Фибоначчи, начиная с 0. Затем примените функцию map и лямбда-выражение для возведения в куб каждого из полученных чисел Фибоначчи и выведите список на стандартный поток вывода. **Формат ввода:** Одна строка: целое число n. **Формат вывода:** Список в одной строке, содержащий кубы первых n чисел Фибоначчи. **Ограничения:** - 1 ⩽ n ⩽ 15 **Пример ввода:** ``` 5 ``` **Пример вывода:** ``` [0, 1, 1, 8, 27] ``` **Название файла:** fibonacci.py ## 11) Средние оценки Университет проводит экзамен для N студентов по X предметам. Реализуйте функцию compute_average_scores, которая подсчитывает средние баллы каждого студента. Функция принимает один параметр scores -- список из X кортежей, каждый из которых содержит по N чисел в диапазоне от 0 до 100. Каждый кортеж соответствует оценкам по определённому предмету. Элементы с одинаковым индексом в каждом из кортежей соответствуют одному и тому же студенту. Возвращает функция кортеж из X элементов -- средние баллы каждого студента. **Формат ввода:** Первая строка содержит значения N и X, разделенные пробелом. Следующие X строк содержат оценки, разделенные пробелом, полученные учащимися по определенному предмету. **Ограничения:** - 0 < N ⩽ 100 - 0 < X ⩽ 100 **Формат вывода:** Выведите средние значения по всем учащимся в отдельных строках. Средние значения должны быть корректными с точностью до 1 десятичного знака. **Пример ввода:** ``` 5 3 89 90 78 93 80 90 91 85 88 86 91 92 83 89 90.5 ``` **Пример вывода:** ``` 90.0 91.0 82.0 90.0 85.5 ``` **Название файла:** average_scores.py ## 12) Угол между плоскостями Вам даны четыре точки (A, B, C, D) в трехмерной декартовой системе координат. Вам нужно вычислить угол между плоскостями, образованными точками A, B, C и B, C, D в градусах (не в радианах). Обозначим этот угол как ϕ, тогда cos(ϕ) = (X, Y)/|X||Y|, где X = AB × BC и Y = BC × CD. (X, Y) -- скалярное произведение X и Y, AB × BC -- векторное произведение AB и BC, где AB = B − A и BC = B − C. Оформите решение в виде функции plane_angle, которая принимает четыре аргумента: точки A, B, C, D (экземпляры класса Point). В файле plane_angle.py приведена заготовка класса Point -- допишите недостающие методы, которые вам потребуются для решения задачи. Функция plane_angle должна возвращать одно число -- искомый угол в градусах. **Название файла:** plane_angle.py ## 13) Форматирование номера телефона Вам даны номера мобильных телефонов. Отсортируйте их в порядке возрастания, затем выведите в стандартном формате: +7 (xxx) xxx-xx-xx. Указанные мобильные номера могут начинаться с 8, +7 или 0, после чего следует десятизначный номер. Также префикс может отсутствовать вовсе. Вам дана заготовка кода в файле phone_number.py -- заполните недостающие фрагменты. **Формат ввода:** Первая строка ввода содержит целое число N, количество номеров мобильных телефонов. Далее следуют N строк, содержащие номера мобильных телефонов. **Формат вывода:** Выведите N номеров мобильных телефонов отдельными строками в требуемом формате. **Пример ввода:** ``` 3 07895462130 89875641230 9195969878 ``` **Пример вывода:** ``` +7 (789) 546-21-30 +7 (919) 596-98-78 +7 (987) 564-12-30 ``` **Название файла:** phone_number.py ## 14) Сортировка списка Вам предоставляется некоторая информация о людях. Для каждого человека в вашем распоряжении есть имя, фамилия, возраст и пол. Выведите их имена в определенном формате (см. ниже), отсортируйте список по возрасту в порядке возрастания, т.е. имя самого младшего человека должно быть напечатано первым. Для двух человек одного возраста выведите их в порядке ввода. Вам дана заготовка кода в файле people_sort.py -- заполните недостающие фрагменты. **Формат ввода:** Первая строка содержит целое число N, количество человек. Следующие N строк содержат разделенные пробелом значения имени, фамилии, возраста и пола соответственно. **Формат вывода:** Выведите имена в отдельных строках в приведённом ниже формате в порядке возрастания возраста. Пример формата вывода: для "Henry Davids" вывод должен быть "Mr. Henry Davids", для "Mary George" вывод должен быть "Ms. Mary George". **Ограничения:** - 1 ⩽ N ⩽ 10 **Пример ввода:** ``` 3 Mike Thomson 20 M Robert Bustle 32 M Andria Bustle 30 F ``` **Пример вывода:** ``` Mr. Mike Thomson Ms. Andria Bustle Mr. Robert Bustle ``` **Название файла:** people_sort.py ## 15) Комплексные числа Для этого задания вам даны два комплексных числа, и вы должны вывести результат их сложения, вычитания, умножения, деления и операции вычисления модуля. Действительная и мнимая части должны быть представлены с точностью до двух знаков после запятой. Вам дана заготовка кода в файле complex_numbers.py -- заполните недостающие фрагменты. **Формат ввода:** Одна строка ввода: действительная и мнимая части числа, разделенные пробелом. **Формат вывода:** Для двух комплексных чисел C и D выходные данные должны быть в следующей последовательности в отдельных строках: - C + D, - C - D, - C * D, - C/D, - mod(C), - mod(D). Для комплексных чисел с ненулевой действительной (A) и комплексной (B) частью выходные данные должны быть в следующем формате: A + Bi. Знак "+" должен быть заменён на "-", если B < 0. Для комплексных чисел с нулевой комплексной частью (B), т.е. действительных чисел, выходные данные должны быть в формате: A + 0.00i. Для комплексных чисел, где действительная часть (A) равна нулю, а комплексная часть (B) ненулевая, выходные данные должны быть: 0.00 + Bi. **Пример ввода:** ``` 2 1 5 6 ``` **Пример вывода:** ``` 7.00+7.00i -3.00-5.00i 4.00+17.00i 0.26-0.11i 2.24+0.00i 7.81+0.00i ``` **Название файла:** complex_numbers.py ## 16) Монте-Карло Реализуйте вычисление площади окружности методом Монте-Карло. Оформите решение в виде функции circle_square_mk, которая принимает два параметра: r -- радиус окружности и n -- количество экспериментов в методе Монте-Карло, и возвращает действительное число -- полученную площадь. При тестировании функции сравните полученные результаты с площадью, вычисленной по формуле. Оцените получаемую погрешность расчёта в зависимости от количества экспериментов (n), результат укажите в комментарии. **Название файла:** circle_square_mk.py ## 17) Декоратор для логирования Напишите декоратор function_logger, который принимает в качестве аргумента путь к файлу. Если данный декоратор добавить к функции, то в указанный файл будет логироваться информация вида: - Название функции, - Время вызова функции (в формате yyyy-mm-dd HH:MM:SS), - Входящие аргументы (при наличии: в виде кортежа -- позиционные, в виде словаря -- ключевые), - Возвращаемое значение (если есть, если нет то логировать '-') - Время завершения работы функции (в формате yyyy-mm-dd HH:MM:SS) - Время работы функции (в секундах). При отсутствии указанного файла он должен быть создан, в противном случае логи должны добавляться в конец файла. **Пример использования:** ```python @function_logger('test.log') def greeting_format(name): return f'Hello, {name}!' greeting_format('John') ``` **Пример содержимого файла test.log:** ``` greeting_format 2024-02-19 16:00:12.670738 ('John',) Hello, John! 2024-02-19 16:00:12.670741 0:00:00.000003 ``` **Название файла:** log_decorator.py **Замечание:** При написании тестов вам может быть полезна библиотека FreezeGun.