Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions lesson_3/hometask/hometask_1.py
Original file line number Diff line number Diff line change
@@ -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)}")
36 changes: 36 additions & 0 deletions lesson_3/hometask/hometask_2.py
Original file line number Diff line number Diff line change
@@ -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"))
48 changes: 48 additions & 0 deletions lesson_3/hometask/hometask_3.py
Original file line number Diff line number Diff line change
@@ -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)
133 changes: 133 additions & 0 deletions lesson_3/hometask/hometask_4.py
Original file line number Diff line number Diff line change
@@ -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))
41 changes: 41 additions & 0 deletions lesson_3/hometask/hometask_5.py
Original file line number Diff line number Diff line change
@@ -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)
23 changes: 23 additions & 0 deletions lesson_3/hometask/hometask_6.py
Original file line number Diff line number Diff line change
@@ -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))