diff --git a/lesson_3/hometask/hometask_1.py b/lesson_3/hometask/hometask_1.py new file mode 100644 index 0000000..e8a436a --- /dev/null +++ b/lesson_3/hometask/hometask_1.py @@ -0,0 +1,33 @@ +# Реализовать функцию, принимающую два числа (позиционные аргументы) +# и выполняющую их деление. Числа запрашивать у пользователя, +# предусмотреть обработку ситуации деления на ноль. + +# нас интересуют только позиционные аргументы +# ни о каких именованных и позиционных аргументах речь не идёт! +def divide_numbers(num_1, num_2, /): + """ + Функция вычисления частного от деления одного числа на другое + + :param num_1: делимое + :param num_2: делитель + :return: результат деления делимого на делитель или None + """ + try: + return num_1 / num_2 + except ZeroDivisionError: + return None + + +divident = float() +denominator = float() +while True: + try: + divident = float(input("Введите числитель дроби:")) + denominator = float(input("Введите знаменатель дроби:")) + break + except ValueError: + continue + +print(f"{divident}/{denominator}={divide_numbers(divident, denominator)}") +# Тут будет ошибка! Так как аргументы строго позиционные +# print(f"{divident}/{denominator}={divide_numbers(num1 = divident, num2 = denominator)}") diff --git a/lesson_3/hometask/hometask_2.py b/lesson_3/hometask/hometask_2.py new file mode 100644 index 0000000..ca09521 --- /dev/null +++ b/lesson_3/hometask/hometask_2.py @@ -0,0 +1,36 @@ +# Реализовать функцию, принимающую несколько параметров, описывающих данные пользователя: +# имя, фамилия, год рождения, город проживания, email, телефон. +# Функция должна принимать параметры как именованные аргументы. +# Реализовать вывод данных о пользователе одной строкой. + +import datetime + + +# Только именованные аргументы! +# значения по умолчанию не придумал) +def get_user_data(*, name, surname, birthdate, location, email=None, phone=None): + """ + Возвращает информацию о пользователе на основе задаваемых данных. + + :param name: имя пользователя + :param surname: фамилия пользователя + :param birthdate: дата рождения пользователя + :param location: местоположение пользователя + :param email: электронная почта пользователя + :param phone: телефон пользователя + :return: информация о пользователе в одной строке + """ + return f"Oh that obnoxious user {name} {surname}! " \ + f"He was born in {birthdate}. " \ + f"Now {name} located on {location}. " \ + f"You may reach {name} by phone {phone} or email {email}" + + +print(get_user_data(name="Louis", birthdate=datetime.date(year=1973, month=2, day=11), + surname="Cachet", location="Demont", + phone="+33-61-666-14-88", email="christian@jw.fr")) + +# ошибка! +# print(get_user_data("Louis", birthdate=datetime.date(year=1973, month=2, day=11), +# surname="Cachet", location="Demont", +# phone="+33-61-666-14-88", email="christian@jw.fr")) diff --git a/lesson_3/hometask/hometask_3.py b/lesson_3/hometask/hometask_3.py new file mode 100644 index 0000000..3ee1651 --- /dev/null +++ b/lesson_3/hometask/hometask_3.py @@ -0,0 +1,48 @@ +# Реализовать функцию my_func(), которая +# принимает три позиционных аргумента, и +# возвращает сумму наибольших двух аргументов. +import math + + +# вспомогательная функция +def calc_sum(*args): + """ + Вычисляет сумму задаваемых чисел. + При некорректном типе аргументов возвращает минус бесконечность + + :param args: задаваемые числа + :return: сумму задаваемых чисел или -math.inf + """ + try: + return sum(args) + except TypeError: + return -math.inf + + +# нас интересуют только позиционные аргументы, +# ни о каких именованных и позиционных аргументах речь не идёт! +def my_func(arg_1, arg_2, arg_3, /): + """ + Вычисляет сумму наибольших двух аргументов. + При некорректном типе двух задаваемых аргументов возвращает минус бесконечность + + :param arg_1: некое целое или дробное число + :param arg_2: некое целое или дробное число + :param arg_3: некое целое или дробное число + :return: сумму наибольших двух аргументов или -math.inf + """ + return max(calc_sum(arg_1, arg_2), + calc_sum(arg_1, arg_3), + calc_sum(arg_2, arg_3)) + + +def lazy_print(arg_1, arg_2, arg_3): + print(f"Max sum of two elements " + f" between {arg_1}, {arg_2}, {arg_3} is " + f"{my_func(arg_1, arg_2, arg_3)}") + + +lazy_print('ahh', 2, 3) +lazy_print(3, 1, 4) +lazy_print(3.13, 5, 9.11) +lazy_print('ahh', 'fggh', 3) diff --git a/lesson_3/hometask/hometask_4.py b/lesson_3/hometask/hometask_4.py new file mode 100644 index 0000000..5c40be7 --- /dev/null +++ b/lesson_3/hometask/hometask_4.py @@ -0,0 +1,133 @@ +# Программа принимает действительное положительное число x и целое отрицательное число y. +# Необходимо выполнить возведение числа x в степень y. +# Задание необходимо реализовать в виде функции my_func(x, y). +# При решении задания необходимо обойтись без встроенной функции возведения числа в степень. +# ** Подсказка:** попробуйте решить задачу двумя способами. +# Первый — возведение в степень с помощью оператора **. +# Второй — более сложная реализация без оператора **, предусматривающая использование цикла. +import math + + +def my_func_var_1(base, exp): + """ + Алгоритм возведения числа в степень. + + :param base: Число, которое требуется возвести в степень + :param exp: степень, в которую требуется возвести число + :return: число, возведенное в степень + """ + return base ** exp + + +# a^x == exp(x*ln(a)) +# универсальна, расчёт дробных корней прост +# если нет претензий к math.log и math.exp +def my_func_var_2(base, exp): + """ + Алгоритм возведения числа в степень. + Базируеся на формуле a**x == exp(x*ln(a)) + + :param base: Положительное число, которое требуется возвести в степень + :param exp: степень, в которую требуется возвести число + :return: число, возведенное в степень + """ + if base < 0: + raise ValueError("base cannot be negative!") + return math.exp(exp * math.log(base)) + + +def my_func_var_3(base, exp): + """ + Иттерационный алгоритм возведения числа в целую степень. + + :param base: Число, которое требуется возвести в степень + :param exp: степень, в которую требуется возвести число + :return: число, возведенное в степень + """ + if type(exp) != int: + raise TypeError("Uncorrect exponent type") + sign = -1 if (exp < 0) else 1 + res = 1 + for step in range(exp * sign): + res *= base + return res if sign == 1 else 1 / res + + +def my_func_var_4(base, exp): + """ + Быстрый алгоритм возведения числа в целую степень. + Базируется на предствалении числа в бинарном виде + и формулах: + -> a**(x*y) = (a**x)**y; + -> a**(x+y) = (a**x)*(a**y). + Выполнен в соответствие с: + https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B1%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B3%D0%BE_%D0%B2%D0%BE%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B2_%D1%81%D1%82%D0%B5%D0%BF%D0%B5%D0%BD%D1%8C + + :param base: Число, которое требуется возвести в степень + :param exp: целая степень, в которую требуется возвести число + :return: число, возведенное в степень + """ + if type(exp) != int: + raise TypeError("Uncorrect exponent type") + sign = -1 if (exp < 0) else 1 + bin_repr = bin(exp * sign) + res = 1 + for bit in bin_repr[2:len(bin_repr)]: + res *= res * base if bit == '1' else res + return res if sign == 1 else 1 / res + + +# BONUS: +def my_math_root(base, exp, max_error=1e-10): + """ + Алгоритм оценки корня целой степени из числа. + Выполнен в соответствие с: + https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BD%D0%B0%D1%85%D0%BE%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BA%D0%BE%D1%80%D0%BD%D1%8F_n-%D0%BD%D0%BE%D0%B9_%D1%81%D1%82%D0%B5%D0%BF%D0%B5%D0%BD%D0%B8 + + :param base: Число, из которого требуется извлечь корень + :param exp: целая степень корня + :param max_error: требуемая точность оценки корня + :return: оценка корня заданной степени из числа или + None, если корень с требуемой точностью оценить не удалось + """ + if type(exp) != int: + raise TypeError("Uncorrect exponent type") + if exp % 2 == 0 and base < 0: + raise ValueError("Cannot estimate negative base root by even exp") + if exp == 0: + return 1 + new_exp = exp if exp > 0 else -exp + xk = x0 = base + # ограничитель цикла + max_cycle_number = 3000 + for i in range(max_cycle_number): + xk = (1 / new_exp) * ((new_exp - 1) * xk + base / my_func_var_4(xk, new_exp - 1)) + if math.fabs(xk - x0) < max_error: + # сходимость достигнута + return xk if exp > 0 else 1 / xk + x0 = xk + # Если количество итераций превыщено, результат не гарантирован! + return None + + +def test_my_funcs(x, y): + var_1 = my_func_var_1(x, y) +# var_2 = my_func_var_2(x, y) + var_3 = my_func_var_3(x, y) + var_4 = my_func_var_4(x, y) + root = my_math_root(x, y) + nominal = pow(x, y) + root_nominal = pow(x, 1 / y) + print(f"Results of power {x} to {y}:\n" + f"variant 1 is {var_1}, error to pow is {math.fabs(var_1 - nominal)}\n" +# f"variant 2 is {var_2}, error to pow is {math.fabs(var_2 - nominal)}\n" + f"variant 3 is {var_3}, error to pow is {math.fabs(var_3 - nominal)}\n" + f"variant 4 is {var_4}, error to pow is {math.fabs(var_4 - nominal)}") + print(f"Special test: my_math_root {x} by {y} of power {x} to {1 / y} (same as root {x} by {y}):") + print(f"my_math_root is {root}") + print(f"error to pow is {math.fabs(root - root_nominal)}") + + +test_my_funcs(50.4564654546, -31) + +print(my_math_root(5.11568, -2, 1e-30) - pow(5.11568, -1 / 2)) diff --git a/lesson_3/hometask/hometask_5.py b/lesson_3/hometask/hometask_5.py new file mode 100644 index 0000000..abb47c0 --- /dev/null +++ b/lesson_3/hometask/hometask_5.py @@ -0,0 +1,41 @@ +# Программа запрашивает у пользователя строку чисел, разделенных пробелом. +# При нажатии Enter должна выводиться сумма чисел. +# Пользователь может продолжить ввод чисел, разделенных пробелом и снова нажать Enter. +# Сумма вновь введенных чисел будет добавляться к уже подсчитанной сумме. +# Но если вместо числа вводится специальный символ, выполнение программы завершается. +# Если специальный символ введен после нескольких чисел, то +# вначале нужно добавить сумму этих чисел к полученной ранее сумме и после этого завершить программу. + +def get_number_by_string(string_number): + """ + Функция преобразования строки к какому-либо числовому формату + + :param string_number: число в строковом виде + :return: число в числовом формате + """ + try: + return int(string_number) + except ValueError: + # если и тут ошибка, пробрасываем + # во внешний код + return float(string_number) + +# если введен нечисловой символ (но и не специальный) после нескольких чисел, то +# - вначале нужно добавить сумму этих чисел к полученной ранее сумме; +# - пользователь может продолжить ввод чисел, разделенных пробелом и снова нажать Enter. +final_sum = 0 +while True: + input_string = input("Enter the numbers string with ' ' as delimiter; in '$' in string, nothing to be more >>>") + input_array = input_string.split() + try: + # Подсчёт суммы ведётся до первого нечислового символа ('4d' - тоже не числовой символ) + for element in input_array: + # возможно, пользователя будет интересовать + # именно сумма целых чисел, а плавающая запятая - раздражать + final_sum += get_number_by_string(element) + except ValueError: + # считаем, что, например, '3.12$' - уже не число + if '$' in input_string: + break + finally: + print("Current sum is ", final_sum) \ No newline at end of file diff --git a/lesson_3/hometask/hometask_6.py b/lesson_3/hometask/hometask_6.py new file mode 100644 index 0000000..c6028cf --- /dev/null +++ b/lesson_3/hometask/hometask_6.py @@ -0,0 +1,23 @@ +# Реализовать функцию int_func(), принимающую слово из маленьких латинских букв и возвращающую его же, +# но с прописной первой буквой. +# Например, print(int_func(‘text’)) -> Text. +# Продолжить работу над заданием. +# В программу должна попадать строка из слов, разделенных пробелом. +# Каждое слово состоит из латинских букв в нижнем регистре. +# Сделать вывод исходной строки, но каждое слово должно начинаться с заглавной буквы. +# Необходимо использовать написанную ранее функцию int_func(). + +def int_func(string): + return string.capitalize() + + +# строки разделены пробелом +string_array = input("Input a string >>>").split(" ") + +for element_index in range(len(string_array)): + string_element = string_array[element_index] + if " " in string_element or string_element.isdigit(): + continue + string_array[element_index] = int_func(string_element) + +print(' '.join(string_array))