├── .gitignore ├── Module1 ├── examples │ ├── 01_class_objects.py │ ├── 02_class_constructor.py │ ├── 03_class_type.py │ ├── 05_objects_list.py │ └── 06_object_methods.py ├── home_work │ ├── 01_hw_coins.py │ ├── 02_Car_result.py │ └── 02_Car_task.md └── practice │ ├── 01-points │ ├── 00_dictance_dict.py │ ├── 01_distance.py │ ├── 02_points.py │ ├── 03_point_method.py │ ├── 04_long_points.py │ ├── 05_line.py │ └── 06_color_points[add].py │ ├── 02-peoples │ ├── 00_people.py │ └── 01_peoples_task.py │ └── 03-figures[add] │ ├── 00_figures_triangle.py │ ├── 01_figures_circles.py │ ├── 02_figures_point_in_circle.py │ ├── 03_figures_circles_intersect.py │ └── 04_figures[add].py ├── Module10 └── practice │ ├── Fraction │ ├── 01_simplification_fraction.py │ ├── 02_task_Fraction_part1.py │ ├── 03_task_Fraction_part2.py │ ├── 04_task_Fraction_part3.py │ └── 05_task_Fraction_part4.py │ ├── IterInt │ └── 01_task_IterInt.py │ └── helpers │ ├── lcmp_gcd.py │ └── parse_fraction.py ├── Module2 ├── home_works │ └── backpack_hw.py └── practice │ └── backpack │ ├── 01_Item.py │ ├── 02_backpack_par1.py │ ├── 03_backpack_part2.py │ └── 04_backpack_part3.py ├── Module3 ├── examples │ ├── 1_overloading.py │ └── 2_polymorphism.py ├── home_work │ ├── 01_Money_result.py │ ├── 01_Money_task.md │ ├── 02_Vector_result.py │ ├── 02_Vector_task.md │ ├── 03_Roman_numbers.py │ ├── img │ │ ├── vector-cartesian.png │ │ ├── vector_add.png │ │ ├── vector_mult.jpg │ │ └── vector_sub.png │ └── tests │ │ └── test_Money.py └── practice │ └── books │ ├── 00_book_author.py │ ├── 01_book_to_str.py │ ├── 02_books_list.py │ └── 03_books_filter.py ├── Module4 ├── examples │ ├── 1_types_extension.py │ ├── 2_inheritance.py │ ├── 3_iter_rules.py │ └── 4_myIter.py ├── home_work │ ├── Currency │ │ └── 01_task_Currency.py │ └── helpers │ │ └── request_currency.py └── practice │ └── deck │ ├── 00_task_deck.md │ ├── 01_card_to_str.py │ ├── 02_card_equal.py │ ├── 03_cards_list.py │ ├── 04_cards_action.py │ ├── 05_deck_part1.py │ ├── 06_deck_part2.py │ ├── 07_deck_part3.py │ ├── 08_deck_part4[add].py │ ├── 09_deck_final.py │ └── deck_tasks │ ├── 01_task_deck.py │ ├── 02_task_deck.py │ ├── 03_task_deck.py │ ├── 04_task_deck.py │ ├── 05_task_deck.py │ ├── 06_task_deck.py │ └── deck_total.py ├── Module5 ├── examples │ ├── 01_sort_choice.py │ ├── 01_sort_choice_com.py │ ├── 02_bubble_sort.py │ ├── 03_quick_sort.py │ ├── 04_bin_search.py │ └── decor_benchmark.py └── practice │ ├── 01_bases_sort │ ├── 01_base_sort.py │ └── 02_base_sort.py │ └── 02_tasks_sort │ ├── 01_task_sort.py │ ├── 02_task_sort.py │ ├── 03_task_sort.py │ ├── 04_task_sort.py │ ├── 05_task_sort.py │ ├── 06_task_sort.py │ ├── 07_task_sort.py │ ├── 08_task_sort.py │ ├── 09_task_sort.py │ ├── 10_task_sort.py │ └── 11_task_sort.py ├── Module6 ├── home_work │ ├── 01_hw_sort.py │ └── 02_hw_linkedList.py └── practice │ ├── LinkedList.py │ └── nodes │ ├── 01_nodes_create.py │ ├── 02_nodes_from_list.py │ ├── 03_nodes_len.py │ ├── 04_nodes_index.py │ └── 05_nodes_find.py ├── Module7 ├── examples │ ├── bfs.py │ └── dfs.py ├── home_work │ ├── friends_of_friends.py │ └── peoples.json └── practice │ ├── 01_Maze-1 │ ├── img │ │ └── maze-task01.png │ ├── maze1.py │ └── task.md │ ├── 02_Maze-2 │ ├── img │ │ └── maze-task02.png │ ├── maze2.py │ └── task.md │ ├── 03_Maze-3 │ ├── img │ │ └── maze-task03.png │ ├── maze3.py │ └── task.md │ ├── 04_Maze-4 │ ├── img │ │ └── maze-task04.png │ ├── maze4.py │ └── task.md │ ├── 05_Maze-with-door │ ├── img │ │ └── maze-with-door-task.png │ ├── maze_door.py │ └── task.md │ └── 06_Maze-with-treasure │ ├── img │ └── maze-with-T-task.png │ ├── maze_treasure.py │ └── task.md ├── Module8 ├── examples │ ├── 1_inheritance.py │ └── 2_types_extension.py └── practice │ ├── Dice │ └── dice.py │ └── IBank │ ├── IBank_part1_1.py │ ├── IBank_part1_2.py │ ├── IBank_part1_3.py │ ├── IBank_part1_4[add].py │ ├── IBank_part2.py │ ├── IBank_part3.py │ ├── IBank_part4_1.py │ ├── IBank_part4_2.py │ ├── IBank_part5.py │ ├── helpers │ ├── validate_passport.py │ └── validate_phone_number.py │ ├── menu_IBank.py │ ├── tasks │ ├── 01_IBank_part1.md │ ├── 02_IBank_part2.md │ ├── 03_IBank_part3.md │ ├── 04_IBank_part4.md │ ├── 05_IBank_part5.md │ ├── img │ │ ├── open_terminal.jpg │ │ └── stuct.jpg │ └── run_test.md │ └── tests │ ├── test_account_part1.py │ ├── test_account_part2.py │ ├── test_account_part3.py │ └── test_credit_account.py └── Module9 ├── examples ├── 01_collections_Counter.py ├── 02_collections_deque.py ├── 03_collections_OrderedDict.py └── 04_collections_namedtuple.py └── practice ├── BlackJack ├── BlackJack.py ├── classes.py ├── task.md └── tools.py ├── collection_tasks ├── 01_task_collect.py ├── 02_task_collect.py ├── 03_task_collect.py └── 04_task_collect.py └── lean_kivy ├── step1.py ├── step2.py ├── step3.py ├── step4.py └── task1_TicTacToe.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.pyc 3 | *cache/ 4 | tmp/ -------------------------------------------------------------------------------- /Module1/examples/01_class_objects.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | pass 3 | 4 | 5 | # Создадим несколько объектов-точек 6 | point1 = Point() 7 | point2 = Point() 8 | 9 | # Добавим координаты(свойства) x, y для первой точки 10 | point1.x = 7 11 | point1.y = 8 12 | 13 | # Прочитаем значения свойств 14 | print(point1.x) # 7 15 | print(point1.y) # 8 16 | # По сути, свойства - это переменные внутри объекта. Объект для свойств является контейнером 17 | 18 | # Попытка обратиться к x, y второй точки 19 | # print(point2.x) <-- ошибка, сейчас свойство x есть только у первой точки 20 | # print(point2.y) <-- ошибка 21 | -------------------------------------------------------------------------------- /Module1/examples/02_class_constructor.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | # Конструктор - вызывается автоматически, при создании объекта из класса 3 | def __init__(self, x, y): 4 | self.x = x 5 | self.y = y 6 | 7 | 8 | # Создадим несколько объектов 9 | point1 = Point(10, -8) 10 | point2 = Point(12, 5) 11 | 12 | print("point1.x = ", point1.x) 13 | print("point1.y = ", point1.y) 14 | 15 | print("point2.x = ", point2.x) 16 | print("point2.y = ", point2.y) 17 | -------------------------------------------------------------------------------- /Module1/examples/03_class_type.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def __init__(self, x, y): 3 | self.x = x 4 | self.y = y 5 | 6 | 7 | point1 = Point(10, -8) 8 | point2 = Point(12, 5) 9 | 10 | print(type(point1)) # 11 | print(type(point2)) # 12 | # Класс - пользовательский тип данных 13 | -------------------------------------------------------------------------------- /Module1/examples/05_objects_list.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def __init__(self, x, y): 3 | self.x = x 4 | self.y = y 5 | 6 | 7 | # Создаем список из объектов-точек 8 | points = [Point(10, -8), Point(12, 5), Point(-3, 7)] 9 | 10 | # Выведем координату x первой точки 11 | print(points[0].x) 12 | 13 | # Переберем все точки циклом и выведем их координаты в нужном нам формате(виде) 14 | for point in points: 15 | print(f"(x:{point.x}, y:{point.y})") -------------------------------------------------------------------------------- /Module1/examples/06_object_methods.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | # Конструктор - тоже является методом, но с зарезервированным именем 3 | def __init__(self, x, y): 4 | self.x = x 5 | self.y = y 6 | 7 | # Метод - функция внутри класса 8 | def dist_to(self, other_point): 9 | return ((self.x - other_point.x) ** 2 + (self.y - other_point.y) ** 2) ** 0.5 10 | 11 | 12 | point1 = Point(10, -8) 13 | point2 = Point(12, 5) 14 | 15 | dist = point1.dist_to(point2) 16 | print("Расстояние между точками =", dist) 17 | -------------------------------------------------------------------------------- /Module1/home_work/01_hw_coins.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | class Coin: 5 | def __init__(self): 6 | self.side = None 7 | 8 | def flip(self) -> None: 9 | """ 10 | Подбрасывание монетки. # heads-орел/tails-решка 11 | """ 12 | self.side = ... # random: heads/tails 13 | 14 | # Задание: 15 | # 1. Создайте список из n-монеток, n - вводится с клавиатуры 16 | # 2. Подбросьте(flip) все монетки. У каждой монетки в списке вызовите метод .flip() 17 | # 3. Выведите соотношение выпавших орлов и решек в процентах 18 | 19 | # Пояснение: когда вы создаете монетку, то она находится в неопределенном состоянии self.side = None, т.е. 20 | # она находится у вас в руке и не выпала ни орлом ни решкой. Монетка "определеяется" со стороной(орел/решка), 21 | # только после того, как вы ее подбрасываете(вызываете метод flip()) 22 | -------------------------------------------------------------------------------- /Module1/home_work/02_Car_result.py: -------------------------------------------------------------------------------- 1 | # Сюда отправляем решение задачи "Автомобиль" 2 | # Само задание в файле 02_Сar_task.md 3 | 4 | class Car: 5 | def __init__(self, ...): 6 | self.gas = ... 7 | self.capacity = ... 8 | self.gas_per_km = ... 9 | 10 | def fill(self, ...) -> None: 11 | ... 12 | 13 | def ride(self, ...) -> None: 14 | ... 15 | -------------------------------------------------------------------------------- /Module1/home_work/02_Car_task.md: -------------------------------------------------------------------------------- 1 | ## Автомобиль 2 | 3 | Описать класс Car 4 | ``` python 5 | class Car: 6 | ... 7 | 8 | ``` 9 | **Важно**: названия методов и атрибутов(свойств) в вашем коде, должны соответствовать указанным в задаче. 10 | 11 | а) У машины должны быть атрибуты 12 | * "сколько бензина в баке" (gas) 13 | * "вместимость бака" - сколько максимум вмещается бензина (capacity) 14 | * "расход топлива на **один** километр" (gas_per_km) 15 | 16 | б) При создании автомобиля, должна быть реализована возможность указывать начальное количество топлива. \ 17 | Но по умолчанию автомобиль должен создаваться с пустым баком. 18 | 19 | "Вместимость бака" и "расход топлива" должны быть обязательными параметрами конструктора, \ 20 | т.е. их необходимо указывать при создании нового автомобиля. 21 | 22 | б) Реализуйте метод "залить столько-то литров в бак" 23 | 24 | ``` python 25 | car.fill(5) # залили 5 литров 26 | ``` 27 | 28 | Должна учитываться вместительность бака. 29 | Если пытаемся залить больше, чем вмещается, то бак заполняется полностью + print'ом выводится сообщение о лишних литрах 30 | 31 | в) метод "проехать сколько-то км" 32 | 33 | ``` python 34 | car1.ride(50) # едем 50 км (если хватит топлива) 35 | ``` 36 | В результате поездки тратится бензин. 37 | Машина проедет расстояние, на которое хватит топлива. 38 | 39 | г) добавить атрибут с пробегом(mileage), который увеличивается в результате вызова .ride() 40 | 41 | Новый автомобиль всегда создается с нулевым пробегом. 42 | 43 | **Важно**: тщательно протестируйте вашу реализацию! 44 | 45 | -------------------------------------------------------------------------------- /Module1/practice/01-points/00_dictance_dict.py: -------------------------------------------------------------------------------- 1 | def distance(p1: dict, p2: dict) -> float: 2 | """ 3 | Расстояние между двумя точками 4 | """ 5 | # TODO: напишите тело функции 6 | 7 | 8 | # Даны две точки на координатной плоскости 9 | point1 = {"x": 2, "y": 5} 10 | point2 = {"x": -2, "y": 4} 11 | 12 | dist = distance(point1, point2) 13 | 14 | print("Расстояние между точками = ", dist) 15 | -------------------------------------------------------------------------------- /Module1/practice/01-points/01_distance.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def __init__(self, x: int, y: int): 3 | self.x = x 4 | self.y = y 5 | 6 | 7 | def distance(p1: Point, p2: Point) -> float: 8 | """ 9 | Расстояние между двумя точками 10 | """ 11 | # TODO: напишите тело функции 12 | 13 | 14 | # Даны две точки на координатной плоскости 15 | point1 = Point(2, 4) 16 | point2 = Point(5, -2) 17 | 18 | dist = distance(point1, point2) # Передаем объекты point1 и point2 в функцию 19 | 20 | print("Расстояние между точками = ", dist) 21 | -------------------------------------------------------------------------------- /Module1/practice/01-points/02_points.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def __init__(self, x: int, y: int): 3 | self.x = x 4 | self.y = y 5 | 6 | 7 | # Дан список из произвольного количества точек: 8 | points = [Point(3, 8), Point(7, -5), Point(10, -2), Point(0, 6), Point(-12, 0)] 9 | # И произвольная точка на плоскости: 10 | random_point = Point(-12, 10) 11 | 12 | # TODO: выведите расстояние от каждой точки(из списка) до точки random_point 13 | # Совет: используйте функцию distance() из предыдущего задания 14 | # Подсказка: смотри пример, Module1/examples/05_objects_list.py 15 | -------------------------------------------------------------------------------- /Module1/practice/01-points/03_point_method.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | class Point: 5 | def __init__(self, x: int, y: int): 6 | self.x = x 7 | self.y = y 8 | 9 | def dist_to(self, other_point: Point) -> float: 10 | # TODO-1: реализуйте метод 11 | # Подсказка: смотри пример, Module1/examples/06_object_methods.py 12 | ... 13 | 14 | 15 | # Дано две точки на координатной плоскости 16 | point1 = Point(2, 4) 17 | point2 = Point(5, -2) 18 | 19 | # TODO-2: выведите расстояние между точками используя метод dist_to() 20 | print(f"Расстояние между точками = {...}") 21 | -------------------------------------------------------------------------------- /Module1/practice/01-points/04_long_points.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | class Point: 5 | def __init__(self, x: int, y: int): 6 | self.x = x 7 | self.y = y 8 | 9 | def dist_to(self, other_point: Point) -> float: 10 | # TODO-0: скопируйте реализацию из предыдущей задачи 11 | ... 12 | 13 | 14 | # Дан список из произвольного количества точек: 15 | points = [Point(2, 7), Point(12, 7), Point(5, -2), Point(10, -16), Point(-12, 0)] 16 | 17 | # TODO-1: найдите точку наиболее удаленную от начала координат и выведите ее координаты 18 | 19 | print("Координаты наиболее удаленной точки = ", ...) 20 | -------------------------------------------------------------------------------- /Module1/practice/01-points/05_line.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | class Point: 5 | def __init__(self, x: int, y: int): 6 | self.x = x 7 | self.y = y 8 | 9 | def dist_to(self, other_point: Point) -> float: 10 | # TODO-0: скопируйте реализацию из предыдущей задачи 11 | ... 12 | 13 | 14 | # Ломаная линия задана произвольным количеством последовательных точек 15 | points = [Point(2, 4), Point(7, 5), Point(5, -2), Point(0, 6), Point(-12, 0)] 16 | 17 | # TODO: Найдите длину ломаной линии 18 | 19 | print("Длина ломаной линии = ", ...) 20 | -------------------------------------------------------------------------------- /Module1/practice/01-points/06_color_points[add].py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | class Point: 5 | def __init__(self, x: int, y: int, color: str): 6 | self.x = x 7 | self.y = y 8 | self.color = ... 9 | 10 | def dist_to(self, other_point: Point) -> float: 11 | ... 12 | 13 | 14 | # Дан список точек нарисованных красным(red) и зеленым(green) цветами 15 | # Точно известно, что точек каждого цвета ровно три, но порядок точек в списке и значение координат произвольные 16 | points = [ 17 | Point(2, 7, "red"), 18 | Point(12, 7, "green"), 19 | Point(5, -2, "red"), 20 | Point(4, 8, "green"), 21 | Point(10, -2, "green"), 22 | Point(-12, 0, "red") 23 | ] 24 | # Все точки одного цвета соединены линиями и образуют треугольник 25 | 26 | # TODO-1: доработайте конструктор class Point для хранения цвета точки 27 | # TODO-2: реализуйте метод dist_to(), для расчета расстояния между точками 28 | # TODO-3: вычислите площади треугольников образованных точками разных цветов 29 | 30 | # your core here... 31 | 32 | print("Площадь красного треугольника = ", ...) 33 | print("Площадь зеленого треугольника = ", ...) 34 | -------------------------------------------------------------------------------- /Module1/practice/02-peoples/00_people.py: -------------------------------------------------------------------------------- 1 | class People: 2 | def __init__(self, name: str, surname: str, age: int): 3 | self.name = name 4 | self.surname = surname 5 | self.age = age 6 | 7 | def full_name_v1(self) -> str: 8 | return f"{self.surname} {self.name}" 9 | 10 | def full_name_v2(self) -> None: 11 | print(f"{self.surname} {self.name}") 12 | 13 | 14 | # Создадим двух человек: 15 | people1 = People("Иван", "Уткин", 27) 16 | people2 = People("Алексей", "Перов", 35) 17 | 18 | # Выведем данные о человеке, используя оба варианта методов: 19 | 20 | ... 21 | 22 | # Какой метод предпочтительнее? 23 | -------------------------------------------------------------------------------- /Module1/practice/02-peoples/01_peoples_task.py: -------------------------------------------------------------------------------- 1 | class People: 2 | def __init__(self, name: str, surname: str, age: int): 3 | self.name = name 4 | self.surname = surname 5 | self.age = age 6 | 7 | def full_name(self) -> str: 8 | return f"{self.surname} {self.name}" 9 | 10 | 11 | # Совет: не забывайте, вы можете добавлять в список и удалять из него любых людей, это просто пример! 12 | peoples = [ 13 | People("Иван", "Уткин", 27), 14 | People("Алена", "Перова", 32), 15 | People("Василий", "Быстров", 55), 16 | People("Ольга", "Подгорная", 32), 17 | ] 18 | 19 | # TODO-1: найдите самого молодого человека и выведите его Фамилию и Имя 20 | # Примечание: Если самых молодых несколько, выведите всех 21 | 22 | # TODO-2: найдите всех одногодок и выведите их Фамилии и Имена 23 | # Примечание: Если одногодок нет, выведите сообщение "одногодок нет" 24 | -------------------------------------------------------------------------------- /Module1/practice/03-figures[add]/00_figures_triangle.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def __init__(self, x, y): 3 | self.x = x 4 | self.y = y 5 | 6 | def dist_to(self, other_point): 7 | return ((self.x - other_point.x) ** 2 + (self.y - other_point.y) ** 2) ** 0.5 8 | 9 | 10 | class Triangle: 11 | def __init__(self, p1, p2, p3): 12 | self.point1 = p1 13 | self.point2 = p2 14 | self.point3 = p3 15 | 16 | def perimeter(self): 17 | # Находим длины сторон треугольника: 18 | a = self.point1.dist_to(self.point2) 19 | b = self.point2.dist_to(self.point3) 20 | c = self.point1.dist_to(self.point3) 21 | return a + b + c 22 | 23 | def area(self): 24 | # Находим длины сторон треугольника: 25 | a = self.point1.dist_to(self.point2) 26 | b = self.point2.dist_to(self.point3) 27 | c = self.point1.dist_to(self.point3) 28 | # Полу-периметр: 29 | half_p = (a + b + c) / 2 30 | # Для нахождения площади, используйте формулу Герона 31 | return (half_p * (half_p - a) * (half_p - b) * (half_p - c)) ** 0.5 32 | 33 | 34 | # Треугольник задан координатами трех точек 35 | triangle1 = Triangle(Point(2, 4), Point(12, 8), Point(-2, 0)) 36 | 37 | # Находим площадь и периметр треугольника: 38 | print("Периметр треугольника = ", triangle1.perimeter()) 39 | print("Площадь треугольника = ", triangle1.area()) 40 | -------------------------------------------------------------------------------- /Module1/practice/03-figures[add]/01_figures_circles.py: -------------------------------------------------------------------------------- 1 | class Circle: 2 | def __init__(self, center_coords, radius): 3 | ... 4 | 5 | def length(self): 6 | """ 7 | :return: длину окружности 8 | """ 9 | # TODO-1: реализуйте метод 10 | ... 11 | 12 | def area(self): 13 | """ 14 | :return: площадь окружности 15 | """ 16 | # TODO-2: реализуйте метод 17 | ... 18 | 19 | 20 | # Окружности заданы координатами центров и радиусами 21 | circle1 = Circle((6, -8), 5) 22 | circle2 = Circle((2, 4), 4) 23 | 24 | print(f"Длина окружности радиусом {...} = {...}") 25 | print(f"Длина окружности радиусом {...} = {...}") 26 | 27 | print(f"Площадь окружности радиусом {...} = {...}") 28 | print(f"Площадь окружности радиусом {...} = {...}") -------------------------------------------------------------------------------- /Module1/practice/03-figures[add]/02_figures_point_in_circle.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def __init__(self, x, y): 3 | self.x = x 4 | self.y = y 5 | 6 | def dist_to(self, other_point): 7 | return ((self.x - other_point.x) ** 2 + (self.y - other_point.y) ** 2) ** 0.5 8 | 9 | 10 | class Circle: 11 | def __init__(self, center_coords, radius): 12 | ... 13 | 14 | def point_into(self, point): 15 | """ 16 | Проверяет лежит ли точка point внутри текущей окружности 17 | :return: True/False 18 | """ 19 | # TODO-1: реализуйте метод 20 | ... 21 | 22 | 23 | # Окружность задана координатами центра и радиусом: 24 | circle1 = Circle((6, -8), 10) 25 | # И дана точка: 26 | point1 = Point(7, 1) 27 | 28 | if circle1.point_into(point1): 29 | print(f"Точка лежит внутри окружности") 30 | else: 31 | print("Точка НЕ лежит внутри окружности") -------------------------------------------------------------------------------- /Module1/practice/03-figures[add]/03_figures_circles_intersect.py: -------------------------------------------------------------------------------- 1 | class Circle: 2 | def __init__(self, center_coords, radius): 3 | ... 4 | 5 | def intersect(self, other_circle): 6 | """ 7 | Проверяет пересекается ли текущая окружность с other_circle 8 | :return: True/False 9 | """ 10 | # TODO-1: реализуйте метод 11 | ... 12 | 13 | 14 | # Окружности заданы координатами центров и радиусами 15 | circle1 = Circle((6, -8), 5) 16 | circle2 = Circle((2, 4), 4) 17 | 18 | if circle1.intersect(circle2): 19 | print("Окружности пересекаются") 20 | else: 21 | print("Окружности НЕ пересекаются") 22 | -------------------------------------------------------------------------------- /Module1/practice/03-figures[add]/04_figures[add].py: -------------------------------------------------------------------------------- 1 | # Используя классы треугольника и окружности из предыдущих задач 2 | # создайте список с произвольным набором фигур 3 | # Найдите и выведите фигуры с наибольшей площадью 4 | 5 | -------------------------------------------------------------------------------- /Module10/practice/Fraction/01_simplification_fraction.py: -------------------------------------------------------------------------------- 1 | # Задание "Упрощение дроби" 2 | 3 | def simplificator(fraction): 4 | pass 5 | 6 | # Простые дроби заданы в виде строки формата: целая_часть числитель/знаменатель 7 | # целая_часть может отсутствовать, числитель и знаменатель всегда присутствуют 8 | # если целая часть присутствует, то всегда отделяется от дробной пробелом 9 | # дроби могут быть отрицательными или положительными 10 | # Примеры дробей 11 | fraction1 = "3 12/15" 12 | fraction2 = "-1 11/6" 13 | fraction3 = "2/4" 14 | fraction4 = "-5/4" 15 | 16 | # TODO: Задание: Напишите функцию simplificator, которая возвращает дробь в упрощенном виде с выделением целой части 17 | simplificator("3 12/15") # --> 3 4/5 18 | simplificator("-1 11/6") # --> -2 5/6 19 | simplificator("2/4") # --> 1/2 20 | simplificator("-5/4") # --> -1 1/4 21 | 22 | # Подсказки: смотри файлы helpers/parse_fraction.py и helpers/lcmp_gcd.py 23 | -------------------------------------------------------------------------------- /Module10/practice/Fraction/02_task_Fraction_part1.py: -------------------------------------------------------------------------------- 1 | # Задание "Простые дроби" 2 | import math 3 | 4 | 5 | class Fraction: 6 | def __init__(self, raw_fraction): # Дробь в конструктор передается в виде строки 7 | # А мы храним дробь в виде 8 | self.numerator = ... # числителя 9 | self.denominator = ... # знаменателя 10 | 11 | def __str__(self): 12 | """ 13 | Возвращает строковое представление в формате: <Целая часть> <числитель>/<знаменатель> 14 | Пример: "-3 5/7" 15 | """ 16 | 17 | return f"..." 18 | 19 | 20 | # Простые дроби заданы в виде строки 21 | 22 | # Конструктор принимает простую дробь в виде строки формата: <Целая часть> <числитель>/<знаменатель> 23 | # целая_часть может отсутствовать, числитель и знаменатель всегда присутствуют 24 | # дроби могут быть отрицательными или положительными 25 | f1 = Fraction("3 12/15") 26 | f2 = Fraction("-1 11/6") 27 | f3 = Fraction("2/4") 28 | f4 = Fraction("-5/4") 29 | 30 | # TODO: Задание: реализуйте class Fraction, который выводит дробь в упрощенном виде с выделением целой части 31 | print(f1) # 3 4/5 32 | print(f2) # -2 5/6 33 | print(f3) # 1/2 34 | print(f4) # -1 1/4 35 | -------------------------------------------------------------------------------- /Module10/practice/Fraction/03_task_Fraction_part2.py: -------------------------------------------------------------------------------- 1 | # Задание "Простые дроби" 2 | 3 | class Fraction: 4 | def __init__(self, raw_fraction): 5 | ... 6 | # TODO: сюда копируем класс Дроби из предыдущей задачи 7 | 8 | 9 | f1 = Fraction("3 12/15") 10 | f2 = Fraction("-1 11/6") 11 | f3 = Fraction("2/4") 12 | f4 = Fraction("-3/4") 13 | 14 | # TODO: Задание: реализуйте операции с дробями 15 | # Сложение 16 | f_sum = f1 + f2 17 | print(f"{f1} + {f2} = {f_sum}") 18 | # Вычитание 19 | f_sub = f3 - f4 20 | print(f"{f3} + {f4} = {f_sub}") 21 | # Умножение 22 | f_mult = f3 * f4 23 | print(f"{f3} * {f4} = {f_mult}") 24 | 25 | -------------------------------------------------------------------------------- /Module10/practice/Fraction/04_task_Fraction_part3.py: -------------------------------------------------------------------------------- 1 | # Задание "Простые дроби" 2 | 3 | class Fraction: 4 | def __init__(self, raw_fraction): 5 | ... 6 | # TODO: сюда копируем класс Дроби из предыдущей задачи 7 | 8 | 9 | f1 = Fraction("3 12/15") 10 | f2 = Fraction("-1 11/6") 11 | 12 | # TODO: Задание: реализуйте операции с дробями 13 | # Сравнение (> < ==) 14 | if f1 > f2: 15 | print(f"{f1} > {f2}") 16 | elif f1 < f2: 17 | print(f"{f1} < {f2}") 18 | else: 19 | print(f"{f1} = {f2}") 20 | 21 | -------------------------------------------------------------------------------- /Module10/practice/Fraction/05_task_Fraction_part4.py: -------------------------------------------------------------------------------- 1 | # Задание "Простые дроби" 2 | 3 | class Fraction: 4 | pass 5 | # TODO: сюда копируем класс Дроби из предыдущей задачи 6 | 7 | 8 | f1 = Fraction("3 12/15") 9 | f2 = Fraction("-1 11/6") 10 | f3 = Fraction("2/4") 11 | f4 = Fraction("-3/4") 12 | 13 | # TODO: Задание: реализуйте cложение дроби с целым(int) числом 14 | f_sum2 = f1 + 2 15 | print(f"{f1} + {2} = {f_sum2}") 16 | f_sum3 = 2 + f1 17 | print(f"{2} + {f1} = {f_sum2}") 18 | 19 | -------------------------------------------------------------------------------- /Module10/practice/IterInt/01_task_IterInt.py: -------------------------------------------------------------------------------- 1 | # Разработать класс IterInt, который наследует функциональность стандартного типа int, но добавляет 2 | # возможность итерировать по цифрам числа 3 | 4 | class IterInt(int): 5 | pass 6 | 7 | 8 | n = IterInt(12346) 9 | 10 | for digit in n: 11 | print("digit = ", digit) 12 | 13 | # Выведет: 14 | # digit = 1 15 | # digit = 2 16 | # digit = 3 17 | # digit = 4 18 | # digit = 6 19 | -------------------------------------------------------------------------------- /Module10/practice/helpers/lcmp_gcd.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def lcm(a, b): 4 | return abs(a*b) // math.gcd(a, b) 5 | 6 | # Наибольший общий делитель(greatest common denominator) gcd 7 | print("gcd") 8 | print(math.gcd(15, 5)) 9 | print(math.gcd(12, 14)) 10 | print(math.gcd(7, 12)) 11 | 12 | # Наименьшее общее кратное(least common multiple) lcm 13 | print("lcm") 14 | print(lcm(15, 5)) 15 | print(lcm(12, 14)) 16 | print(lcm(4, 12)) 17 | -------------------------------------------------------------------------------- /Module10/practice/helpers/parse_fraction.py: -------------------------------------------------------------------------------- 1 | def parse_fraction(raw_fraction: str): 2 | """ 3 | Извлекает из строки элементы дроби: целую часть(whole), числитель(numerator) и знаменатель(denominator). 4 | Также определяет знак дроби(sign) +/- 5 | """ 6 | sign = 1 7 | if raw_fraction.startswith("-"): 8 | sign = -1 9 | raw_fraction = raw_fraction[1:] 10 | pair = raw_fraction.split() 11 | whole = 0 12 | if len(pair) == 2: 13 | whole = int(pair[0]) 14 | raw_fraction = pair[-1] 15 | pair = raw_fraction.split('/') 16 | numerator = int(pair[0]) 17 | denominator = int(pair[1]) 18 | return {"sign": sign, "whole": whole, "numerator": numerator, "denominator": denominator} 19 | 20 | 21 | print(parse_fraction("-2 4/5")) 22 | print(parse_fraction("-7/8")) 23 | print(parse_fraction("3/8")) 24 | print(parse_fraction("7 3/8")) -------------------------------------------------------------------------------- /Module2/home_works/backpack_hw.py: -------------------------------------------------------------------------------- 1 | class Item: 2 | # TODO-0: копируем реализацию всех методов из практики или дописываем самостоятельно 3 | def __init__(self, name, weight, cost): 4 | ... 5 | 6 | def show(self): 7 | ... 8 | 9 | 10 | class BackPack: # рюкзак 11 | # TODO-0: копируем реализацию всех методов из практики или дописываем самостоятельно 12 | def __init__(self, max_weight: float): 13 | ... 14 | 15 | def add_item(self, item: Item) -> None: 16 | """ 17 | Добавляет предмет(item) в этот рюкзак 18 | """ 19 | ... 20 | 21 | def show_items(self) -> None: 22 | """ 23 | Вывод все предметы, содержащиеся в рюкзаке в виде нумерованного списка 24 | """ 25 | ... 26 | 27 | 28 | # Создаем рюкзак, указываем максимальный вес 29 | backpack = BackPack(max_weight=...) 30 | 31 | # TODO-1: Создаем 5-8 предметов и добавляем их в рюкзак 32 | ... 33 | 34 | # TODO-2: В рюкзаке найдите самый тяжелый предмет и выведите его на экран 35 | # поиск предмета реализуйте в виде метода .max_weight() 36 | 37 | # TODO-3: В рюкзаке найдите самый ценный предмет и выведите его на экран 38 | # ценным предметом, считать предмет, с самым высоким значение цены на единицу веса 39 | # поиск предмета реализуйте в виде метода .max_valuable() 40 | -------------------------------------------------------------------------------- /Module2/practice/backpack/01_Item.py: -------------------------------------------------------------------------------- 1 | class Item: 2 | def __init__(self, name: str, weight: float, cost: int): 3 | self.name = ... # Название предмета 4 | self.weight = ... # Вес предмета, в килограммах 5 | self.cost = ... # Цена предмета, пусть будет, в рублях 6 | 7 | 8 | def show_item(item: Item) -> str: 9 | """ 10 | Возвращает строковое представление объекта Item 11 | """ 12 | return f"{item.name} вес:{item.weight} цена:{item.cost}" 13 | 14 | 15 | # TODO-1: Дополните конструктор класса Item 16 | item1 = Item("Гиря", 25, 500) 17 | item2 = Item("Арбуз", 4, 300) 18 | item3 = Item("Ноутбук", 2.5, 22500) 19 | item4 = Item("Кот", 0.5, 250) 20 | 21 | # TODO-2: запустите программу, посмотрите результаты функции show_item() 22 | print(show_item(item1)) 23 | print(show_item(item2)) 24 | print(show_item(item3)) 25 | print(show_item(item4)) 26 | 27 | # TODO-3: сделайте функцию show_item(), методом show() класса Item 28 | # print(item1.show()) 29 | # print(item2.show()) 30 | # print(item3.show()) 31 | # print(item4.show()) 32 | 33 | # Помещаем все объекты item в список: 34 | items = [item1, item2, item3, item4] 35 | # TODO-4: Выведите элементы в виде нумерованного списка, при выводе используйте метод .show() 36 | for item in items: 37 | ... 38 | -------------------------------------------------------------------------------- /Module2/practice/backpack/02_backpack_par1.py: -------------------------------------------------------------------------------- 1 | class Item: 2 | ... 3 | # TODO: сюда копируем реализацию класса из предыдущего задания 4 | 5 | 6 | class BackPack: # рюкзак 7 | def __init__(self): 8 | self.items = [] # Предметы, которые хранятся в рюкзаке 9 | 10 | def add_item(self, item: Item) -> None: 11 | """ 12 | Добавляет предмет(item) в этот рюкзак 13 | """ 14 | # TODO: реализуйте метод 15 | 16 | def show_items(self) -> None: 17 | """ 18 | Выводит(print'ом) все предметы, содержащиеся в рюкзаке в виде нумерованного списка 19 | """ 20 | # TODO: реализуйте метод 21 | 22 | 23 | # Создаем предметы 24 | item1 = Item("Гиря", 25, 500) 25 | item2 = Item("Арбуз", 4, 300) 26 | 27 | # Создаем пустой рюкзак 28 | backpack = BackPack() 29 | 30 | # Добавляем пару предметов в рюкзак 31 | backpack.add_item(item1) 32 | backpack.add_item(item2) 33 | 34 | # Выводим все предметы в рюкзаке 35 | backpack.show_items() 36 | -------------------------------------------------------------------------------- /Module2/practice/backpack/03_backpack_part2.py: -------------------------------------------------------------------------------- 1 | class Item: 2 | ... 3 | # TODO: сюда копируем реализацию класса из предыдущего задания 4 | 5 | 6 | class BackPack: # рюкзак 7 | ... 8 | 9 | # TODO: сюда копируем реализацию класса из предыдущего задания 10 | # TODO: добавьте новое свойство .max_weight - максимальный суммарный вес предметов, которые можно положить в рюкзак 11 | 12 | def sum_weight(self) -> float: 13 | """ 14 | Возвращает суммарный вес всех предметов в рюкзаке 15 | """ 16 | # TODO: реализуйте метод 17 | 18 | def sum_cost(self) -> int: 19 | """ 20 | Возвращает суммарную стоимость всех предметов в рюкзаке 21 | """ 22 | # TODO: реализуйте метод 23 | 24 | 25 | # Создаем предметы 26 | item1 = Item("Гиря", 25, 500) 27 | item2 = Item("Арбуз", 4, 300) 28 | item3 = Item("Ноутбук", 2.5, 22500) 29 | item4 = Item("Кот", 0.5, 250) 30 | 31 | # Создаем пустой рюкзак и указываем его вместимость(в кг) 32 | backpack = BackPack(max_weight=30) 33 | 34 | # Пытаемся добавлять предметы в рюкзак 35 | backpack.add_item(item1) 36 | backpack.add_item(item2) 37 | backpack.add_item(item3) 38 | backpack.add_item(item4) 39 | # TODO: Если предмет не помещается в рюкзак по весу - вывести сообщение "Предмет {name} слишком тяжелый", 40 | # и сам предмет не должен быть добавлен в рюкзак. 41 | # Если предмет помещает, то добавляем его в рюкзак. 42 | 43 | # Выводим все предметы в рюкзаке 44 | backpack.show_items() 45 | -------------------------------------------------------------------------------- /Module2/practice/backpack/04_backpack_part3.py: -------------------------------------------------------------------------------- 1 | class Item: 2 | ... 3 | # TODO: сюда копируем реализацию класса из предыдущего задания 4 | 5 | 6 | class BackPack: # рюкзак 7 | ... 8 | 9 | # TODO: сюда копируем реализацию класса из предыдущего задания 10 | 11 | def add_items(self, items: list[Item]): 12 | """ 13 | :param items: Список вещей(объектов класса Item) 14 | """ 15 | # TODO: реализуйте метод так, чтобы из переданного списка предметов выбиралось и помещалось в рюкзак, 16 | # максимальное количество, с учетом ограничения общего веса в рюкзаке. Т.е. берем самые легкие предметы. 17 | 18 | 19 | # Создаем предметы 20 | items = [ 21 | Item("Гиря", 25, 500), 22 | Item("Арбуз", 4, 300), 23 | Item("Ноутбук", 2.5, 22500), 24 | Item("Кот", 0.5, 250), 25 | Item("Трос", 3, 150), 26 | ] 27 | 28 | # Создаем пустой рюкзак и указываем его вместимость(в кг) 29 | backpack = BackPack(max_weight=7) 30 | 31 | # Пытаемся добавлять максимальное кол-во предметов в рюкзак 32 | backpack.add_items(items) 33 | 34 | # Выводим все предметы в рюкзаке 35 | backpack.show_items() 36 | -------------------------------------------------------------------------------- /Module3/examples/1_overloading.py: -------------------------------------------------------------------------------- 1 | # ============================= 2 | # Перегрузка операторов 3 | # ============================= 4 | 5 | # Имена методов, начинающиеся и заканчивающиеся двумя символами подчеркивания __X__, имеют специальное назначение. 6 | # Такие методы вызываются автоматически, когда объект участвует в соответствующей операции. 7 | # Возвращаемое значение метода становится результатом соответствующей операции. 8 | 9 | 10 | class Vector: 11 | def __init__(self, pos): 12 | self.x = pos[0] 13 | self.y = pos[1] 14 | 15 | # Перегружаем оператор + 16 | def __add__(self, other): 17 | return Vector((self.x + other.x, self.y + other.y)) 18 | 19 | def as_point(self): 20 | return self.x, self.y 21 | 22 | # Формируем удобное отображение объекта при выводе функцией print() 23 | def __str__(self): 24 | return "V(x:{} y:{})".format(self.x, self.y) 25 | 26 | 27 | # Создаем экземпляры класса (объекты) 28 | v1 = Vector((10, 15)) 29 | v2 = Vector((12, 10)) 30 | 31 | # Наши объекты участвуют в операции сложения (+) 32 | v3 = v1 + v2 33 | # На самом деле это работает так: 34 | # v3 = v1.__add__(v2) 35 | # Благодаря перегрузке, мы можем использовать более удобную и привычную запись: v3 = v1 + v2 36 | 37 | # Выводим результат 38 | print('v3 = ', v3) 39 | # Функция print() для получения строки для вывода вызывает методы __str__() 40 | print('v3 + v3 =', v3 + v3) 41 | 42 | # Список ВСЕХ magic-методов см. тут: http://pythonworld.ru/osnovy/peregruzka-operatorov.html 43 | -------------------------------------------------------------------------------- /Module3/examples/2_polymorphism.py: -------------------------------------------------------------------------------- 1 | # Полиморфизм - разное поведение одного и того же метода в разных классах. 2 | # Например, мы можем сложить два числа, и можем сложить две строки. 3 | # При этом получим разный результат, так как числа и строки являются разными классами. 4 | 5 | print(2 + 4) 6 | print('2' + '4') 7 | print((2, 4)+(2, 4)) -------------------------------------------------------------------------------- /Module3/home_work/01_Money_result.py: -------------------------------------------------------------------------------- 1 | class Money: 2 | pass 3 | # TODO: your code here 4 | -------------------------------------------------------------------------------- /Module3/home_work/01_Money_task.md: -------------------------------------------------------------------------------- 1 | ### class Money 2 | 3 | Напишите класс для работы с денежными суммами. 4 | 5 | Реализовать: 6 | 7 | 8 | 9 | * сложение 10 | * вычитание 11 | * умножение на целое число 12 | * сравнение (больше, меньше, равно, не равно) 13 | 14 | денежной суммы. При всех операциях, сумма должна преобразовываться к сумме с минимальным количеством копеек. 15 | 16 | Примеры: 17 | 18 | 19 | ``` 20 | # Создаем сумму из 20 рублей и 120 копеек 21 | money_sum1 = Money(20, 120) 22 | # Выводим сумму, с учетом минимального кол-ва копеек 23 | print(money_sum1) # 21руб 20коп 24 | ``` 25 | 26 | 27 | 28 | ``` 29 | # Создаем две денежные суммы 30 | money_sum1 = Money(20, 60) 31 | money_sum2 = Money(10, 45) 32 | 33 | # Складываем суммы 34 | money_result = money_sum1 + money_sum2 35 | print(money_result) # 31руб 5коп 36 | ``` 37 | 38 | 39 | **Примечание**: список всех методов для перегрузки операций [тут](https://pythonworld.ru/osnovy/peregruzka-operatorov.html). 40 | 41 | 42 | #### Доп.задание 43 | 44 | Добавьте операцию - вычисление процент от суммы. 45 | 46 | **Пример**: 47 | 48 | 49 | ``` 50 | # Создаем две денежные суммы 51 | money_sum1 = Money(20, 60) 52 | 53 | # Находим 21% от суммы 54 | percent_sum = money_sum1 % 21 55 | 56 | print(percent_sum) # 4руб 33коп 57 | ``` 58 | 59 | 60 | **Пояснение**: % (процет от суммы) - должна являться новая денежная сумма. После вычисления процента, используем округление (функция round()) 61 | 62 | 63 | ### Конвертация валют 64 | 65 | Доработайте класс Money, добавив ему метод .convert(), для конвертации суммы в рублях в евро и доллары. Актуальные значения можно взять, сделав запрос на: [https://www.cbr-xml-daily.ru/daily_json.js](https://www.cbr-xml-daily.ru/daily_json.js) 66 | 67 | #### Отправка запроса на url-адрес 68 | 69 | 70 | ``` 71 | import urllib.request 72 | 73 | data = urllib.request.urlopen(url).read() 74 | ``` 75 | 76 | 77 | , где **url** - адрес сайта, на который отправляете запрос. 78 | 79 | В переменную **data** получите ответ сайта. 80 | 81 | Для преобразования ответа из json-формата используйте функцию: 82 | ``` 83 | data_dict = json.loads(data) 84 | ``` 85 | Модуля json -------------------------------------------------------------------------------- /Module3/home_work/02_Vector_result.py: -------------------------------------------------------------------------------- 1 | # Сюда отправляем решение задачи "Вектор" 2 | # Само задание в файле 01_Vector_task.md 3 | 4 | class Vector: 5 | pass 6 | -------------------------------------------------------------------------------- /Module3/home_work/02_Vector_task.md: -------------------------------------------------------------------------------- 1 | 2 | ## Задания на дом 3 | 4 | Напишите класс для математического вектора. 5 | 6 | 7 | 8 | 9 | **Вектор**— направленный отрезок прямой. Вектор задается двумя числами. 10 | 11 | 12 | ### Операции с векторами 13 | 14 | **Сложение векторов:** 15 | 16 | 17 | 18 | 19 | **Вычитание векторов:** 20 | 21 | 22 | 23 | 24 | **Умножение вектора на скаляр(число):** 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Module3/home_work/03_Roman_numbers.py: -------------------------------------------------------------------------------- 1 | # Задание: 2 | # Напишите класс для работы с римскими цифрами. 3 | # Подробнее про Римские цифры тут: http://graecolatini.bsu.by/htm-different/num-converter-roman.htm 4 | class Roman: 5 | def __init__(self, number): 6 | pass 7 | 8 | 9 | # Реализуйте операции: 10 | # Сложение 11 | # Вычитание 12 | # Умножение 13 | # Целочисленное деление 14 | # Сравнение (> < == !=) 15 | # Пример: 16 | n1 = Roman(10) 17 | n2 = Roman(14) 18 | print(n1) # X 19 | print(n2) # XIV 20 | n3 = n1 + n2 21 | print(n3) # XXIV 22 | n3 *= 2 23 | print(n3) # XLVIII 24 | 25 | # ограничение: 4-значные числа. 26 | # Алгоритм 27 | # 1. Выделяем (если есть) количество целых тысяч. 28 | # Полученное значение позволить сгенерировать строку с n количеством «M» (читаем, n*1000). 29 | # Пример: 2012 после первого пункта даст «MM» 30 | # 31 | # 2. Получаем остаток после деления на 1000, чтобы выделить в дальнейшем следующие значения. 32 | # 33 | # 3. Выделяем (если возможно), целые 500. При этом учитываем что если полученное значение равно 4 (5+4=9), 34 | # то следует записывать как значение 1000-100, что в римский СС равнозначно «CM». 35 | # Пример: 1887 после этого пункта даст нам «MD». 36 | # 1945 соответственно «MCM». 37 | # 38 | # 4. Получаем остаток от деления на 500. 39 | # 40 | # 5. Делим на 100 чтобы выделить целые сотни и складываем к предыдущему результату. Учитываем что если получили 4, 41 | # что равнозначно 400, то записываем как 500-100, то есть «CD». 42 | # Пример: 1709 даст после этого шага «MDCCC». 43 | # 44 | # 6. Получаем остаток от деления на 100. 45 | # 46 | # 7. Выделяем из него целые полсотни. Если значение будет равно 4 (то есть 90), то записываем как 100-10, 47 | # что равно «XC». Иначе прибавляем к строке «L» 48 | # Пример: 1986 после всего выдаст нам «MCML». 49 | # 50 | # 8. Выделяем остаток от 50. 51 | # 52 | # 9. Выделяем целое количество десятков и складываем к строке n раз символ «X». 53 | # При этом учитываем что 40 пишется как 50-10, то есть «XL». 54 | # Пример: 1986 после всего выдаст нам «MCMLXXX». 55 | # 56 | # 10. Получаем остаток от деления на 10. Этот шаг отличается от других тем, 57 | # что можно сразу приравнять остаток к его эквиваленту. 1=I, 7=VII и так далее. 58 | # 59 | # После перебора числа этим алгоритмом мы получаем примерно такое: 60 | # 2012 == MMXII 61 | -------------------------------------------------------------------------------- /Module3/home_work/img/vector-cartesian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module3/home_work/img/vector-cartesian.png -------------------------------------------------------------------------------- /Module3/home_work/img/vector_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module3/home_work/img/vector_add.png -------------------------------------------------------------------------------- /Module3/home_work/img/vector_mult.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module3/home_work/img/vector_mult.jpg -------------------------------------------------------------------------------- /Module3/home_work/img/vector_sub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module3/home_work/img/vector_sub.png -------------------------------------------------------------------------------- /Module3/home_work/tests/test_Money.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from ... import Money 3 | 4 | 5 | def test_create_and_show(): 6 | money1 = Money(12, 35) 7 | money2 = Money(20, 120) 8 | money3 = Money(0, 400) 9 | money4 = Money(1, 405) 10 | assert str(money1) == "12руб 35коп" 11 | assert str(money2) == "21руб 20коп" 12 | assert str(money3) == "4руб 0коп" 13 | assert str(money4) == "5руб 5коп" 14 | 15 | 16 | def test_add(): 17 | money1 = Money(12, 35) 18 | money2 = Money(20, 120) 19 | money3 = money1 + money2 20 | assert str(money1) == "12руб 35коп" 21 | assert str(money2) == "21руб 20коп" 22 | assert str(money3) == "33руб 55коп" 23 | assert isinstance(money3, Money) 24 | money4 = Money(12, 35) 25 | money5 = Money(20, 90) 26 | money6 = money4 + money5 27 | assert str(money4) == "12руб 35коп" 28 | assert str(money5) == "20руб 90коп" 29 | assert str(money6) == "33руб 25коп" 30 | assert isinstance(money3, Money) 31 | 32 | 33 | def test_sub(): 34 | money1 = Money(22, 35) 35 | money2 = Money(20, 120) 36 | money3 = money1 - money2 37 | assert str(money1) == "22руб 35коп" 38 | assert str(money2) == "21руб 20коп" 39 | assert str(money3) == "1руб 15коп" 40 | assert isinstance(money3, Money) 41 | money4 = Money(12, 35) 42 | money5 = Money(20, 90) 43 | money6 = money4 - money5 44 | assert str(money4) == "12руб 35коп" 45 | assert str(money5) == "20руб 90коп" 46 | assert str(money6) == "-8руб 55коп" 47 | assert isinstance(money3, Money) 48 | money7 = Money(20, 90) 49 | money8 = Money(20, 90) 50 | money9 = money7 - money8 51 | assert str(money9) == "0руб 0коп" 52 | 53 | 54 | def test_mul(): 55 | money1 = Money(22, 55) 56 | money2 = money1 * 2 57 | assert str(money1) == "22руб 55коп" 58 | assert str(money2) == "45руб 10коп" 59 | assert isinstance(money2, Money) 60 | money3 = Money(4, 105) 61 | money4 = money3 * 3 62 | assert str(money3) == "5руб 5коп" 63 | assert str(money4) == "15руб 15коп" 64 | assert isinstance(money4, Money) 65 | 66 | 67 | def test_gt(): 68 | money1 = Money(12, 35) 69 | money2 = Money(20, 120) 70 | assert money2 > money1 71 | money3 = Money(2, 435) 72 | money4 = Money(2, 120) 73 | assert money3 > money4 74 | 75 | 76 | def test_lt(): 77 | money1 = Money(12, 35) 78 | money2 = Money(20, 120) 79 | assert money1 < money2 80 | money3 = Money(2, 435) 81 | money4 = Money(2, 120) 82 | assert money4 < money3 83 | assert money4 < money2 84 | -------------------------------------------------------------------------------- /Module3/practice/books/00_book_author.py: -------------------------------------------------------------------------------- 1 | class Author: 2 | def __init__(self, name: str, surname: str): 3 | self.name = name 4 | self.surname = surname 5 | 6 | 7 | class Book: 8 | def __init__(self, name: str, author: Author, year: int, pages: int): 9 | self.name = name 10 | self.author = author 11 | self.year = year 12 | self.pages = pages 13 | 14 | 15 | author = Author("Михаил", "Булгаков") 16 | book = Book("Вьюга", author, 1926, 25) 17 | 18 | print(book.author.surname) 19 | -------------------------------------------------------------------------------- /Module3/practice/books/01_book_to_str.py: -------------------------------------------------------------------------------- 1 | class Author: 2 | def __init__(self, name: str, surname: str): 3 | self.name = name 4 | self.surname = surname 5 | 6 | def short_name(self) -> str: 7 | # TODO-1: метод возвращает строку в формате: М.Булгаков 8 | # пояснение: Первую букву имени, фамилию целиком 9 | ... 10 | 11 | 12 | class Book: 13 | def __init__(self, name: str, author: Author, year: int, pages: int): 14 | self.name = name 15 | self.author = author 16 | self.year = year 17 | self.pages = pages 18 | 19 | def to_str(self) -> str: 20 | # TODO-2: метод возвращает строку в формате: "Вьюга" author:М.Булгаков publish:1926 год 21 | # пояснение: Название книги выводим в кавычках(""), у имени автора только первую букву 22 | ... 23 | 24 | 25 | author = Author("Михаил", "Булгаков") 26 | book = Book("Вьюга", author, 1926, 25) 27 | 28 | # TODO-3: Измените имя, фамилию автора и название книги, проверьте, что программа корректно работает с новыми значениями 29 | print(book.to_str()) 30 | -------------------------------------------------------------------------------- /Module3/practice/books/02_books_list.py: -------------------------------------------------------------------------------- 1 | class Author: 2 | def __init__(self, name: str, surname: str): 3 | self.name = name 4 | self.surname = surname 5 | 6 | def short_name(self) -> str: 7 | # TODO-0: скопируйте реализацию метода из предыдущей задачи 8 | ... 9 | 10 | 11 | class Book: 12 | def __init__(self, name: str, author: Author, year: int, pages: int): 13 | self.name = name 14 | self.author = author 15 | self.year = year 16 | self.pages = pages 17 | 18 | def to_str(self) -> str: 19 | # TODO-0: скопируйте реализацию метода из предыдущей задачи 20 | ... 21 | 22 | 23 | author1 = Author("Михаил", "Булгаков") 24 | author2 = Author(name="Стивен", surname="Кинг") 25 | 26 | books_catalog = [ 27 | Book("Вьюга", author1, 1926, 25), 28 | Book("Мастер и Маргарита", author1, 1967, 480), 29 | Book("Собачье сердце", author1, 1987, 352), 30 | Book("Сияние", author2, 2014, 544), 31 | Book("Оно", author2, 1986, 320), 32 | ] 33 | 34 | # TODO-1: Выведите нумерованный список книг, используя для каждой книги ее строковое представление(метод .to_str()) 35 | -------------------------------------------------------------------------------- /Module3/practice/books/03_books_filter.py: -------------------------------------------------------------------------------- 1 | class Author: 2 | def __init__(self, name: str, surname: str): 3 | self.name = name 4 | self.surname = surname 5 | 6 | def short_name(self) -> str: 7 | # TODO-0: скопируйте реализацию метода из предыдущей задачи 8 | ... 9 | 10 | 11 | class Book: 12 | def __init__(self, name: str, author: Author, year: int, pages: int): 13 | self.name = name 14 | self.author = author 15 | self.year = year 16 | self.pages = pages 17 | 18 | def to_str(self) -> str: 19 | # TODO-0: скопируйте реализацию метода из предыдущей задачи 20 | ... 21 | 22 | 23 | author1 = Author("Михаил", "Булгаков") 24 | author2 = Author(name="Стивен", surname="Кинг") 25 | 26 | books_catalog = [ 27 | Book("Вьюга", author1, 1926, 25), 28 | Book("Мастер и Маргарита", author1, 1967, 480), 29 | Book("Собачье сердце", author1, 1987, 352), 30 | Book("Сияние", author2, 2014, 544), 31 | Book("Оно", author2, 1986, 320), 32 | ] 33 | print("Найти все книги по фамилии автора") 34 | surname = input("Фамилия автора: ") 35 | # TODO-1: Выведите нумерованный список книг автора с фамилией surname 36 | # примечание: если книг для автора с указанной фамилией нет - выведите "Книги не найдены" 37 | -------------------------------------------------------------------------------- /Module4/examples/1_types_extension.py: -------------------------------------------------------------------------------- 1 | # ================================ 2 | # Расширение встроенных типов 3 | # ================================ 4 | 5 | 6 | # Расширяем стандартный class dict 7 | class my_dict(dict): 8 | # Добавляем свой метод 9 | def new_method(self): 10 | return "I'm new_method" 11 | 12 | # Добавляем дополнительный функционал к существующему методу 13 | def __setitem__(self, key, value): 14 | print('Setting %r to %r' % (key, value)) 15 | return super().__setitem__(key, value) 16 | 17 | 18 | m_dict = my_dict({1: 2, 2: 3}) 19 | print(m_dict) 20 | 21 | # Данная операция вызывает метод __setitem__ 22 | m_dict["new_key"] = "new_value" 23 | print(m_dict) 24 | 25 | # print(m_dict.keys()) 26 | 27 | print(m_dict.new_method()) 28 | 29 | print("\n***Demo MyList****") 30 | 31 | 32 | class MyList(list): 33 | """ 34 | Список, индексы которого начинатся с 1, а не с 0 35 | """ 36 | def __getitem__(self, offset): 37 | print('(indexing % s at % s)' % (self, offset)) 38 | return list.__getitem__(self, offset - 1) 39 | 40 | x = MyList('abc') # __init__ наследуется из списка 41 | print(x) # __repr__ наследуется из списка 42 | 43 | print(x[1]) # MyList.__getitem__ 44 | print(x[3]) # Изменяет поведение метода суперкласса 45 | 46 | x.append('spam') 47 | print(x) # Атрибуты, унаследованные от суперкласса list 48 | x.reverse() 49 | print(x) 50 | -------------------------------------------------------------------------------- /Module4/examples/2_inheritance.py: -------------------------------------------------------------------------------- 1 | # Наследование подразумевает, что дочерний класс содержит все атрибуты родительского класса, 2 | # при этом некоторые из них могут быть переопределены или добавлены в дочернем. 3 | 4 | 5 | # Рассмотрим два класса 6 | class Student: 7 | def __init__(self, name, surname, birth_date, school, class_room): 8 | self.name = name 9 | self.surname = surname 10 | self.birth_date = birth_date 11 | self.school = school 12 | self._class_room = {'class_num': int(class_room.split()[0]), 13 | 'class_char': class_room.split()[1]} 14 | 15 | @property 16 | def class_room(self): 17 | return "{} {}".format(self._class_room['class_num'], self._class_room['class_char']) 18 | 19 | def next_class(self): 20 | self._class_room['class_num'] += 1 21 | 22 | def get_full_name(self): 23 | return self.name + ' ' + self.surname 24 | 25 | def set_name(self, new_name): 26 | self.name = new_name 27 | 28 | 29 | class Teacher: 30 | def __init__(self, name, surname, birth_date, school, teach_classes): 31 | self.name = name 32 | self.surname = surname 33 | self.birth_date = birth_date 34 | self.school = school 35 | self.teach_classes = list(map(self.convert_class, teach_classes)) 36 | 37 | def convert_class(self, class_room): 38 | """ 39 | ' ' --> {'class_num': , 'class_int': } 40 | """ 41 | return {'class_num': int(class_room.split()[0]), 42 | 'class_char': class_room.split()[1]} 43 | 44 | def get_full_name(self): 45 | return self.name + ' ' + self.surname 46 | 47 | def set_name(self, new_name): 48 | self.name = new_name 49 | 50 | # Эти Классы описывают два различных объекта 51 | # Но часть информации у них общая(атрибуты, методы) 52 | 53 | 54 | # Общую информацию выносим в Класс-предок (родитель) 55 | class People: 56 | def __init__(self, name, surname, birth_date, school): 57 | self.name = name 58 | self.surname = surname 59 | self.birth_date = birth_date 60 | self.school = school 61 | 62 | def get_full_name(self): 63 | return self.name + ' ' + self.surname 64 | 65 | def set_name(self, new_name): 66 | self.name = new_name 67 | 68 | 69 | # Сами классы наследуем 70 | class Student(People): 71 | def __init__(self, name, surname, birth_date, school, class_room): 72 | # Явно вызываем конструктор родительского класса 73 | People.__init__(self, name, surname, birth_date, school) 74 | # Добавляем уникальные атрибуты 75 | self._class_room = {'class_num': int(class_room.split()[0]), 76 | 'class_char': class_room.split()[1]} 77 | 78 | # И уникальные методы 79 | @property 80 | def class_room(self): 81 | return "{} {}".format(self._class_room['class_num'], self._class_room['class_char']) 82 | 83 | def next_class(self): 84 | self._class_room['class_num'] += 1 85 | 86 | 87 | class Teacher(People): 88 | def __init__(self, name, surname, birth_date, school, teach_classes): 89 | People.__init__(self, name, surname, birth_date, school) 90 | self.teach_classes = list(map(self.convert_class, teach_classes)) 91 | 92 | # Уникальный метод Учителя 93 | def convert_class(self, class_room): 94 | """ 95 | ' ' --> {'class_num': , 'class_int': } 96 | """ 97 | return {'class_num': int(class_room.split()[0]), 98 | 'class_char': class_room.split()[1]} 99 | 100 | # Наследование позволяет избежать дублирования и кода 101 | # и повторно использовать уже готовые реализации -------------------------------------------------------------------------------- /Module4/examples/3_iter_rules.py: -------------------------------------------------------------------------------- 1 | # ================================ 2 | # Принципы работы итераторов 3 | # ================================ 4 | 5 | test_list = [1, 2, 3, 4, 'END'] 6 | # Когда вы пишете 7 | for el in test_list: 8 | print(test_list) 9 | 10 | # Python выполняет: 11 | # 1. Вызывает метод __iter__(): test_list.__iter__() 12 | # Метод __iter__() должен вернуть объект, у которого есть метод __next__() 13 | # 2. Цикл for..in каждую итерацию вызывает метод __next__() 14 | # __next__() при каждом вызове возвращает следующий элемент итератора 15 | # 3. Когда элементы итератора заканчиваются, метод __next__() возбуждает исключение StopIteration 16 | # for..in завершает свою работу, когда перехватывает это исключение 17 | 18 | # Проведем обход элементов списка test_list вручную (без цикла) 19 | 20 | print("Итерируем вручную...") 21 | # Получаем объект-итератор 22 | test_list_iter = iter(test_list) 23 | # Функция iter() просто вызывает метод __iter__() 24 | 25 | print(next(test_list_iter)) 26 | print(next(test_list_iter)) 27 | print(next(test_list_iter)) 28 | print(next(test_list_iter)) 29 | print(next(test_list_iter)) 30 | 31 | print(next(test_list_iter)) # Будет возбуждено исключение StopIteration 32 | 33 | 34 | -------------------------------------------------------------------------------- /Module4/examples/4_myIter.py: -------------------------------------------------------------------------------- 1 | # ================================= 2 | # Создание объектов-итераторов 3 | # ================================= 4 | 5 | 6 | class IterObj: 7 | """ 8 | Объект-итератор 9 | """ 10 | def __init__(self, start=0): 11 | self.i = start 12 | # Объект считается итератором - если у него есть метод __next__ 13 | 14 | def __next__(self): 15 | self.i += 1 16 | if self.i <= 5: 17 | return self.i 18 | else: 19 | raise StopIteration 20 | 21 | 22 | class Iter: 23 | """ 24 | Объект, поддерживающий интерфейс итерации 25 | """ 26 | def __init__(self, start=0): 27 | self.start = start - 1 28 | 29 | def __iter__(self): 30 | # Метод __iter__ должен возвращать объект итератор 31 | return IterObj(self.start) 32 | 33 | obj = Iter(start=2) 34 | 35 | for el in obj: 36 | print(el) 37 | 38 | print("Еще раз ...") 39 | for el in obj: 40 | print(el) 41 | 42 | print('sum(obj) -->', sum(obj)) 43 | 44 | # Функция map() возвращает объект-итератор 45 | map_iter = map(int, '123') 46 | 47 | print('next(map_iter) --> ', next(map_iter)) 48 | print('next(map_iter) --> ', next(map_iter)) 49 | 50 | # Цикл for..in продолжает перебор элементов, т.к. map_iter является итератором 51 | for el in map_iter: 52 | print("el in for in -->", el) 53 | 54 | 55 | class Iter2: 56 | def __init__(self, start=0): 57 | self.i = start 58 | 59 | def __iter__(self): 60 | # Метод __iter__ должен возвращать объект-итератор 61 | return self 62 | 63 | def __next__(self): 64 | self.i += 1 65 | if self.i <= 5: 66 | return self.i 67 | else: 68 | raise StopIteration 69 | 70 | 71 | print("Demo Iter2") 72 | obj = Iter2(start=2) 73 | 74 | for el in obj: 75 | print(el) 76 | 77 | print("Еще раз ...") 78 | for el in obj: 79 | print(el) 80 | -------------------------------------------------------------------------------- /Module4/home_work/Currency/01_task_Currency.py: -------------------------------------------------------------------------------- 1 | # Задание: Создать удобную структуру для работы с курсами валют на определенную дату 2 | # Курсы валют будем брать с этого сайта: https://www.cbr-xml-daily.ru/ . 3 | # Нас будут интересовать только курсы доллара и евро. 4 | # Как получить курс по API со стороннего сайта - смотри в helpers/request_currency.py 5 | 6 | class Currency: 7 | def __init__(self, type): 8 | pass 9 | 10 | 11 | usd = Currency("usd") # Создаем валюту "Доллар" 12 | euro = Currency("euro") # Создаем валюту "Евро" 13 | print(usd['02.09.2020']) # ← получение курса доллара на указанную дату 14 | print(euro['12.10.2018']) # ← получение курса евро на указанную дату 15 | print(euro['12.14.2018']) # ← в случае некорректной выбрасываем исключение 16 | -------------------------------------------------------------------------------- /Module4/home_work/helpers/request_currency.py: -------------------------------------------------------------------------------- 1 | from pprint import pprint 2 | # Внимание! Библиотеку requests нужно установить, выполните в консоли команду: 3 | # pip install requests 4 | import requests 5 | 6 | url = 'https://www.cbr-xml-daily.ru/daily_json.js' 7 | # Отправляем запрос на указанный url 8 | response = requests.get(url) 9 | 10 | pprint(response.json()) 11 | 12 | # Если хотим получить курсы на определенную дату, то нужно отправить запрос на : 13 | # url: https://www.cbr-xml-daily.ru/archive/2021/04/07/daily_json.js 14 | # где /2021(год)/04(месяц)/07(день)/ 15 | -------------------------------------------------------------------------------- /Module4/practice/deck/00_task_deck.md: -------------------------------------------------------------------------------- 1 | # Колода карт 2 | 3 | 4 | ### Задание 5 | 6 | Разработать класс для “колоды игральных карт”, который в дальнейшем будет использоваться для карточных консольных мини-игр. 7 | 8 | 9 | ### Колода 10 | 11 | Колода состоит из 52 карт. 12 | 13 | Значения карт: 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A 14 | 15 | Масти карт: ♥ ♦ ♣ ♠ 16 | 17 | Говоря “берем карту сверху колоды” подразумеваем получение карты с начала списка колоды. 18 | 19 | 20 | #### Конструктор колоды 21 | 22 | При создании новой колоды все карты должны находиться в отсортированном порядке - сначала идут все червы от 2-ки до туза, затем буби, крести и пики. 23 | 24 | 25 | #### Методы колоды 26 | 27 | * метод **.shuffle**() - перемешивает колоду, располагая карты в случайном порядке. 28 | * метод .**draw**(x) - возвращает x первых карт из колоды в виде списка, эти карты **убираются** из колоды. 29 | Уточнение: первую карту в списке считаем верхней картой колоды 30 | * метод .**show**() - отображает все карты колоды в формате: \ 31 | deck[12]: 3♥, 4♦, A♣, … \ 32 | где 12 - текущее кол-во карт в колоде. 33 | 34 | 35 | ### Карты 36 | 37 | Карты в колоде тоже должны являться объектами - экземплярами класса Card 38 | 39 | 40 | #### Конструктор карты 41 | 42 | При создании конструктор карты принимает: значение карты и ее масть. \ 43 | **Примечание:** 44 | 45 | Diamonds Бубны 46 | 47 | Hearts Червы 48 | 49 | Spades Пики 50 | 51 | Clubs Трефы 52 | 53 | 54 | #### Методы карты 55 | 56 | * .**to_str**() возвращает строковое представление карты в виде строки, формата:4♦ 57 | * .**equal_suit**(card) - проверяет, одинаковые ли масти у карт \ 58 | Пример: \ 59 | card1.equal_suit(card2) → **True**, при card1(J♦) card2(10♦). 60 | * .**more**(card) - возвращает True, если карта у которой вызван метод больше, чем карта которую передали в качестве параметра. \ 61 | **Пример**: \ 62 | card1.more(card2) → **True**, при card1(J♦) card2(10♦). Валет больше(старше) 10-ки \ 63 | card1.more(card2) → **False**, при card1(4♦) card2(10♦). 4-ка не старше 10-ки 64 | * .**less**(card) - проверяет является ли карта младше, чем карта в параметре 65 | 66 | 67 | ##### Нюансы сравнения карт 68 | 69 | Если у карты больше(старше) значение, то она больше(старше). При равенстве значений, сравниваем масти. Старшинство мастей определяем следующее: ♥>♦>♣>♠ 70 | 71 | 72 | ##### Вывод иконок карт в консоль 73 | 74 | Пример вывода иконок в консоль: 75 | 76 | 77 | ``` 78 | print('\u2661', '\u2665') 79 | print('\u2662', '\u2666') 80 | print('\u2667', '\u2663') 81 | print('\u2664', '\u2660') 82 | ``` 83 | 84 | 85 | \uxxxx - юникод символ. Полный список всех юникод символов можно взять [тут](https://unicode-table.com/ru/#basic-latin). 86 | 87 | Юникод символы мастей игральных карт [тут](https://unicode-table.com/ru/search/?q=%D0%BC%D0%B0%D1%81%D1%82%D0%B8). 88 | -------------------------------------------------------------------------------- /Module4/practice/deck/01_card_to_str.py: -------------------------------------------------------------------------------- 1 | # Начнем с создания карты 2 | class Card: 3 | def __init__(self, value, suit): 4 | self.value = value # Значение карты(2, 3... 10, J, Q, K, A) 5 | self.suit = suit # Масть карты 6 | 7 | def to_str(self): 8 | # TODO-1: метод возвращает строковое представление карты в виде: 10♥ и A♦ 9 | ... 10 | 11 | 12 | # Создадим несколько карт 13 | card1 = Card("10", "Hearts") 14 | card2 = Card("A", "Diamonds") 15 | 16 | # Выведем карты на экран в виде: 10♥ и A♦ 17 | print(card1.to_str()) 18 | print(card2.to_str()) 19 | 20 | # Пример, вывод иконок мастей: 21 | print('\u2661', '\u2665') 22 | print('\u2662', '\u2666') 23 | print('\u2667', '\u2663') 24 | print('\u2664', '\u2660') 25 | -------------------------------------------------------------------------------- /Module4/practice/deck/02_card_equal.py: -------------------------------------------------------------------------------- 1 | # Начнем с создания карты 2 | class Card: 3 | def __init__(self, value, suit): 4 | self.value = value # Значение карты(2, 3... 10, J, Q, K, A) 5 | self.suit = suit # Масть карты 6 | 7 | def to_str(self): 8 | # TODO-0: скопируйте реализацию метода из предыдущей задачи 9 | ... 10 | 11 | def equal_suit(self, other_card): 12 | # TODO-1: метод возвращает True - если масти карт равны или False - если нет 13 | ... 14 | 15 | 16 | # Создадим несколько карт 17 | card1 = Card("10", "Hearts") 18 | card2 = Card("A", "Diamonds") 19 | 20 | # Проверим, одинаковые ли масти у карт 21 | if card1.equal_suit(card2): 22 | print(f"У карт: {card1.to_str()} и {card2.to_str()} одинаковые масти") 23 | else: 24 | print(f"У карт: {card1.to_str()} и {card2.to_str()} разные масти") 25 | -------------------------------------------------------------------------------- /Module4/practice/deck/03_cards_list.py: -------------------------------------------------------------------------------- 1 | class Card: 2 | # TODO-0: сюда копируем реализацию класса карты из предыдущего задания 3 | ... 4 | 5 | 6 | values = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] 7 | hearts_cards = [] 8 | # TODO-1: добавьте в список hearts_cards все червовые карты(от 2-ки до туза) 9 | 10 | diamonds_cards = [] 11 | # TODO-2: добавьте в список diamonds_cards все бубновые карты(от туза до 2-ки) 12 | 13 | # TODO-3: выведите все карты из списка hearts_cards в терминал через запятую в одну строку: 14 | # Пример вывода: 2♥, 3♥, 4♥ ... A♥ 15 | 16 | 17 | cards = [ 18 | Card("2", "Hearts"), 19 | Card("3", "Hearts"), 20 | Card("4", "Hearts"), 21 | ...] -------------------------------------------------------------------------------- /Module4/practice/deck/04_cards_action.py: -------------------------------------------------------------------------------- 1 | class Card: 2 | # TODO-0: сюда копируем реализацию класса карты из предыдущего задания 3 | ... 4 | 5 | 6 | cards = [] 7 | values = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] 8 | suits = ["Hearts", "Diamonds", "Spades", "Clubs"] 9 | # TODO-1: в список cards добавьте ВСЕ карты всех мастей 10 | 11 | # TODO-2: Выведите карты в формате: cards[кол-во]2♥, 3♥, 4♥ ... A♥, 2♦, 3♦ ... A♦, ... 12 | # кол-во берем от размера списка cards 13 | -------------------------------------------------------------------------------- /Module4/practice/deck/05_deck_part1.py: -------------------------------------------------------------------------------- 1 | class Card: 2 | # TODO-0: сюда копируем реализацию класса карты из предыдущего задания 3 | ... 4 | 5 | 6 | class Deck: 7 | def __init__(self): 8 | # Список карт в колоде. Каждым элементом списка будет объект класса Card 9 | values = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] 10 | suits = ["Hearts", "Diamonds", "Spades", "Clubs"] 11 | self.cards = [] 12 | # TODO-1: конструктор добавляет в список self.cards все(52) карты 13 | 14 | def show(self): 15 | # TODO-2: Принцип работы данного метода прописан в 00_task_deck.md 16 | ... 17 | 18 | 19 | # Создаем колоду 20 | deck = Deck() 21 | # Выводим колоду в формате указанном в основном задании 22 | print(deck.show()) 23 | -------------------------------------------------------------------------------- /Module4/practice/deck/06_deck_part2.py: -------------------------------------------------------------------------------- 1 | class Card: 2 | # TODO-0: сюда копируем реализацию класса карты из предыдущего задания 3 | ... 4 | 5 | 6 | class Deck: 7 | def __init__(self): 8 | # Список карт в колоде. Каждым элементом списка будет объект класса Card 9 | values = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] 10 | suits = ["Hearts", "Diamonds", "Spades", "Clubs"] 11 | self.cards = [] 12 | # TODO-0: конструктор копируем из предыдущей задачи 13 | 14 | def show(self): 15 | # TODO-0: копируем из предыдущей задачи 16 | ... 17 | 18 | def draw(self, x): 19 | # TODO-1: Принцип работы данного метода прописан в 00_task_deck.md 20 | ... 21 | 22 | def shuffle(self): 23 | # TODO-2: Принцип работы данного метода прописан в 00_task_deck.md 24 | # Подсказка: https://www.w3schools.com/python/ref_random_shuffle.asp 25 | ... 26 | 27 | 28 | # Создаем колоду 29 | deck = Deck() 30 | # Выводим колоду в формате указанном в основном задании 31 | print(deck.show()) 32 | # Тусуем колоду 33 | deck.shuffle() 34 | print(deck.show()) 35 | 36 | # Возьмем 5 карт "в руку" 37 | hand = deck.draw(5) 38 | # Выводим колоду, чтобы убедиться что 5 верхних карт отсутствуют 39 | print(deck.show()) 40 | # Выводим список карт "в руке"(список hand) 41 | print(...) 42 | -------------------------------------------------------------------------------- /Module4/practice/deck/07_deck_part3.py: -------------------------------------------------------------------------------- 1 | class Card: 2 | # TODO-0: сюда копируем реализацию класса карты из предыдущего задания 3 | 4 | # TODO-1: реализуем новые методы 5 | def more(self, other_card): 6 | ... 7 | 8 | def less(self, other_card): 9 | ... 10 | 11 | 12 | class Deck: 13 | # TODO-0: сюда копируем реализацию класса колоды из предыдущего задания 14 | ... 15 | 16 | 17 | # Создаем колоду 18 | deck = Deck() 19 | # Тусуем колоду 20 | deck.shuffle() 21 | print(deck.show()) 22 | # Берем две карты из колоды 23 | card1, card2 = deck.draw(2) 24 | 25 | # Тестируем методы .less() и .more() 26 | if card1.more(card2): 27 | print(f"{card1.to_str()} больше {card2.to_str()}") 28 | if card1.less(card2): 29 | print(f"{card1.to_str()} меньше {card2.to_str()}") 30 | -------------------------------------------------------------------------------- /Module4/practice/deck/08_deck_part4[add].py: -------------------------------------------------------------------------------- 1 | class Card: 2 | # TODO-0: сюда копируем реализацию класса карты из предыдущего задания 3 | ... 4 | 5 | 6 | class Deck: 7 | # TODO-0: сюда копируем реализацию класса колоды из предыдущего задания 8 | ... 9 | 10 | def shift(self, num_card): 11 | # TODO-1: реализуем новый метод "сдвиг" 12 | # Принцип работы: перемещает num_card с верха колоды под низ 13 | ... 14 | 15 | 16 | # Создаем колоду 17 | deck = Deck() 18 | # Тусуем колоду 19 | deck.shuffle() 20 | print(deck.show()) 21 | # Сдвигаем 10 карт 22 | deck.shift(10) 23 | print(deck.show()) -------------------------------------------------------------------------------- /Module4/practice/deck/09_deck_final.py: -------------------------------------------------------------------------------- 1 | class Card: 2 | # TODO-0: сюда копируем реализацию класса карты из предыдущего задания 3 | ... 4 | 5 | 6 | class Deck: 7 | # TODO-0: сюда копируем реализацию класса колоды из предыдущего задания 8 | ... 9 | 10 | 11 | deck = Deck() 12 | # TODO-final: реализовать нативную работу с объектами: 13 | # 1. Вывод колоды в терминал: 14 | print(deck) # вместо print(deck.show()) 15 | 16 | card1, card2 = deck.draw(2) 17 | # 2. Вывод карты в терминал: 18 | print(card1) # вместо print(card1.to_str()) 19 | 20 | # 3. Сравнение карт: 21 | if card1 > card2: 22 | print(f"{card1} больше {card2}") 23 | 24 | # 4. Итерация по колоде: 25 | for card in deck: 26 | print(card) 27 | 28 | # 5. Просмотр карты в колоде по ее индексу: 29 | print(deck[6]) 30 | 31 | 32 | # Список ВСЕХ magic-методов см. тут: http://pythonworld.ru/osnovy/peregruzka-operatorov.html 33 | -------------------------------------------------------------------------------- /Module4/practice/deck/deck_tasks/01_task_deck.py: -------------------------------------------------------------------------------- 1 | from deck_total import Card, Deck 2 | 3 | # Важно! При решении задач данного блока классы Колоды и Карты размещаем в файле deck_total.py и импортируем 4 | 5 | # TODO: Создайте колоду из 52 карт. Перемешайте ее. Вытяните две карты сверху. 6 | # Сравните эти карты и выведите сообщение формата: “карта A♦ больше J♣” 7 | -------------------------------------------------------------------------------- /Module4/practice/deck/deck_tasks/02_task_deck.py: -------------------------------------------------------------------------------- 1 | from deck_total import Card, Deck 2 | 3 | # TODO: Создайте колоду из 52 карт. Перемешайте ее. Вытяните 10 карт сверху 4 | # и посчитайте карт какой/каких мастей среди вытянутых карт оказалось больше всего? 5 | -------------------------------------------------------------------------------- /Module4/practice/deck/deck_tasks/03_task_deck.py: -------------------------------------------------------------------------------- 1 | from deck_total import Card, Deck 2 | 3 | # TODO: Создайте колоду из 52 карт. Перемешайте ее. Вытяните одну карту сверху. 4 | # Снова перемешайте колоду и вытяните еще одну. Если вторая карта меньше первой, повторите “перемешать + вытянуть”, 5 | # до тех пор, пока не вытяните карту больше предыдущей карты. 6 | # В качестве результата выведи все вытягиваемые карты в консоль. 7 | -------------------------------------------------------------------------------- /Module4/practice/deck/deck_tasks/04_task_deck.py: -------------------------------------------------------------------------------- 1 | from deck_total import Card, Deck 2 | 3 | # TODO: Создайте две колоды, в каждой должно быть 36 карт(старшинство карт начинается с 6-ки). Перемешайте их. 4 | # Вытягивайте карты парами - одну из первой колоды, вторую из второй. 5 | # Если карта из первой колоды окажется больше(старше), то записываем 1:0(условно начисляем победное очко первой колоде), 6 | # если карты одинаковые, то не учитываем очко никуда. 7 | # Выведите итоговый счет, сравнив попарно все карты в колодах. 8 | -------------------------------------------------------------------------------- /Module4/practice/deck/deck_tasks/05_task_deck.py: -------------------------------------------------------------------------------- 1 | from deck_total import Card, Deck 2 | 3 | # Теперь немного сложнее: создадим имитацию одного хода в “Дурака без козырей”: 4 | 5 | # 1. Создайте колоду из 52 карт. Перемешайте ее. 6 | # 2. Первый игрок берет сверху 6 карт 7 | # 3. Второй игрок берет сверху 6 карт. 8 | # 4. Игрок-1 ходит: 9 | # 1. игрок-1 выкладывает самую маленькую карту по значению 10 | # 2. игрок-2 пытается бить карту, если у него есть такая же масть но значением больше. 11 | # 3. Если игрок-2 не может побить карту, то он проигрывает. 12 | # 4. Если игрок-2 бьет карту, то игрок-1 может подкинуть карту любого значения, которое есть на столе. 13 | # 5. Выведите в консоль максимально наглядную визуализацию данного игрового хода. 14 | -------------------------------------------------------------------------------- /Module4/practice/deck/deck_tasks/06_task_deck.py: -------------------------------------------------------------------------------- 1 | from deck_total import Card, Deck 2 | 3 | # TODO: Создайте две колоды по 52 карты. Перемешайте их вместе - в итоге получится одна колода из 104 карт. 4 | # Выбросите/вытяните половину карт. Узнайте, какой/каких мастей в колоде осталось больше всего? 5 | -------------------------------------------------------------------------------- /Module4/practice/deck/deck_tasks/deck_total.py: -------------------------------------------------------------------------------- 1 | class Card: 2 | pass 3 | # TODO: сюда копируем последнюю версию реализации класса карты 4 | 5 | 6 | class Deck: 7 | pass 8 | # TODO: сюда копируем последнюю версию реализации класса колоды 9 | 10 | 11 | # В этом файле дорабатываем классы, если это требуется для решения задачи 12 | # Важно! При доработке классов для решение очередной задачи, необходимо не сломать решение предыдущей 13 | 14 | if __name__ == "__main__": 15 | # Тут можно разместить тесты классов 16 | ... 17 | -------------------------------------------------------------------------------- /Module5/examples/01_sort_choice.py: -------------------------------------------------------------------------------- 1 | from random import randint 2 | 3 | # Алгоритм: 4 | # 1. Найти наименьшее значение в списке. 5 | # 2. Записать его в начало списка, а первый элемент - на место, где раньше стоял наименьший. 6 | # 3. Снова найти наименьший элемент в списке. При этом в поиске не участвует первый элемент. 7 | # 4. Второй минимум поместить на второе место списка. Второй элемент при этом перемещается на освободившееся место. 8 | # 5. Продолжать выполнять поиск и обмен, пока не будет достигнут конец списка. 9 | 10 | nums = [5, 2, -1, 8, 4, -4, 7] 11 | print("before sort = ", nums) 12 | i = 0 13 | while i < len(nums) - 1: 14 | m = i 15 | j = i + 1 16 | while j < len(nums): 17 | if nums[j] < nums[m]: 18 | m = j 19 | j += 1 20 | nums[i], nums[m] = nums[m], nums[i] 21 | i += 1 22 | print("after sort = ", nums) 23 | -------------------------------------------------------------------------------- /Module5/examples/01_sort_choice_com.py: -------------------------------------------------------------------------------- 1 | # Заполняем список из 10 элементов 2 | # случайными числами от 1 до 99 и 3 | # выводим неотсортированный список на экран. 4 | from random import randint 5 | 6 | nums = [5, 2, 1, 8, 4] 7 | print("before sort = ", nums) 8 | 9 | # В цикле переменная i хранит индекс ячейки, 10 | # в которую записывается минимальный элемент. 11 | # Сначала это будет первая ячейка. 12 | i = 0 13 | 14 | # N - 1, так как последний элемент 15 | # обменивать уже не надо. 16 | while i < len(nums) - 1: 17 | 18 | # ПОИСК МИНИМУМА 19 | # Сначала надо найти минимальное значение 20 | # на срезе от i до конца списка. 21 | # Переменная m будет хранить индекс ячейки 22 | # с минимальным значением. 23 | # Сначала предполагаем, что 24 | # в ячейке i содержится минимальный элемент. 25 | m = i 26 | # Поиск начинаем с ячейки следующей за i. 27 | j = i + 1 28 | # Пока не дойдем конца списка, 29 | while j < len(nums): 30 | # будем сравнивать значение ячейки j, 31 | # со значением ячейки m. 32 | if nums[j] < nums[m]: 33 | # Если в j значение меньше, чем в m, 34 | # сохраним в m номер найденного 35 | # на данный момент минимума. 36 | m = j 37 | # Перейдем к следующей ячейке. 38 | j += 1 39 | 40 | # ОБМЕН ЗНАЧЕНИЙ 41 | # В ячейку i записывается найденный минимум, 42 | # а значение из ячейки i переносится 43 | # на старое место минимума. 44 | nums[i], nums[m] = nums[m], nums[i] 45 | 46 | # ПЕРЕХОД К СЛЕДУЮЩЕЙ НЕОБРАБОТАННОЙ ЯЧЕЙКЕ 47 | i += 1 48 | 49 | # Вывод отсортированного списка 50 | print("after sort = ", nums) 51 | -------------------------------------------------------------------------------- /Module5/examples/02_bubble_sort.py: -------------------------------------------------------------------------------- 1 | # Алгоритм 2 | # Сначала сравниваются первые два элемента списка. 3 | # Если первый элемент больше, они меняются местами. 4 | # Если они уже в нужном порядке, оставляем их как есть. Затем переходим к следующей паре элементов, 5 | # сравниваем их значения и меняем местами при необходимости. 6 | # Этот процесс продолжается до последней пары элементов в списке. 7 | 8 | nums = [5, 2, 1, 8, 4] 9 | print("before sort = ", nums) 10 | swapped = True 11 | while swapped: 12 | swapped = False 13 | # print("*****") 14 | for i in range(len(nums) - 1): 15 | # print("i = ", i) 16 | if nums[i] > nums[i + 1]: 17 | # Меняем элементы 18 | nums[i], nums[i + 1] = nums[i + 1], nums[i] 19 | # Устанавливаем swapped в True для следующей итерации 20 | swapped = True 21 | print("after sort = ", nums) 22 | -------------------------------------------------------------------------------- /Module5/examples/03_quick_sort.py: -------------------------------------------------------------------------------- 1 | # Алгоритм: 2 | # 1. Выбор опорного элемента из массива. 3 | # 2. Перераспределение элементов в массиве таким образом, что элементы меньше опорного помещаются перед ним, 4 | # а больше или равные — после. 5 | # 3. Рекурсивное применение первых двух шагов к двум подмассивам слева и справа от опорного элемента. 6 | # Рекурсия не применяется к массиву, в котором только один или отсутствуют элементы. 7 | 8 | def partition(nums, low, high): 9 | # Выбираем средний элемент в качестве опорного 10 | # Также возможен выбор первого, последнего 11 | # или произвольного элементов в качестве опорного 12 | pivot = nums[(low + high) // 2] 13 | i = low - 1 14 | j = high + 1 15 | while True: 16 | i += 1 17 | while nums[i] < pivot: 18 | i += 1 19 | 20 | j -= 1 21 | while nums[j] > pivot: 22 | j -= 1 23 | 24 | if i >= j: 25 | return j 26 | 27 | # Если элемент с индексом i (слева от опорного) больше, чем 28 | # элемент с индексом j (справа от опорного), меняем их местами 29 | nums[i], nums[j] = nums[j], nums[i] 30 | 31 | 32 | def quick_sort(nums): 33 | # Создадим вспомогательную функцию, которая вызывается рекурсивно 34 | def _quick_sort(items, low, high): 35 | if low < high: 36 | # Индекс опорного элемента 37 | split_index = partition(items, low, high) 38 | _quick_sort(items, low, split_index) 39 | _quick_sort(items, split_index + 1, high) 40 | 41 | _quick_sort(nums, 0, len(nums) - 1) 42 | 43 | 44 | # Проверяем, что оно работает 45 | nums = [22, 5, 1, 18, 99, 32, 12, 18, 5] 46 | print("before sort = ", nums) 47 | quick_sort(nums) 48 | print("after sort = ", nums) 49 | -------------------------------------------------------------------------------- /Module5/examples/04_bin_search.py: -------------------------------------------------------------------------------- 1 | # Алгоритм 2 | # 1. Находится средний элемент последовательности. Для этого первый и последний индексы связываются с переменными, 3 | # а индекс среднего элемента вычисляется. 4 | # 2. Значение среднего элемента сравнивается с искомым значение. В зависимости от того, больше оно или меньше значения 5 | # среднего элемента, дальнейший поиск будет происходить только в левой или только в правой половинах массива. 6 | # Если значение среднего элемента оказывается равным искомому, поиск завершается. 7 | # 3. Иначе одна из границ исследуемой последовательности сдвигается. Если искомое значение больше значения 8 | # среднего элемента, то нижняя граница сдвигается за средний элемент на один элемент справа. 9 | # Если искомое значение меньше значения среднего элемента, то верхняя граница сдвигается на элемент перед средним. 10 | # 4. Снова находится средний элемент теперь уже в выбранной половине. 11 | # Описанный выше алгоритм повторяется для данного среза. 12 | 13 | from random import randint 14 | 15 | # Создание списка, 16 | # его сортировка по возрастанию 17 | # и вывод на экран 18 | a = [] 19 | for i in range(10): 20 | a.append(randint(1, 50)) 21 | a.sort() 22 | print(a) 23 | 24 | # искомое число 25 | value = int(input()) 26 | 27 | mid = len(a) // 2 28 | low = 0 29 | high = len(a) - 1 30 | 31 | while a[mid] != value and low <= high: 32 | if value > a[mid]: 33 | low = mid + 1 34 | else: 35 | high = mid - 1 36 | mid = (low + high) // 2 37 | 38 | if low > high: 39 | print("No value") 40 | else: 41 | print("ID =", mid) 42 | -------------------------------------------------------------------------------- /Module5/examples/decor_benchmark.py: -------------------------------------------------------------------------------- 1 | def benchmark(iters=1): 2 | def actual_decorator(func): 3 | import time 4 | 5 | def wrapper(*args, **kwargs): 6 | total = 0 7 | for i in range(iters): 8 | start = time.time() 9 | return_value = func(*args, **kwargs) 10 | end = time.time() 11 | total = total + (end - start) 12 | print(f'[*] Среднее время выполнения: {total / iters} секунд.') 13 | return return_value 14 | 15 | return wrapper 16 | 17 | return actual_decorator 18 | -------------------------------------------------------------------------------- /Module5/practice/01_bases_sort/01_base_sort.py: -------------------------------------------------------------------------------- 1 | # Возьмите алгоритм сортировки пузырьком из examples/bubble_sort.py 2 | # Раскомментируйте print-ы, изучите вывод в консоли. 3 | # Вспомнив теорию, оптимизируйте алгоритм сортировки... 4 | 5 | -------------------------------------------------------------------------------- /Module5/practice/01_bases_sort/02_base_sort.py: -------------------------------------------------------------------------------- 1 | # Все алгоритмы сортировки из examples/ оберните в функции 2 | 3 | def bubble_sort(): 4 | pass 5 | 6 | 7 | def sort_choice(): 8 | pass 9 | 10 | 11 | def quick_sort(): 12 | pass 13 | 14 | 15 | # Напишите функцию для заполнения списка случайными числами 16 | def gen_list(size, at=-100, to=100): 17 | import random 18 | """ 19 | :param size: кол-во элементов списка 20 | :param at: минимально возможное значение элементов 21 | :param to: максимально возможное значение элементов 22 | :return: список из size произвольных элементов в диапазоне at..to 23 | """ 24 | pass 25 | 26 | # протестируйте функции сортировки, используя gen_list() для создания сортируемых списков 27 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/01_task_sort.py: -------------------------------------------------------------------------------- 1 | # Сумма с условием 2 | # Дан список чисел. 3 | # Найти: сумму элементов списка, больших данного числа a 4 | 5 | numbers = [2.5, 13.6, 13, -22.4, -12.8, 6.7, 12.8, 21, 4, -22.1] 6 | a = ... # Задайте самостоятельно, выбрав произвольное число 7 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/02_task_sort.py: -------------------------------------------------------------------------------- 1 | # Сумма из диапазона 2 | # Дан список чисел. 3 | # Найти: сумму элементов списка, больших данного числа А, но меньше B. 4 | 5 | numbers = [-2.5, 13.6, 13, -22.4, -12.8, 12.8, 21, 4, 22.1, 3] 6 | a = ... # Задайте самостоятельно, выбрав произвольное число 7 | b = ... # Задайте самостоятельно, выбрав произвольное число 8 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/03_task_sort.py: -------------------------------------------------------------------------------- 1 | # Сумма наибольших 2 | # Дан список чисел. 3 | # Найти: сумму 5-ти самых больших элементов 4 | 5 | numbers = [-2.5, 13.6, -13, -22.4, -12.8, -6.7, 12.8, -21, 4, -22.1, 0] 6 | 7 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/04_task_sort.py: -------------------------------------------------------------------------------- 1 | # Сумма наибольших по модулю 2 | # Дан массив(список) чисел. 3 | # Найти: сумму 5-ти самых больших элементов по модулю. 4 | # Пояснение: сравниваем элементы по модулю, а в сумму добавляем сами значения элементов(без модуля) 5 | # В примере ниже, два самых больших по модулю числа это: -22.4 и 21.1. Они самые большие по модулю, а их сумма = -1.3 6 | 7 | numbers = [-2.5, 13.6, -13, -22.4, -12.8, -6.7, 12.8, -21, 4, 21.1, 0] -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/05_task_sort.py: -------------------------------------------------------------------------------- 1 | # Дан список сотрудников: 2 | staff = [ 3 | { 4 | 'name': 'Григорий', 5 | 'surname': 'Петров', 6 | 'salary': 124300 7 | }, 8 | { 9 | 'name': 'Николай', 10 | 'surname': 'Петров', 11 | 'salary': 120000 12 | }, 13 | { 14 | 'name': 'Иван', 15 | 'surname': 'Павлов', 16 | 'salary': 34500 17 | }, 18 | { 19 | 'name': 'Василий', 20 | 'surname': 'Кукушкин', 21 | 'salary': 162500 22 | }, 23 | { 24 | 'name': 'Василий', 25 | 'surname': 'Павлов', 26 | 'salary': 34500 27 | }, 28 | ] 29 | 30 | # 1. Выведите список сотрудников, отсортированный по уменьшению их заработной платы. 31 | # Если у нескольких сотрудников одинаковая ЗП, то добавьте сортировку по Фамилии 32 | print("Список сотрудников отсортированный по уменьшению ЗП:") 33 | 34 | # 2. Найдите сумму зарплат трех самых низкооплачиваемых сотрудников: 35 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/06_task_sort.py: -------------------------------------------------------------------------------- 1 | # Рекламная акция 2 | # В сети магазинов "Н-Аудио" проводится рекламная акция. Каждый второй товар – бесплатно. 3 | # Естественно, кассирам дано указание пробивать товары в таком порядке, чтобы магазин потерял как можно меньше денег. 4 | # По списку товаров определите максимальную сумму в чеке. 5 | # 6 | # Вход:дано N натуральных чисел – цены товаров. 7 | # Выход: одно число – максимальная сумма чека. 8 | 9 | # Пример 10 | # Вход: 11 | # 2 1 10 50 10 12 | # Выход: 13 | # 70 14 | # Пояснение: 15 | # Возможен такой порядок: 10 2 50 1 10 16 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/07_task_sort.py: -------------------------------------------------------------------------------- 1 | # Призеры олимпиады 2 | # По результатам олимпиады участники награждаются дипломами. 3 | # Набравшие одинаковые баллы получают дипломы одинаковой степени. 4 | # Призером олимпиады считается участник, получивший диплом не хуже III степени. 5 | # По результатам олимпиады определите количество призеров. 6 | # Вход: натуральное число участников(N < 100) и далее N натуральных# чисел – результаты участников. 7 | # Выход: одно число – число призеров. 8 | # Пример: 9 | # Вход 10 | # 11 | # 10 1 3 4 3 5 6 7 7 6 1 12 | # Выход 13 | # 5 14 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/08_task_sort.py: -------------------------------------------------------------------------------- 1 | # Телефонная база 2 | # Отсортируйте список телефонов по возрастанию и используя сортировку выбором. 3 | # Телефон задан в виде строки формата nn-nn-nn. Например, 23-45-67 4 | 5 | phones = ["25-17-58", "11-34-85", "54-61-56", "34-61-72", "25-17-55", "34-56-56"] 6 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/09_task_sort.py: -------------------------------------------------------------------------------- 1 | # Список сотрудников 2 | # Дан список, элементами которого являются сотрудники, представленные в виде словаря(dict). 3 | # Пример данных: 4 | employees = [ 5 | {"name": "Петр", "surname": "Алексеев", "position": "Инженер"}, 6 | {"name": "Иван", "surname": "Петров", "position": "Прораб"}, 7 | {"name": "Алексей", "surname": "Петров", "position": "Строитель"}, 8 | {"name": "Иван", "surname": "Сидоров", "position": "Строитель"}, 9 | ] 10 | # Выведите список сотрудников(без указания должности) в формате: Фамилия Имя, в отсортированном порядке. 11 | # Примечание: если фамилии сотрудников совпадают, при сортировке учесть имя. 12 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/10_task_sort.py: -------------------------------------------------------------------------------- 1 | # Камни* 2 | # Имеется N камней веса А1,А2,...,АN. 3 | # 4 | # Необходимо разбить их на две кучи таким образом, чтобы веса куч отличались не более чем в 2 раза. 5 | # Если этого сделать нельзя, то указать это. 6 | 7 | -------------------------------------------------------------------------------- /Module5/practice/02_tasks_sort/11_task_sort.py: -------------------------------------------------------------------------------- 1 | # Анаграммы* 2 | # Задается словарь (список слов). Найти в нем все анаграммы (слова, составленные из одних и тех же букв). 3 | -------------------------------------------------------------------------------- /Module6/home_work/01_hw_sort.py: -------------------------------------------------------------------------------- 1 | # Доделайте все задачи Module-5/practice/02_tasks_sort/ 2 | -------------------------------------------------------------------------------- /Module6/home_work/02_hw_linkedList.py: -------------------------------------------------------------------------------- 1 | # Для Связанного списка(LinkedList): 2 | # 1. Реализуйте все задания в файле LinkedList.py Модуля-6 3 | # 2. Реализуйте метод reverse() - меняющий значения всех нод(узлов) на противоположное. 4 | # Значение первой ноды становится значением последней, значение второй, значением предпоследней. 5 | # Примечание: при реализации не используйте список(list). 6 | -------------------------------------------------------------------------------- /Module6/practice/LinkedList.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | """ 3 | Класс для узла списка. Хранит значение и указатель на следующий узел. 4 | """ 5 | 6 | def __init__(self, value=None, next=None): 7 | self.value = value 8 | self.next = next 9 | 10 | 11 | class LinkedList: 12 | def __init__(self): 13 | self.first = None 14 | self.last = None 15 | 16 | def __str__(self): 17 | # FIXME: убрать вывод запятой после последнего элемента 18 | if self.first is not None: 19 | current = self.first 20 | out = 'LinkedList [' + str(current.value) + ',' 21 | while current.next is not None: 22 | current = current.next 23 | out += str(current.value) + ',' 24 | return out + ']' 25 | return 'LinkedList []' 26 | 27 | def clear(self): 28 | """ 29 | Очищаем список 30 | """ 31 | # TODO: реализовать очистку списка 32 | raise TypeError("Not implemented") 33 | 34 | def add(self, value): 35 | """ 36 | Добавляем новое значение value в конец списка 37 | """ 38 | new_node = Node(value, None) # Создаем новый узел 39 | if self.first is None: # Если список был пуст 40 | # self.first и self.last будут указывать на один и тотже узел, т.к. он единственный 41 | self.last = new_node 42 | self.first = new_node 43 | else: 44 | self.last.next = new_node 45 | self.last = new_node 46 | 47 | def push(self, value): 48 | """ 49 | Добавляет элемент со значением value в начало списка 50 | """ 51 | if self.first is None: # Если список был пуст 52 | # self.first и self.last будут указывать на один и тотже узел 53 | self.last = self.first = Node(value, None) 54 | else: 55 | new_node = Node(value, self.first) 56 | self.first = new_node 57 | 58 | def insert(self, value, index): 59 | """ 60 | Вставляет узел со значением value на позицию index 61 | """ 62 | # TODO: реализовать вставку 63 | raise TypeError("Not implemented") 64 | 65 | def find(self, value): 66 | """ 67 | Ищет элемент со зачением value 68 | :param value: значение искомого элемента 69 | :return: индекс искомого элемента, или ???, если элемент не найден 70 | """ 71 | # TODO: реализовать поиск элемента 72 | # подумать над возвращаемым значением, если элемент со значение value не найден 73 | raise TypeError("Not implemented") 74 | 75 | def len(self): 76 | # TODO: сделать более быструю реализацию, т.к. каждый раз проходка по всем элементам - долго 77 | length = 0 78 | if self.first is not None: 79 | current = self.first 80 | while current.next is not None: 81 | current = current.next 82 | length += 1 83 | return length + 1 # +1 для учета self.first 84 | 85 | 86 | if __name__ == "__main__": 87 | L = LinkedList() 88 | print("empty list = ", L) 89 | L.add(1) 90 | L.add(2) 91 | L.add(3) 92 | 93 | print("list = ", L) 94 | 95 | # TODO: реализовать интерфейс итерации 96 | # for el in L: 97 | # print(el) 98 | # Напомню принцип работы итератора: 99 | # iterator_L = iter(L) L.__iter__() 100 | # next(iterator_L) it.__next__() 101 | # next(iterator_L) 102 | # next(iterator_L) 103 | # next(iterator_L) 104 | 105 | # TODO: реализовать обращение по индексу и изменение значение по индексу 106 | # print(L[0]) 107 | # L[0] = "new" 108 | # print(L[0]) 109 | 110 | # TODO: реализовать создание нового списка с задание начальных элементов 111 | # L = LinkedList(2, 4, 6, -12) 112 | # print(L) 113 | -------------------------------------------------------------------------------- /Module6/practice/nodes/01_nodes_create.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | """ 3 | Класс для узла списка. Хранит значение и указатель на следующий узел. 4 | """ 5 | 6 | def __init__(self, value=None, next=None): 7 | self.value = value 8 | self.next = next 9 | 10 | 11 | # Создаем ноды(узлы) 12 | node0 = Node("Иван") 13 | node1 = Node("Алекс") 14 | node2 = Node("Петр") 15 | node3 = Node("Анна") 16 | # TODO: Добавьте еще несколько нод с именами 17 | 18 | # Связываем ноды 19 | node0.next = node1 20 | node1.next = node2 21 | node2.next = node3 22 | # TODO: Свяжите добавленные выше ноды вместе 23 | 24 | # Пройдемся по значениям всех нод, начиная с первой 25 | current_node = node0 26 | while current_node: 27 | print(current_node.value) 28 | current_node = current_node.next 29 | -------------------------------------------------------------------------------- /Module6/practice/nodes/02_nodes_from_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | """ 3 | Класс для узла списка. Хранит значение и указатель на следующий узел. 4 | """ 5 | 6 | def __init__(self, value=None, next=None): 7 | self.value = value 8 | self.next = next 9 | 10 | 11 | def print_nodes_value(start_node): 12 | current_node = start_node 13 | while current_node: 14 | print(current_node.value) 15 | current_node = current_node.next 16 | 17 | 18 | def gen_names_list(size=None): 19 | import random 20 | names = ["Василий", "Николай", "Екатерина", "Ирина", "Линус", "Ганс", "Игнат", "Марина", "Кристина", "Кирилл"] 21 | if not size: 22 | size = random.randint(3, len(names)) 23 | random.shuffle(names) 24 | return names[:size] 25 | 26 | 27 | # Дан список из произвольного количества имен 28 | names = gen_names_list() 29 | print(names) 30 | 31 | # TODO: создайте цепочку нод из имен списка 32 | ... 33 | 34 | 35 | # TODO: Передайте первую ноду в функцию print_nodes_value(), чтобы получить значения всех нод в цепочке 36 | first_node = ... 37 | print_nodes_value(first_node) -------------------------------------------------------------------------------- /Module6/practice/nodes/03_nodes_len.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | """ 3 | Класс для узла списка. Хранит значение и указатель на следующий узел. 4 | """ 5 | 6 | def __init__(self, value=None, next=None): 7 | self.value = value 8 | self.next = next 9 | 10 | 11 | def gen_names_list(size=None): 12 | import random 13 | names = ["Василий", "Николай", "Екатерина", "Ирина", "Линус", "Ганс", "Игнат", "Марина", "Кристина", "Кирилл"] 14 | if not size: 15 | size = random.randint(3, len(names)) 16 | random.shuffle(names) 17 | return names[:size] 18 | 19 | 20 | def len_nodes(start_node): 21 | """ 22 | Возвращает целое число - кол-во нод у цепочке 23 | """ 24 | pass 25 | 26 | 27 | # Дан список из произвольного количества имен 28 | names = gen_names_list() 29 | print(names) 30 | 31 | # TODO: скопируйте цепочку нод из предыдущей задачи 32 | ... 33 | 34 | # TODO: Передайте первую ноду в функцию len_nodes(), чтобы получить количество нод в цепочке 35 | first_node = ... 36 | len_nodes(first_node) 37 | -------------------------------------------------------------------------------- /Module6/practice/nodes/04_nodes_index.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | """ 3 | Класс для узла списка. Хранит значение и указатель на следующий узел. 4 | """ 5 | 6 | def __init__(self, value=None, next=None): 7 | self.value = value 8 | self.next = next 9 | 10 | 11 | def print_node_by_index(start_node, index): 12 | """ 13 | Выводит в терминал значение(value) ноды с заданным индексом(index). Индексация начинается с нуля. 14 | Если index = 0, выводим значение ноды start_node 15 | Считаем, что index гарантированно > 0 16 | """ 17 | pass 18 | 19 | 20 | def gen_names_list(size=None): 21 | import random 22 | names = ["Василий", "Николай", "Екатерина", "Ирина", "Линус", "Ганс", "Игнат", "Марина", "Кристина", "Кирилл"] 23 | if not size: 24 | size = random.randint(3, len(names)) 25 | random.shuffle(names) 26 | return names[:size] 27 | 28 | 29 | # Дан список из произвольного количества имен 30 | names = gen_names_list() 31 | # print(names) 32 | 33 | # TODO: скопируйте цепочку нод из предыдущей задачи 34 | ... 35 | 36 | 37 | # TODO: Передайте первую ноду и индекс ноды, значение которой нужно вывести, в функцию print_node_by_index() 38 | # напишите реализацию функции print_node_by_index() 39 | first_node = ... 40 | index = ... 41 | print_node_by_index(first_node, index) 42 | -------------------------------------------------------------------------------- /Module6/practice/nodes/05_nodes_find.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | """ 3 | Класс для узла списка. Хранит значение и указатель на следующий узел. 4 | """ 5 | 6 | def __init__(self, value=None, next=None): 7 | self.value = value 8 | self.next = next 9 | 10 | 11 | def find_node_by_value(start_node, value): 12 | """ 13 | Возвращает индекс ноды с заданным значением(value). 14 | Если нода с указанным значение(value) не найдена, дублируйте поведение методы .index() списка 15 | """ 16 | pass 17 | 18 | 19 | def gen_names_list(size=None): 20 | import random 21 | names = ["Василий", "Николай", "Екатерина", "Ирина", "Линус", "Ганс", "Игнат", "Марина", "Кристина", "Кирилл"] 22 | if not size: 23 | size = random.randint(3, len(names)) 24 | random.shuffle(names) 25 | return names[:size] 26 | 27 | 28 | # Дан список из произвольного количества имен 29 | names = gen_names_list() 30 | # print(names) 31 | 32 | # TODO: скопируйте цепочку нод из предыдущей задачи 33 | ... 34 | 35 | 36 | # TODO: Передайте первую ноду и искомое значение в функцию find_node_by_value() 37 | # напишите реализацию функции find_node_by_value() 38 | first_node = ... 39 | value = ... 40 | find_node_by_value(first_node, value) 41 | -------------------------------------------------------------------------------- /Module7/examples/bfs.py: -------------------------------------------------------------------------------- 1 | # BFS(Breadth-First Search). Алгоритм поиска в ширину. 2 | # Позволяет найти кратчайшие расстояния из одной вершины невзвешенного (ориентированного или неориентированного) графа 3 | # до всех остальных вершин. 4 | # Под кратчайшим путем подразумевается путь, содержащий наименьшее число ребер. 5 | # Алгоитм: 6 | # 1. Начальную вершину помещаем в очередь 7 | # 2. Пока очередь не пуста: 8 | # 2.1 Достаем из очереди первую вершину 9 | # 2.2 Для каждой вершины списка смежности 10 | # 2.2.1 Если еще до этой вершины еще не доходили, то помечаем расстояние до нее и добавляем ее в конец очереди 11 | # 2.2.1 Если вершину уэе посещали, то игнорируем ее 12 | # 3 --5--2 6--7 13 | # / \ / / 14 | # 0---1--4 15 | graph = [ 16 | # список смежности 17 | [1, 3], # 0 18 | [0, 3, 4, 5], # 1 19 | [4, 5], # 2 20 | [0, 1, 5], # 3 21 | [1, 2], # 4 22 | [1, 2, 3], # 5 23 | [7], # 6 24 | [6] # 7 25 | ] 26 | 27 | start = 0 28 | lengths = [None] * (len(graph)) 29 | lengths[start] = 0 30 | queue = [start] 31 | while queue: 32 | cur_vertex = queue.pop(0) 33 | for vertex in graph[cur_vertex]: 34 | if lengths[vertex] is None: 35 | lengths[vertex] = lengths[cur_vertex] + 1 36 | queue.append(vertex) 37 | 38 | print(lengths) 39 | -------------------------------------------------------------------------------- /Module7/examples/dfs.py: -------------------------------------------------------------------------------- 1 | # DFS(Depth-First Search) - поиск в глубину 2 | # Позволяет построить обход ориентированного или неориентированного графа, 3 | # при котором посещаются все вершины, доступные из начальной вершины. 4 | 5 | # Алгоритм обхода в глубину: 6 | # 1. Пойти в какую-нибудь смежную вершину, не посещенную ранее. 7 | # 2. Запустить из этой вершины алгоритм обхода в глубину 8 | # 3. Вернуться в начальную вершину. 9 | # 4. Повторить пункты 1-3 для всех не посещенных ранее смежных вершин. 10 | 11 | # 3 --5--2 6--7 12 | # / \ / / 13 | # 0---1--4 14 | graph = [ 15 | # список смежности 16 | [1, 3], # 0 17 | [0, 3, 4, 5], # 1 18 | [4, 5], # 2 19 | [0, 1, 5], # 3 20 | [1, 2], # 4 21 | [1, 2, 3], # 5 22 | [7], # 6 23 | [6] # 7 24 | ] 25 | 26 | visited = [False] * (len(graph)) 27 | start = 0 28 | 29 | 30 | def dfs(v): 31 | visited[v] = True 32 | for w in graph[v]: 33 | if not visited[w]: # посещён ли текущий сосед? 34 | dfs(w) 35 | 36 | 37 | dfs(start) 38 | 39 | print(visited) 40 | -------------------------------------------------------------------------------- /Module7/home_work/friends_of_friends.py: -------------------------------------------------------------------------------- 1 | # "Друзья друзей" 2 | # У всех людей, по крайне мере я надеюсь, есть друзья. У ваших друзей тоже есть друзья и так далее. 3 | # Вы решили запустить свой бизнес и пригласить максимальное количество людей на его открытие. 4 | # Вам в руки попала, как нельзя кстати, база людей со списком их друзей. 5 | # Считаем, что комбинация Имя+Фамилия нам позволяет однозначно идентифицировать человека. 6 | 7 | # Задача 8 | # По предоставленным данным(файл peoples.json) определите: 9 | # 1. Сколько людей придет на открытие, если вы отправляете приглашение конкретному человеку 10 | # (любому, на ваш выбор, из базы), а тот всем друзьям, друзья друзьям и т.д. 11 | 12 | # 2. Какому минимальному числу людей, нужно отправить приглашение, 13 | # чтобы пришли ВСЕ люди, присутствующие в базе? 14 | 15 | 16 | # Сюда отправляем полное решение 17 | -------------------------------------------------------------------------------- /Module7/home_work/peoples.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Вячеслав", 4 | "surname": "Сидоров", 5 | "friends": [ 6 | { 7 | "name": "Дмитрий", 8 | "surname": "Гаврилов" 9 | }, 10 | { 11 | "name": "Владислав", 12 | "surname": "Иванов" 13 | }, 14 | { 15 | "name": "Иван", 16 | "surname": "Быстров" 17 | }, 18 | { 19 | "name": "Андрей", 20 | "surname": "Хмельнов" 21 | }, 22 | { 23 | "name": "Владислав", 24 | "surname": "Барин" 25 | }, 26 | { 27 | "name": "Андрей", 28 | "surname": "Быстров" 29 | }, 30 | { 31 | "name": "Вячеслав", 32 | "surname": "Васин" 33 | } 34 | ] 35 | }, 36 | { 37 | "name": "Вячеслав", 38 | "surname": "Иванов", 39 | "friends": [ 40 | { 41 | "name": "Дмитрий", 42 | "surname": "Гаврилов" 43 | }, 44 | { 45 | "name": "Андрей", 46 | "surname": "Васин" 47 | }, 48 | { 49 | "name": "Иван", 50 | "surname": "Быстров" 51 | }, 52 | { 53 | "name": "Андрей", 54 | "surname": "Хмельнов" 55 | }, 56 | { 57 | "name": "Петр", 58 | "surname": "Иванов" 59 | } 60 | ] 61 | }, 62 | { 63 | "name": "Дмитрий", 64 | "surname": "Гаврилов", 65 | "friends": [ 66 | { 67 | "name": "Андрей", 68 | "surname": "Быстров" 69 | }, 70 | { 71 | "name": "Дмитрий", 72 | "surname": "Быстров" 73 | }, 74 | { 75 | "name": "Андрей", 76 | "surname": "Васин" 77 | }, 78 | { 79 | "name": "Владислав", 80 | "surname": "Иванов" 81 | }, 82 | { 83 | "name": "Алексей", 84 | "surname": "Иванов" 85 | }, 86 | { 87 | "name": "Вячеслав", 88 | "surname": "Барин" 89 | } 90 | ] 91 | }, 92 | { 93 | "name": "Андрей", 94 | "surname": "Васин", 95 | "friends": [ 96 | { 97 | "name": "Андрей", 98 | "surname": "Хмельнов" 99 | }, 100 | { 101 | "name": "Петр", 102 | "surname": "Иванов" 103 | }, 104 | { 105 | "name": "Алексей", 106 | "surname": "Сидоров" 107 | }, 108 | { 109 | "name": "Вячеслав", 110 | "surname": "Васин" 111 | }, 112 | { 113 | "name": "Алексей", 114 | "surname": "Иванов" 115 | } 116 | ] 117 | }, 118 | { 119 | "name": "Владислав", 120 | "surname": "Иванов", 121 | "friends": [ 122 | { 123 | "name": "Вячеслав", 124 | "surname": "Иванов" 125 | }, 126 | { 127 | "name": "Андрей", 128 | "surname": "Хмельнов" 129 | }, 130 | { 131 | "name": "Владислав", 132 | "surname": "Барин" 133 | }, 134 | { 135 | "name": "Петр", 136 | "surname": "Иванов" 137 | }, 138 | { 139 | "name": "Алексей", 140 | "surname": "Сидоров" 141 | }, 142 | { 143 | "name": "Дмитрий", 144 | "surname": "Быстров" 145 | }, 146 | { 147 | "name": "Вячеслав", 148 | "surname": "Барин" 149 | }, 150 | { 151 | "name": "Вячеслав", 152 | "surname": "Куролесов" 153 | }, 154 | { 155 | "name": "Иван", 156 | "surname": "Хмельнов" 157 | } 158 | ] 159 | }, 160 | { 161 | "name": "Иван", 162 | "surname": "Гриб", 163 | "friends": [ 164 | { 165 | "name": "Андрей", 166 | "surname": "Хмельнов" 167 | }, 168 | { 169 | "name": "Андрей", 170 | "surname": "Быстров" 171 | }, 172 | { 173 | "name": "Вячеслав", 174 | "surname": "Куролесов" 175 | }, 176 | { 177 | "name": "Иван", 178 | "surname": "Хмельнов" 179 | } 180 | ] 181 | } 182 | ] -------------------------------------------------------------------------------- /Module7/practice/01_Maze-1/img/maze-task01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module7/practice/01_Maze-1/img/maze-task01.png -------------------------------------------------------------------------------- /Module7/practice/01_Maze-1/maze1.py: -------------------------------------------------------------------------------- 1 | # Выверите и скопируйте сюда наиболее подходяший алгоритм для работы с графом(bfs/dfs) 2 | 3 | # Опишите список смежности по изображению лабиринта из файла task.md 4 | graph = [ 5 | ... 6 | ] 7 | 8 | # Решите задачу и выведите ответ в нужном формате 9 | -------------------------------------------------------------------------------- /Module7/practice/01_Maze-1/task.md: -------------------------------------------------------------------------------- 1 | ### Задание "Лабиринт-1" 2 | Дана схема лабиринта: 3 | 4 | 5 | 6 | Дана схема района, указано местоположение вашего дома и банка. 7 | 8 | **Определите**: Можно ли добраться из дома до банка, описав схему района в виде "списока смежности" и расположение объектов (дом, банк). 9 | 10 | **Выведите ответ в формате:** 11 | 12 | **Сan/can't** go to the **bank** 13 | -------------------------------------------------------------------------------- /Module7/practice/02_Maze-2/img/maze-task02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module7/practice/02_Maze-2/img/maze-task02.png -------------------------------------------------------------------------------- /Module7/practice/02_Maze-2/maze2.py: -------------------------------------------------------------------------------- 1 | # Скопируйте решение из предыдущей задачи(Maze-1) и адаптируйте под условия текущей задачи 2 | # Чем меньше пришлось вносить изменений в код программы, тем лучше было решение предыдущей задачи 3 | 4 | 5 | # Решите задачу и выведите ответ в нужном формате 6 | -------------------------------------------------------------------------------- /Module7/practice/02_Maze-2/task.md: -------------------------------------------------------------------------------- 1 | ### Задание "Лабиринт-2" 2 | Дана схема лабиринта: 3 | 4 | 5 | 6 | Схема района и расположение объектов изменились. 7 | 8 | Адаптируйте решение из задания "Maze-1" для новой конфигурации лабиринта 9 | 10 | **Выведите ответ в формате:** 11 | 12 | **Сan/can't** go to the **bank** 13 | -------------------------------------------------------------------------------- /Module7/practice/03_Maze-3/img/maze-task03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module7/practice/03_Maze-3/img/maze-task03.png -------------------------------------------------------------------------------- /Module7/practice/03_Maze-3/maze3.py: -------------------------------------------------------------------------------- 1 | # Скопируйте решение из предыдущей задачи и адаптируйте под условия текущей задачи 2 | # Чем меньше пришлось вносить изменений в код программы, тем лучше было решение предыдущей задачи 3 | 4 | 5 | # Решите задачу и выведите ответ в нужном формате 6 | -------------------------------------------------------------------------------- /Module7/practice/03_Maze-3/task.md: -------------------------------------------------------------------------------- 1 | ### Задание "Лабиринт-3" 2 | Дана схема лабиринта: 3 | 4 | 5 | 6 | Снова меняем схему района, а так же добавляем новый объект - "Магазин". 7 | 8 | Адаптируйте решение из предыдущей задачи для новой конфигурации лабиринта и нового объекта. 9 | 10 | **Выведите ответ в формате:** 11 | 12 | **Сan/can't** go to the **bank** \ 13 | **Сan/can't** go to the **shop** 14 | -------------------------------------------------------------------------------- /Module7/practice/04_Maze-4/img/maze-task04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module7/practice/04_Maze-4/img/maze-task04.png -------------------------------------------------------------------------------- /Module7/practice/04_Maze-4/maze4.py: -------------------------------------------------------------------------------- 1 | # Скопируйте решение из предыдущей задачи и адаптируйте под условия текущей задачи 2 | # Чем меньше пришлось вносить изменений в код программы, тем лучше было решение предыдущей задачи 3 | 4 | 5 | # Решите задачу и выведите ответ в нужном формате 6 | -------------------------------------------------------------------------------- /Module7/practice/04_Maze-4/task.md: -------------------------------------------------------------------------------- 1 | ### Задание "Лабиринт-4" 2 | Дана схема лабиринта: 3 | 4 | 5 | 6 | Снова меняем схему района, а так же добавляем еще один объект - "Бар>". 7 | 8 | Адаптируйте решение из предыдущей задачи для новой конфигурации лабиринта и нового объекта. 9 | 10 | **Выведите ответ в формате:** 11 | 12 | **Сan/can't** go to the **bank** \ 13 | **Сan/can't** go to the **shop** \ 14 | **Сan/can't** go to the **bar** -------------------------------------------------------------------------------- /Module7/practice/05_Maze-with-door/img/maze-with-door-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module7/practice/05_Maze-with-door/img/maze-with-door-task.png -------------------------------------------------------------------------------- /Module7/practice/05_Maze-with-door/maze_door.py: -------------------------------------------------------------------------------- 1 | # Сюда отправляем решение задачи "Лабиринт с дверьми" 2 | # Подумайте, как можно моделировать двери, используя существующие алгоритмы работы с графами. 3 | 4 | 5 | # Решите задачу и выведите ответ в нужном формате 6 | -------------------------------------------------------------------------------- /Module7/practice/05_Maze-with-door/task.md: -------------------------------------------------------------------------------- 1 | ### Задание "Лабиринт с дверьми" 2 | Дана схема лабиринта: 3 | 4 | 5 | 6 | S-1, S-2, S-3 - точки старта \ 7 | K - ключи \ 8 | D - двери 9 | 10 | Посетив клетку K, можно подобрать ключ, который отпирают любую дверь(D). \ 11 | Любым ключом можно открыть любое количество дверей 12 | 13 | **Выведите ответ в формате:**: \ 14 | Из точки S-... можно добраться до финиша, используя ключ \ 15 | ... \ 16 | Из точки S-... можно добраться до финиша без ключа \ 17 | ... \ 18 | Из точки S-... нельзя добраться до финиша 19 | 20 | -------------------------------------------------------------------------------- /Module7/practice/06_Maze-with-treasure/img/maze-with-T-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module7/practice/06_Maze-with-treasure/img/maze-with-T-task.png -------------------------------------------------------------------------------- /Module7/practice/06_Maze-with-treasure/maze_treasure.py: -------------------------------------------------------------------------------- 1 | # Сюда отправляем решение задачи "Лабиринт с сокровищами" 2 | 3 | 4 | # Решите задачу и выведите ответ в нужном формате 5 | -------------------------------------------------------------------------------- /Module7/practice/06_Maze-with-treasure/task.md: -------------------------------------------------------------------------------- 1 | ### Задание "Лабиринт с сокровищами" 2 | Дана схема лабиринта: 3 | 4 | 5 | 6 | S-1, S-2, S-3 - точки старта \ 7 | Розовые кубы - сокровища. Цифра на них - их ценность 8 | 9 | На какую суммарную ценность можно собрать сокровищ, стартовав из разных точек? 10 | 11 | **Выведите ответ в формате:**: \ 12 | Из точки S-... можно собрать сокровищ суммарной ценностью ... \ 13 | ... \ 14 | Из точки S-... можно собрать сокровищ суммарной ценностью ... 15 | 16 | -------------------------------------------------------------------------------- /Module8/examples/1_inheritance.py: -------------------------------------------------------------------------------- 1 | # Рассмотрим два класса 2 | class Person: 3 | def __init__(self, name): 4 | self.name = name 5 | 6 | def greet(self): 7 | return f"Hi, it's {self.name}" 8 | 9 | 10 | class Employee: 11 | def __init__(self, name, job_title): 12 | self.name = name 13 | self.job_title = job_title 14 | 15 | def greet(self): 16 | return f"Hi, it's {self.name}" 17 | 18 | def my_job(self): 19 | return f"I'm {self.job_title}" 20 | 21 | 22 | # Эти Классы описывают два различных типа объектов 23 | # Часть информации у них общая(атрибуты, методы), а часть отличается 24 | 25 | 26 | # Чтобы избежать дублирования кода, воспользуемся наследованием. 27 | # Наследуем класс Employee от Person: 28 | class Employee(Person): 29 | def __init__(self, name, job_title): 30 | # Вызываем конструктор родителя, чтобы создать атрибут .name 31 | super().__init__(name) 32 | # Добавляем новый атрибут, которого не было у родителя: 33 | self.job_title = job_title 34 | 35 | # Метод greet() - описывать не нужно, он будет унаследован от родителя 36 | 37 | # Описываем новый метод, которого не было у родителя: 38 | def my_job(self): 39 | return f"I'm {self.job_title}" 40 | -------------------------------------------------------------------------------- /Module8/examples/2_types_extension.py: -------------------------------------------------------------------------------- 1 | # ================================ 2 | # Расширение встроенных типов 3 | # ================================ 4 | 5 | 6 | # Расширяем стандартный class dict 7 | class my_dict(dict): 8 | # Добавляем свой метод 9 | def new_method(self): 10 | return "I'm new_method" 11 | 12 | # Добавляем дополнительный функционал к существующему методу 13 | def __setitem__(self, key, value): 14 | print('Setting %r to %r' % (key, value)) 15 | return super().__setitem__(key, value) 16 | 17 | 18 | m_dict = my_dict({1: 2, 2: 3}) 19 | print(m_dict) 20 | 21 | # Данная операция вызывает метод __setitem__ 22 | m_dict["new_key"] = "new_value" 23 | print(m_dict) 24 | 25 | # print(m_dict.keys()) 26 | 27 | print(m_dict.new_method()) 28 | 29 | print("\n***Demo MyList****") 30 | 31 | 32 | class MyList(list): 33 | """ 34 | Список, индексы которого начинатся с 1, а не с 0 35 | """ 36 | def __getitem__(self, offset): 37 | print('(indexing % s at % s)' % (self, offset)) 38 | return list.__getitem__(self, offset - 1) 39 | 40 | x = MyList('abc') # __init__ наследуется из списка 41 | print(x) # __repr__ наследуется из списка 42 | 43 | print(x[1]) # MyList.__getitem__ 44 | print(x[3]) # Изменяет поведение метода суперкласса 45 | 46 | x.append('spam') 47 | print(x) # Атрибуты, унаследованные от суперкласса list 48 | x.reverse() 49 | print(x) 50 | -------------------------------------------------------------------------------- /Module8/practice/Dice/dice.py: -------------------------------------------------------------------------------- 1 | class Dice: 2 | # Тут будет код игрального шестигранного кубика 3 | pass 4 | 5 | # TODO-1: Найти некорректные значение, которые можно записать в атрибут .side и исправьте 6 | 7 | # TODO-2: Создать список из N кубиков, подбросить все и посмотреть количество выпадений каждой стороны 8 | # Формат: 2-ка выпала у 3 кубиков, 3-ка выпала у 2 кубиков 9 | 10 | # TODO-3: Добавить три операции сравнения кубиков(< > ==). Кубики можно сравнивать только после подбрасывания. 11 | # Если кубик выпал 5-кой, то он больше чем кубик выпавший 3-кой 12 | # При сравнении кубиков до подбрасывание выбрасываем исключение TypeError 13 | 14 | # TODO-4: Добавить возможность создавать кубики с произвольным количеством граней: 15 | # Пример: dice6 = Dice(6) - создаем шестигранный кубик 16 | # Пример: dice20 = Dice(20) - создаем двадцатигранный кубик 17 | -------------------------------------------------------------------------------- /Module8/practice/IBank/IBank_part1_1.py: -------------------------------------------------------------------------------- 1 | class Account: 2 | def __init__(self, name: str, passport: str, phone_number: str, start_balance: int = 0): 3 | self.name = name 4 | self.passport = passport 5 | self.phone_number = phone_number 6 | self.balance = start_balance 7 | 8 | def full_info(self) -> str: 9 | """ 10 | Полная информация о счете в формате: "Иван баланс: 100 руб. паспорт: 3200 123456 т.+7-900-200-02-03" 11 | """ 12 | return f"..." 13 | 14 | def __repr__(self) -> str: 15 | """ 16 | :return: Информацию о счете в виде строки в формате "Иван баланс: 100 руб." 17 | """ 18 | return f"..." 19 | 20 | 21 | account1 = Account("Иван", "3230 634563", "+7-900-765-12-34") 22 | print(account1) # При отсутствии .__str__(), вызывает __repr__() 23 | print(account1.full_info()) 24 | 25 | account2 = Account(name="Алексей", phone_number="+7-901-744-22-99", passport="3232 456124", start_balance=500) 26 | print(account2) # При отсутствии .__str__(), вызывает __repr__() 27 | print(account2.full_info()) 28 | -------------------------------------------------------------------------------- /Module8/practice/IBank/IBank_part1_2.py: -------------------------------------------------------------------------------- 1 | class Account: 2 | def __init__(self, name: str, passport: str, phone_number: str, start_balance: int = 0): 3 | self.name = name 4 | self.passport = passport 5 | self.phone_number = phone_number 6 | # self.balance = start_balance 7 | self.__balance = start_balance # TODO: Закрываем прямой доступ к балансу 8 | 9 | def full_info(self) -> str: 10 | """ 11 | Полная информация о счете в формате: "Иван баланс: 100 руб. паспорт: 3200 123456 т.+7-900-200-02-03" 12 | """ 13 | return f"..." 14 | 15 | def __repr__(self) -> str: 16 | """ 17 | :return: Информацию о счете в виде строки в формате "Иван баланс: 100 руб." 18 | """ 19 | return f"..." 20 | 21 | # TODO: реализуйте getter для просмотра баланса 22 | # Подробнее тут: https://pythobyte.com/using-getters-and-setters-in-python-5205-840ed13f/ 23 | @property 24 | def balance(self) -> int: 25 | return ... 26 | 27 | def deposit(self, amount: int) -> None: 28 | """ 29 | Внесение суммы на текущий счет 30 | :param amount: сумма 31 | """ 32 | pass 33 | 34 | def withdraw(self, amount: int) -> None: 35 | """ 36 | Снятие суммы с текущего счета 37 | :param amount: сумма 38 | """ 39 | pass 40 | 41 | 42 | # Создаем тестовый аккаунт: 43 | account1 = Account("Алексей", "3232 456124", "+7-901-744-22-99", start_balance=500) 44 | 45 | # Вносим сумму на счет: 46 | # account1.deposit(600) 47 | # print(account1) 48 | 49 | # Снимаем деньги со счета: 50 | # try: 51 | # account1.withdraw(1000) 52 | # except ValueError as e: 53 | # print(e) 54 | # print(account1) 55 | 56 | # Пробуем снять еще: 57 | # try: 58 | # account1.withdraw(1000) 59 | # except ValueError as e: 60 | # print(e) 61 | # print(account1) 62 | -------------------------------------------------------------------------------- /Module8/practice/IBank/IBank_part1_3.py: -------------------------------------------------------------------------------- 1 | class Account: 2 | # TODO-0: скопируйте реализацию из предыдущего решения 3 | 4 | # TODO-1: напишите реализацию метода transfer() 5 | def transfer(self, target_account: 'Account', amount: int) -> None: 6 | """ 7 | Перевод денег на счет другого клиента 8 | :param target_account: счет клиента для перевода 9 | :param amount: сумма перевода 10 | :return: 11 | """ 12 | pass 13 | 14 | 15 | account1 = Account("Иван", "3230 634563", "+7-900-765-12-34", 1000) 16 | account2 = Account("Алексей", "3232 456124", "+7-901-744-22-99", 200) 17 | 18 | print(account1) 19 | print(account2) 20 | 21 | # Переводим деньги с первого аккаунт на второй: 22 | try: 23 | account1.transfer(account2, 500) 24 | except ValueError as e: 25 | print(e) 26 | 27 | # Проверяем изменения баланса: 28 | print(account1) 29 | print(account2) 30 | 31 | # Переводим еще с первого аккаунт на второй: 32 | try: 33 | account1.transfer(account2, 600) 34 | except ValueError as e: 35 | print(e) 36 | 37 | # Проверяем изменения баланса: 38 | print(account1) 39 | print(account2) 40 | -------------------------------------------------------------------------------- /Module8/practice/IBank/IBank_part1_4[add].py: -------------------------------------------------------------------------------- 1 | class Account: 2 | def __init__(self, name: str, passport: str, phone_number: str, start_balance: int = 0): 3 | pass 4 | 5 | # TODO-0: сюда копируем реализацию класса Account из предыдущей задачи 6 | 7 | # TODO-1: добавьте проверку паспорта и телефона(в конструкторе) на соответствие заданным форматам 8 | # В случае несоответствия выбрасываем исключение ValueError("Неверный формат телефона/паспорта") 9 | # Проверка информации на корректность - валидация 10 | # Готовые валидаторы можете взять в директории helpers 11 | pass 12 | 13 | 14 | account1 = Account("Иван", "3230 634563", "+7-900-765-12-34", 1000) # аккаунт с корректными данными 15 | account2 = Account("Алексей", "323 456124", "+7-901-744-22-99") # номер паспорта задан неверно 16 | account3 = Account("Петр", "3232 456124", "+7-904-745-47", 400) # номер телефона задан неверно 17 | -------------------------------------------------------------------------------- /Module8/practice/IBank/IBank_part2.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | # класс для хранения информации об операциях 5 | class Operation: 6 | # Типы операций храним в свойствах класса 7 | DEPOSIT = 'Пополнение' 8 | WITHDRAW = 'Снятие' 9 | TRANSFER_OUT = 'Перевод' 10 | TRANSFER_IN = 'Поступление' 11 | 12 | # Напоминаю: обращение к этим переменным происходит через имя класса, пример: Operation.WITHDRAW 13 | 14 | def __init__(self, type, amount, target_account=None): 15 | self.type = type 16 | self.amount = amount 17 | self.target_account = target_account 18 | 19 | def __repr__(self) -> str: 20 | """ 21 | :return: возвращает строковое представление операции. Формат указан в 02_IBank_part2.md 22 | """ 23 | str_out = f"{self.type} {self.amount} руб." 24 | if self.type == Operation.TRANSFER_OUT: 25 | str_out += f" на счет клиента: {self.target_account.name}" 26 | if self.type == Operation.TRANSFER_IN: 27 | str_out += f" со счета клиента: {self.target_account.name}" 28 | return str_out 29 | 30 | 31 | class Account: 32 | def __init__(self, name: str, passport: str, phone_number: str, start_balance: int = 0): 33 | self.name = name 34 | self.passport = passport 35 | self.phone_number = phone_number 36 | self.__balance = start_balance 37 | # историю храним как список объектов класса Operation, добавив свойство в конструктор: 38 | self.__history: List[Operation] = [] 39 | 40 | # TODO: сюда копируем реализацию методом класса Account из предыдущей задачи 41 | # и реализуем добавление в историю 42 | 43 | # Данный метод дан в готовом виде. Изучите его и используйте как пример, для доработки других 44 | def deposit(self, amount: int, to_history: bool = True) -> None: 45 | """ 46 | Внесение суммы на текущий счет 47 | :param amount: сумма 48 | :param to_history: True - записывать операцию в историю, False - не записывать 49 | """ 50 | self.__balance += amount 51 | if to_history: 52 | operation = Operation(amount, Operation.DEPOSIT) 53 | self.__history.append(operation) 54 | 55 | def get_history(self) -> List[Operation]: 56 | """ 57 | :return: возвращаем историю операций в виде списка операций 58 | """ 59 | return self.__history 60 | 61 | 62 | # Создаем тестовый аккаунт: 63 | account1 = Account("Алексей", "3232 456124", "+7-901-744-22-99", start_balance=500) 64 | 65 | # Выполняем пару операций пополнения: 66 | account1.deposit(200) 67 | account1.deposit(500) 68 | 69 | # Выводим историю операций: 70 | for operation in account1.get_history(): 71 | print(operation) 72 | -------------------------------------------------------------------------------- /Module8/practice/IBank/IBank_part3.py: -------------------------------------------------------------------------------- 1 | # Сюда отправляем готовое решение IBank часть-3 2 | class Operation: 3 | # TODO: сюда копируем реализацию класса Operation из предыдущей задачи 4 | pass 5 | 6 | 7 | class Account: 8 | # TODO: сюда копируем реализацию класса Account из предыдущей задачи 9 | pass 10 | 11 | -------------------------------------------------------------------------------- /Module8/practice/IBank/IBank_part4_1.py: -------------------------------------------------------------------------------- 1 | # Сюда отправляем готовое решение IBank часть-4 2 | class Operation: 3 | # TODO-0: сюда копируем реализацию класса Operation из предыдущей задачи 4 | pass 5 | 6 | 7 | class Account: 8 | pass 9 | # TODO-0: сюда копируем реализацию класса Account из предыдущей задачи 10 | 11 | 12 | # TODO-1: Создаем класс для кредитного аккаунта, наследуясь от аккаунта 13 | class CreditAccount(Account): 14 | def __init__(self, name, passport, phone_number, start_balance=0, negative_limit=0): 15 | # TODO-1: Пока реализуем ТОЛЬКО первый пункт задания "возможность уходить в отрицательный баланс" 16 | # Договоримся, что negative_limit будет положительным числом. 17 | # Например, negative_limit = 500 означает, что мы можем уйти в минус на 500 рублей, self.__balance = -500 18 | pass 19 | -------------------------------------------------------------------------------- /Module8/practice/IBank/IBank_part4_2.py: -------------------------------------------------------------------------------- 1 | # Сюда отправляем готовое решение IBank часть-4 2 | class Operation: 3 | # TODO-0: сюда копируем реализацию класса Operation из предыдущей задачи 4 | pass 5 | 6 | 7 | class Account: 8 | pass 9 | # TODO-0: сюда копируем реализацию класса Account из предыдущей задачи 10 | 11 | 12 | class CreditAccount(Account): 13 | # TODO-0: сюда копируем реализацию класса Account из предыдущей задачи 14 | def __init__(self, name, passport, phone_number, start_balance=0, negative_limit=0): 15 | # TODO-1: Реализуем все оставшиеся пункты задания 16 | # TODO-2: Запускаем тесты 17 | pass 18 | -------------------------------------------------------------------------------- /Module8/practice/IBank/IBank_part5.py: -------------------------------------------------------------------------------- 1 | # Сюда отправляем готовое решение IBank часть-5 2 | class Operation: 3 | # TODO: сюда копируем реализацию класса Operation из предыдущей задачи 4 | pass 5 | 6 | 7 | class Account: 8 | pass 9 | # TODO: сюда копируем реализацию класса Account из предыдущей задачи 10 | 11 | 12 | class CreditAccount(Account): 13 | pass 14 | # TODO: сюда копируем реализацию класса CreditAccount из предыдущей задачи 15 | -------------------------------------------------------------------------------- /Module8/practice/IBank/helpers/validate_passport.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | passport_numbers = ["3200 123456", "3200 12345" , "hello", "320! 12345", "1234 654321"] 4 | pattern = r"\d{4} \d{6}" 5 | 6 | for passport in passport_numbers: 7 | if re.match(pattern, passport): 8 | print(f"Passport number {passport} is correct") 9 | else: 10 | print(f"Passport number {passport} is not correct") -------------------------------------------------------------------------------- /Module8/practice/IBank/helpers/validate_phone_number.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | phone_numbers = ["+7-900-620-10-20", "8-900-620-10-20", "+7-90-62-10-20", "+7 900 620 10 20", "+7-100-100-11-22"] 4 | pattern = r"[+]7-\d{3}-\d{3}-\d{2}-\d{2}" 5 | 6 | for phone_number in phone_numbers: 7 | if re.match(pattern, phone_number): 8 | print(f"Passport number {phone_number} is correct") 9 | else: 10 | print(f"Passport number {phone_number} is not correct") -------------------------------------------------------------------------------- /Module8/practice/IBank/menu_IBank.py: -------------------------------------------------------------------------------- 1 | from IBank_part5 import Account, CreditAccount 2 | 3 | EMPLOYEE_PASSWORD = "123" 4 | 5 | 6 | def close_account(): 7 | """ 8 | Закрыть счет клиента. 9 | Считаем, что оставшиеся на счету деньги были выданы клиенту наличными, при закрытии счета 10 | """ 11 | pass 12 | 13 | 14 | def view_accounts_list(): 15 | """ 16 | Отображение всех клиентов банка в виде нумерованного списка 17 | """ 18 | 19 | 20 | def view_account_by_passport(): 21 | pass 22 | 23 | 24 | def view_client_account(): 25 | """ 26 | Узнать состояние своего счета 27 | """ 28 | pass 29 | 30 | 31 | def put_account(): 32 | """ 33 | Пополнить счет на указанную сумму. 34 | Считаем, что клиент занес наличные через банкомат 35 | """ 36 | pass 37 | 38 | 39 | def withdraw(): 40 | """ 41 | Снять со счета. 42 | Считаем, что клиент снял наличные через банкомат 43 | """ 44 | pass 45 | 46 | 47 | def transfer(): 48 | """ 49 | Перевести на счет другого клиента по номеру телефона 50 | """ 51 | pass 52 | 53 | 54 | def create_new_account(): 55 | print("Укажите данные клиента") 56 | name = input("Имя:") 57 | passport = input("Номер паспорта: ") 58 | phone_number = input("Номер телефона: ") 59 | # TODO: тут создаем новый аккаунт пользователя account = ... 60 | # и добавляем его в accounts.append(account) 61 | 62 | 63 | def client_menu(account): 64 | while True: 65 | print("***********Меню клиента <Иванов И.И.>*************") 66 | print("1. Состояние счета") 67 | print("2. Пополнить счет") 68 | print("3. Снять со счета") 69 | print("4. Перевести деньги другому клиенту банка") 70 | print("5. Exit") 71 | choice = input(":") 72 | if choice == "1": 73 | view_client_account() 74 | elif choice == "2": 75 | put_account() 76 | elif choice == "3": 77 | withdraw() 78 | elif choice == "4": 79 | transfer() 80 | elif choice == "5": 81 | return 82 | # input("Press Enter") 83 | 84 | 85 | def employee_menu(): 86 | while True: 87 | print("***********Меню сотрудника*************") 88 | print("1. Создать новый счет") 89 | print("2. Закрыть счет") 90 | print("3. Посмотреть список счетов") 91 | print("4. Посмотреть счет по номеру паспорта") 92 | print("5. Exit") 93 | choice = input(":") 94 | if choice == "1": 95 | create_new_account() 96 | elif choice == "2": 97 | close_account() 98 | elif choice == "3": 99 | view_accounts_list() 100 | elif choice == "4": 101 | view_account_by_passport() 102 | elif choice == "5": 103 | return 104 | 105 | 106 | def employee_access(): 107 | """ 108 | Проверяет доступ сотрудника банка, запрашивая пароль 109 | """ 110 | password = input("Пароль: ") 111 | if password == EMPLOYEE_PASSWORD: 112 | return True 113 | return False 114 | 115 | 116 | def client_access(accounts): 117 | """ 118 | Находит аккаунт с введеным номером паспорта 119 | Или возвращает False, если аккаунт не найден 120 | """ 121 | try: 122 | passport = int(input("Номер паспорта: ")) 123 | except ValueError: 124 | return False 125 | for account in accounts: 126 | if passport == account.passport8: 127 | return account 128 | 129 | return False 130 | 131 | 132 | def start_menu(): 133 | while True: 134 | print("Укажите вашу роль:") 135 | print("1. Сотрудник банка") 136 | print("2. Клиент") 137 | print("3. Завершить работу") 138 | 139 | choice = input(":") 140 | if choice == "3": 141 | break 142 | elif choice == "1": 143 | if employee_access(): 144 | employee_menu() 145 | else: 146 | print("Указан неверный пароль, укажите роль и повторите попытку...") 147 | elif choice == "2": 148 | account = client_access(accounts) 149 | if account: 150 | client_menu(account) 151 | else: 152 | print("Указан несуществующий пасспорт, укажите роль и повторите попытку...") 153 | else: 154 | print("Указан некорректный пункт меню, повторите выбор...") 155 | 156 | 157 | if __name__ == "__main__": 158 | accounts = [] 159 | start_menu() 160 | -------------------------------------------------------------------------------- /Module8/practice/IBank/tasks/01_IBank_part1.md: -------------------------------------------------------------------------------- 1 | ## ТЗ “I-Bank” Часть-1 2 | 3 | ## Цель 4 | 5 | Разработать класс для консольного приложения “I-Bank” для хранения денежных вкладов и манипуляций с ними. 6 | 7 | 8 | ### Реализуемый функционал 9 | 10 | 1. Создать новый счет для клиента 11 | 1. Узнать состояние счета 12 | 1. Положить деньги на счет 13 | 1. Снять деньги со счета 14 | 1. Перевести деньги на счет другому клиенту 15 | 16 | 17 | ### Подробнее о счете 18 | 19 | При создании нового счета необходимо указать информацию: 20 | 21 | * Имя клиента 22 | * Номер паспорта, строка в формате: "yyyy xxxxxx". \ 23 | Где yyyy - четыре цифры (серия паспорта) \ 24 | xxxxxx - шесть цифр(номер паспорта) 25 | * Номер телефона клиента, строка в формате: "+7-9xx-xxx-xx-xx" 26 | 27 | #### “Создать новый счет” 28 | 29 | Запрашивает данные о клиенте и создает новый объект счета 30 | 31 | 32 | #### “Узнать состояние своего счета” 33 | 34 | Отображает баланс счета в виде строки формата: 35 | 36 | "Иван баланс: 100 руб. паспорт: 3200 123456 т.+7-900-200-02-03" 37 | 38 | #### “Положить деньги на счет” 39 | 40 | Зачисляет(добавляет) указанную сумму на счет клиента. \ 41 | Проверять зачисляемую сумму на корректность не требуется 42 | 43 | **Пояснение:** 44 | Считается, что мы симулируем ситуацию перевода средств, например, с банкомата или через кассу банка. 45 | 46 | #### “Снять деньги со счета” 47 | 48 | Клиент указывает сумму и если на его счету достаточно средств, то сумма списывается со счета. \ 49 | Точно известно, что сумма списания неотрицательное целое число. \ 50 | Если денег на счету недостаточно, то выбрасываем исключение ValueError. \ 51 | Считаем, что клиент не может работать с банком в кредит и его `счет всегда должен оставаться неотрицательным`. 52 | 53 | 54 | #### “Перевести деньги на счет другому клиенту” 55 | 56 | При переводе указываем счет клиента и сумму, которую хотим перевести. Сумма списывается с одного счета и зачисляется на другой. 57 | 58 | Также требуется `проверить наличие переводимой суммы`, на счете отправителя. 59 | 60 | 61 | ## Тестирование 62 | 63 | Выполнив все доработки, проверьте работу своего класса, запустив тесты(`tests/test_account_part1.py`) -------------------------------------------------------------------------------- /Module8/practice/IBank/tasks/02_IBank_part2.md: -------------------------------------------------------------------------------- 1 | ## ТЗ “I-Bank” Часть-2 "История операций" 2 | 3 | Дополнение к документу “ТЗ I-Bank Часть-1” 4 | 5 | 6 | ### Доработки 7 | 8 | 1. Необходимо добавить возможность просмотра всей **истории операций** над счетом клиента(поступление, снятие, переводы) 9 | 10 | ### Формат вывода истории: 11 | 12 | **Пополнение** **600** руб. \ 13 | **Снятие** **400** руб. \ 14 | **Пополнение** **1000** руб. \ 15 | **Перевод** **750** руб. на счет клиента: **Петр** \ 16 | **Поступление** **300** руб. со счета клиента: **Александр** \ 17 | ... 18 | 19 | **Жирным** выделена информация, которая _обязательно_ должна присутствовать в строковом представлении истории операций. 20 | Типы операций должны именоваться именно этими терминами: "Пополнение", "Снятие", "Перевод" и "Поступление". 21 | 22 | **_Обратите внимание!_** Операция "перевод другому клиенту" создает две операции: 23 | 1. Операцию "**Перевод**", на счету отправителя 24 | 2. Операцию "**Поступление**", на счету получателя 25 | 26 | **_Обратите внимание!_** В историю записываем только операции меняющие баланс счета. Например, попытка снять денег больше, 27 | чем есть на счету, будет отклонена и не будет записана в историю. 28 | 29 | ### Правило реализации 30 | 31 | Информацию о каждой операции (пополнение, снятие и т.д.) храним в виде отдельного объекта(см. `iBank_part2.py`) 32 | 33 | ## Тестирование 34 | 35 | Выполнив все доработки, проверьте работу своего класса, запустив тесты(`tests/test_account_part2.py`) -------------------------------------------------------------------------------- /Module8/practice/IBank/tasks/03_IBank_part3.md: -------------------------------------------------------------------------------- 1 | ## ТЗ “I-Bank” Часть-3 "Комиссия" 2 | 3 | Дополнение к документу “ТЗ I-Bank Часть-2” 4 | 5 | 6 | ## Доработки 7 | 8 | 1. За операции **снятие** средств и **перевод** другому клиенту банк будет брать комиссию в размере 2% от суммы операции. 9 | При отображении в истории, комиссия банка должна отображаться явно. \ 10 | _Пример_: **Снятие** **400** руб. (комиссия: **8** руб.) \ 11 | Баланс уменьшается на **408** рублей. \ 12 | _Помните!_ Баланс не может быть отрицательным, т.е. чтобы снять 400 рублей, на счету должно быть минимум 408. 13 | 14 | ## Точность расчетов 15 | 16 | Для простоты расчетов, комиссию всегда считаем целым числом. Округляйте сумму комиссии вниз(к ближайшему целому числу). 17 | 18 | _Пример_: Комиссия от 540, составит 10. 540 * 0.02 = 10.8 --> округл.вниз(10.8) = 10 19 | 20 | ## Подумайте о гибкости реализации 21 | 22 | В текущем задании комиссия составляет 2%, но вполне очевидно, что банк может менять комиссию. Постарайтесь учесть это при разработке. 23 | Попробуйте сделать такую реализацию, чтобы изменение сумы комиссии можно было легко поменять в единственном месте программы. 24 | 25 | ## Тестирование 26 | 27 | Выполнив все доработки, проверьте работу своего класса, запустив тесты(`tests/test_account_part3.py`) 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Module8/practice/IBank/tasks/04_IBank_part4.md: -------------------------------------------------------------------------------- 1 | ## ТЗ “I-Bank” Часть-4 2 | 3 | Дополнение к документу “ТЗ I-Bank Часть-3” 4 | 5 | #### Кредитный счет 6 | 7 | Банк решил реализовать новую услугу “кредитные счета” для своих клиентов. 8 | 9 | Особенности кредитного счета: 10 | 11 | 1. Клиент на кредитном счету может уходить в отрицательный баланс. Размер максимального кредита задается сотрудником, при создании счета(negative_limit). 12 | 1. При отрицательном балансе комиссии на операции “снятие средств” и “перевод другому клиент” возрастают с 2% до 5%. \ 13 | Пояснение: повышенный процент(5%) применяется только при **отрицательном балансе на момент начала операций** "перевода"/"снятия" 14 | 1. При отображении кредитных счетов, они помечаются <К>.(русская буква К) \ 15 | Пример: "<К> Иван баланс: 100 руб. паспорт: 3200 123456 т.+7-900-200-02-03" 16 | 17 | Примечание: появление кредитных счетов не отменяет наличие обычных счетов. Клиенту можно завести как обычный, 18 | так и кредитный счет, в зависимости от его желания. 19 | 20 | ## Тестирование 21 | 22 | Выполнив все доработки, проверьте работу своего класса, запустив тесты(`tests/test_credit_account.py`) -------------------------------------------------------------------------------- /Module8/practice/IBank/tasks/05_IBank_part5.md: -------------------------------------------------------------------------------- 1 | ## ТЗ “I-Bank” Часть-5 2 | 3 | Дополнение к документу “ТЗ I-Bank Часть-4” 4 | 5 | 6 | ## Доработки 7 | 8 | ### Консольная программа 9 | 10 | 1. Используя созданные классы, напишите консольную программу для работы с пользователями. 11 | В качестве заготовки для меню возьмите файл "iBank_menu.py" 12 | 1. Добавьте опцию "Создание кредитного счета" для сотрудника банка 13 | 14 | ### Загрузка и Сохранение информации во внешнем файле 15 | 16 | 1. При старте программа должна загружать информацию об аккаунте пользователя из файла 17 | 1. Перед завершением работы все изменения вносим в файл -------------------------------------------------------------------------------- /Module8/practice/IBank/tasks/img/open_terminal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module8/practice/IBank/tasks/img/open_terminal.jpg -------------------------------------------------------------------------------- /Module8/practice/IBank/tasks/img/stuct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boo-learn/SpecialistPython2_v2/bffbfd4b94f34e2d878ddc272e52444c0cd7d1e0/Module8/practice/IBank/tasks/img/stuct.jpg -------------------------------------------------------------------------------- /Module8/practice/IBank/tasks/run_test.md: -------------------------------------------------------------------------------- 1 | # Запуск тестов: 2 | 1. Рекомендуемая структура проекта: 3 | 4 | 5 | 6 | 1. Установите модуль pytest: `pip install pytest` 7 | 1. Откройте терминал и перейдите в директорию вашего проекта: 8 | 9 | 10 | 11 | 1. В файле с тестом **test_account_part1.py**, исправьте import 12 | 1. В терминале наберите: `python -m pytest -v tests\test_account_part1.py` -------------------------------------------------------------------------------- /Module8/practice/IBank/tests/test_account_part1.py: -------------------------------------------------------------------------------- 1 | # Как запустить тесты? 2 | # Смотри в 'tasks/run_test.md' 3 | 4 | from typing import List 5 | import pytest 6 | from IBank_part1_3 import Account 7 | 8 | 9 | @pytest.fixture 10 | def account() -> Account: 11 | return Account(name="Иван", passport="3230 634563", phone_number="+7-900-765-12-34", start_balance=1000) 12 | 13 | 14 | @pytest.fixture 15 | def accounts() -> List[Account]: 16 | return [ 17 | Account("Иван", "3002 123477", "+7-900-600-10-22", start_balance=200), 18 | Account("Петр", "3002 123456", "+7-900-600-10-20", start_balance=300) 19 | ] 20 | 21 | 22 | def test_create_account(account: Account): 23 | assert account.name == "Иван" 24 | assert account.passport == "3230 634563" 25 | assert account.phone_number == "+7-900-765-12-34" 26 | assert account.balance == 1000 27 | 28 | 29 | def test_full_info(account: Account): 30 | # format: "Иван баланс: 100 руб. паспорт: 3230 634563 т.+7-900-765-12-34" 31 | assert "Иван" in account.full_info() 32 | assert "1000 руб" in account.full_info() 33 | assert "3230 634563" in account.full_info() 34 | assert "+7-900-765-12-34" in account.full_info() 35 | 36 | 37 | def test_deposit(account: Account): 38 | assert account.balance == 1000 39 | account.deposit(400) 40 | assert account.balance == 1400 41 | account.deposit(200) 42 | assert account.balance == 1600 43 | 44 | 45 | def test_withdraw(account: Account): 46 | assert account.balance == 1000 47 | account.withdraw(500) 48 | assert account.balance == 500 49 | 50 | 51 | def test_withdraw_raise(account: Account): 52 | with pytest.raises(ValueError): 53 | account.withdraw(1200) 54 | assert account.balance == 1000 55 | 56 | 57 | def test_transfer(accounts: List[Account]): 58 | account1, account2 = accounts 59 | assert account1.balance == 200 60 | assert account2.balance == 300 61 | account1.transfer(account2, 100) 62 | assert account1.balance == 100 63 | assert account2.balance == 400 64 | 65 | 66 | def test_transfer_raise(accounts: List[Account]): 67 | account1, account2 = accounts 68 | assert account1.balance == 200 69 | assert account2.balance == 300 70 | with pytest.raises(ValueError): 71 | account1.transfer(account2, 250) 72 | assert account1.balance == 200 73 | assert account2.balance == 300 74 | -------------------------------------------------------------------------------- /Module8/practice/IBank/tests/test_account_part2.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import pytest 3 | from IBank_part2 import Account, Operation 4 | 5 | 6 | @pytest.fixture 7 | def account() -> Account: 8 | return Account(name="Иван", passport="3230 634563", phone_number="+7-900-765-12-34", start_balance=1000) 9 | 10 | 11 | @pytest.fixture 12 | def accounts() -> List[Account]: 13 | return [ 14 | Account("Иван", "3002 123477", "+7-900-600-10-22", start_balance=200), 15 | Account("Петр", "3002 123456", "+7-900-600-10-20", start_balance=300) 16 | ] 17 | 18 | 19 | ########################## 20 | # Тесты истории операций # 21 | ########################## 22 | 23 | def test_operation_deposit(account: Account): 24 | assert len(account.get_history()) == 0 # На новом аккаунте не должно быть операций 25 | account.deposit(500) 26 | account.deposit(200) 27 | assert len(account.get_history()) == 2 # Должны быть добавлены ровно две операции 28 | assert Operation.DEPOSIT in str(account.get_history()[0]) 29 | assert "500" in str(account.get_history()[0]) 30 | assert Operation.DEPOSIT in str(account.get_history()[1]) 31 | assert "200" in str(account.get_history()[1]) 32 | 33 | 34 | def test_operation_withdraw(account: Account): 35 | assert len(account.get_history()) == 0 36 | account.withdraw(100) 37 | assert len(account.get_history()) == 1 38 | assert Operation.WITHDRAW in str(account.get_history()[0]) 39 | assert "100" in str(account.get_history()[0]) 40 | 41 | 42 | def test_operation_withdraw_raise(account: Account): 43 | assert len(account.get_history()) == 0 44 | with pytest.raises(ValueError): 45 | account.withdraw(1200) 46 | assert len(account.get_history()) == 0 47 | 48 | 49 | def test_operation_transfer(accounts: List[Account]): 50 | sum_transfer = 200 # Сумма перевода 51 | account_sender, account_recipient = accounts 52 | account_sender.transfer(account_recipient, sum_transfer) 53 | 54 | assert len(account_sender.get_history()) == 1 55 | assert len(account_recipient.get_history()) == 1 56 | 57 | assert Operation.TRANSFER_OUT in str(account_sender.get_history()[0]) 58 | assert Operation.TRANSFER_IN in str(account_recipient.get_history()[0]) 59 | 60 | assert str(sum_transfer) in str(account_sender.get_history()[0]) 61 | assert str(sum_transfer) in str(account_recipient.get_history()[0]) 62 | 63 | assert account_recipient.name in str(account_sender.get_history()[0]) 64 | assert account_sender.name in str(account_recipient.get_history()[0]) 65 | 66 | 67 | def test_operation_transfer_raise(accounts: List[Account]): 68 | sum_transfer = 250 # Сумма перевода 69 | account_sender, account_recipient = accounts 70 | 71 | with pytest.raises(ValueError): 72 | account_sender.transfer(account_recipient, sum_transfer) 73 | 74 | assert len(account_sender.get_history()) == 0 75 | assert len(account_recipient.get_history()) == 0 76 | -------------------------------------------------------------------------------- /Module8/practice/IBank/tests/test_account_part3.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import pytest 3 | from IBank_part3 import Account 4 | 5 | 6 | @pytest.fixture 7 | def account() -> Account: 8 | return Account(name="Иван", passport="3230 634563", phone_number="+7-900-765-12-34", start_balance=1000) 9 | 10 | 11 | @pytest.fixture 12 | def accounts() -> List[Account]: 13 | return [ 14 | Account("Иван", "3002 123477", "+7-900-600-10-22", start_balance=200), 15 | Account("Петр", "3002 123456", "+7-900-600-10-20", start_balance=300) 16 | ] 17 | 18 | 19 | ########################### 20 | # Тесты с учетом комиссии # 21 | ########################### 22 | 23 | # Тестируем только те методы, которые приводят к снятию комиссии 24 | 25 | def test_withdraw(account: Account): 26 | assert account.balance == 1000 27 | account.withdraw(200) 28 | assert account.balance == 796 # С учетом комиссии 2% 29 | account.withdraw(540) 30 | assert account.balance == 246 # Комиссию округляем вниз 31 | 32 | 33 | def test_withdraw_raise(account: Account): 34 | assert account.balance == 1000 35 | with pytest.raises(ValueError): 36 | account.withdraw(1000) # Всю сумму снять нельзя, нужно учесть комиссию 37 | assert account.balance == 1000 38 | 39 | 40 | def test_transfer(accounts: List[Account]): 41 | account1, account2 = accounts 42 | assert account1.balance == 200 43 | assert account2.balance == 300 44 | account1.transfer(account2, 100) 45 | assert account1.balance == 98 # Комиссия берется только с отправителя 46 | assert account2.balance == 400 47 | 48 | 49 | def test_transfer_raise(accounts: List[Account]): 50 | account1, account2 = accounts 51 | assert account1.balance == 200 52 | assert account2.balance == 300 53 | with pytest.raises(ValueError): 54 | account1.transfer(account2, 200) # Всю сумму перевести нельзя, нужно учесть комиссию 55 | assert account1.balance == 200 56 | assert account2.balance == 300 57 | -------------------------------------------------------------------------------- /Module8/practice/IBank/tests/test_credit_account.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import pytest 3 | from IBank_part4_2 import CreditAccount 4 | 5 | 6 | @pytest.fixture 7 | def credit_account() -> CreditAccount: 8 | return CreditAccount(name="Иван", passport="3230 634563", phone_number="+7-900-765-12-34", 9 | start_balance=500, negative_limit=200) 10 | 11 | 12 | @pytest.fixture 13 | def credit_accounts() -> List[CreditAccount]: 14 | return [ 15 | CreditAccount("Иван", "3002 123477", "+7-900-600-10-22", start_balance=200, negative_limit=100), 16 | CreditAccount("Петр", "3002 123456", "+7-900-600-10-20", start_balance=300, negative_limit=150) 17 | ] 18 | 19 | 20 | ############################# 21 | # Тесты кредитного аккаунта # 22 | ############################# 23 | 24 | def test_full_info(credit_account: CreditAccount): 25 | # format: "<К> Иван баланс: 500 руб. паспорт: 3230 634563 т.+7-900-765-12-34" 26 | assert "<К>" in credit_account.full_info() 27 | assert "Иван" in credit_account.full_info() 28 | assert "500 руб" in credit_account.full_info() 29 | assert "3230 634563" in credit_account.full_info() 30 | assert "+7-900-765-12-34" in credit_account.full_info() 31 | 32 | 33 | def test_deposit(credit_account: CreditAccount): 34 | assert credit_account.balance == 500 35 | credit_account.deposite(400) 36 | assert credit_account.balance == 900 37 | 38 | 39 | def test_withdraw(credit_account: CreditAccount): 40 | assert credit_account.balance == 500 41 | credit_account.withdraw(200) 42 | assert credit_account.balance == 796 # С учетом комиссии 2% 43 | credit_account.withdraw(540) 44 | assert credit_account.balance == 246 # Комиссию округляем вниз 45 | 46 | 47 | def test_withdraw_limit(self): 48 | assert credit_account.balance == 500 49 | self.account1.withdraw(600) 50 | self.assertEqual(self.account1.balance, -112) # С учетом комиссии в 2% 51 | 52 | 53 | def test_withdraw_limit_max(self): 54 | assert credit_account.balance == 500 55 | with self.assertRaises(ValueError): 56 | self.account1.withdraw(700) # При балансе 500 и кредите 200, нельзя снять 700, т.к. есть комиссия 57 | 58 | 59 | def test_withdraw_inc_commission_on_negative_balance(self): 60 | assert credit_account.balance == 500 61 | self.account1.withdraw(600) 62 | self.assertEqual(self.account1.balance, -112) # уходим в -баланс. Комиссия 2%, т.к. до снятия был положительный баланс 63 | self.account1.withdraw(50) # снимаем при -балансе. Комиссия 5% (2 рубля с 50) 64 | self.assertEqual(self.account1.balance, -164) 65 | 66 | 67 | def test_transfer(accounts: List[CreditAccount]): 68 | """ 69 | Проверяем успешный перевод средств между кредитными счетами(аккаунтами) 70 | """ 71 | # TODO: напишите данный тест самостоятельно 72 | pass 73 | 74 | 75 | def test_transfer_raise(accounts: List[CreditAccount]): 76 | """ 77 | Проверяем перевод, при нехватке суммы на счету отправителя даже с учетом кредита, между кредитными счетами(аккаунтами) 78 | """ 79 | # TODO: напишите данный тест самостоятельно 80 | pass 81 | -------------------------------------------------------------------------------- /Module9/examples/01_collections_Counter.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | # collections.Counter - вид словаря, который позволяет нам считать количество неизменяемых объектов 4 | counter = collections.Counter() 5 | 6 | for word in ['banana', 'egg', 'banana', 'apple', 'apple', 'apple']: 7 | counter[word] += 1 8 | 9 | print("counter=", counter) # Counter({'apple': 3, 'banana': 2, 'egg': 1}) 10 | 11 | print("counter.elements()-->", list(counter.elements())) # ['banana', 'banana', 'egg', 'apple', 'apple', 'apple'] 12 | # .elements - возвращает список всех элементов 13 | 14 | # Можно создавать так: 15 | counter2 = collections.Counter(a=4, b=2, c=0, d=-2) 16 | print("counter2.elements()-->", list(counter2.elements())) 17 | 18 | # А можно и из строки: 19 | counter3 = collections.Counter('abracadabra') 20 | print("counter3.most_common()-->", counter3.most_common()) # [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)] 21 | print("counter3.most_common(3)-->", counter3.most_common(3)) # [('a', 5), ('b', 2), ('r', 2)] 22 | # Подробнее тут: https://docs.python.org/3/library/collections.html#collections.Counter -------------------------------------------------------------------------------- /Module9/examples/02_collections_deque.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | queue = collections.deque() 4 | 5 | print(queue) # deque([]) - пустая очередь 6 | 7 | queue.append("read book") # Добавляет элмент в очередь 8 | queue.append("sleep") # Добавляет элмент в очередь 9 | print(queue) # deque(['read book', 'sleep']) 10 | 11 | queue.popleft() # Удаляет первый(левый) элемент очереди 12 | print(queue) # deque(['sleep']) 13 | 14 | # Методы очереди: 15 | 16 | # append(x) - добавляет x в конец. 17 | # 18 | # appendleft(x) - добавляет x в начало. 19 | # 20 | # clear() - очищает очередь. 21 | # 22 | # count(x) - количество элементов, равных x. 23 | # 24 | # extend(iterable) - добавляет в конец все элементы iterable. 25 | # 26 | # extendleft(iterable) - добавляет в начало все элементы iterable (начиная с последнего элемента iterable). 27 | # 28 | # pop() - удаляет и возвращает последний элемент очереди. 29 | # 30 | # popleft() - удаляет и возвращает первый элемент очереди. 31 | # 32 | # remove(value) - удаляет первое вхождение value. 33 | # 34 | # reverse() - разворачивает очередь. 35 | # 36 | # rotate(n) - последовательно переносит n элементов из начала в конец (если n отрицательно, то с конца в начало). 37 | 38 | # Подробнее тут: https://docs.python.org/3/library/collections.html#collections.deque 39 | -------------------------------------------------------------------------------- /Module9/examples/03_collections_OrderedDict.py: -------------------------------------------------------------------------------- 1 | # collections.OrderedDict - ещё один похожий на словарь объект, но он помнит порядок, в котором ему были даны ключи. 2 | import collections 3 | 4 | d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2} 5 | o_dict = collections.OrderedDict(sorted(d.items(), key=lambda t: t[0])) 6 | print(o_dict) # OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)]) 7 | 8 | # Методы, которых нет у обычного словаря: 9 | # popitem(last=True) - удаляет последний элемент если last=True, и первый, если last=False. 10 | # move_to_end(key, last=True) - добавляет ключ в конец если last=True, и в начало, если last=False. 11 | 12 | # Подробнее тут: https://docs.python.org/3/library/collections.html#collections.OrderedDict -------------------------------------------------------------------------------- /Module9/examples/04_collections_namedtuple.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | car = collections.namedtuple('Car', 'color max_speed') 4 | # Или так: 5 | # car = collections.namedtuple('Car', ['color', 'max_speed']) 6 | my_car = car('red', 160) 7 | # Car(color='red' , mileage=3812.4) 8 | 9 | print(my_car.color) 10 | # Можно использовать операцию * - распаковка 11 | print(*my_car) # red 160 12 | # Можно обращаться по индексу 13 | print(my_car[0]) # red 14 | # Именованный кортеж умеет выводить себя красиво: 15 | print(my_car) # Car(color='red', max_speed=160) 16 | 17 | # Но менять атрибуты после создания, нельзя: 18 | # my_car.color = 'blue' # вызовет исключение 19 | 20 | # именованные кортежи - краткая форма для создания вручную эффективно работающего с памятью неизменяемого класса. 21 | 22 | # Подробнее тут: https://docs.python.org/3/library/collections.html#collections.namedtuple 23 | -------------------------------------------------------------------------------- /Module9/practice/BlackJack/BlackJack.py: -------------------------------------------------------------------------------- 1 | from classes import Deck, Card 2 | from tools import sum_points 3 | 4 | player_money = 100 # Деньги игрока 5 | rate_value = 10 # Размер ставки 6 | 7 | while True: 8 | # 0. Игрок делает ставку 9 | player_money -= rate_value 10 | if player_money < 0: # Если денег на новую ставку недостаточно, то игра заканчивается 11 | print("У вас закончились деньги. Игра окончена!") 12 | break 13 | print(f"Игрок делает ставку: {rate_value}") 14 | # 1. В начале игры создаем колоду и перемешиваем ее 15 | deck = Deck() 16 | ... 17 | # 2. Игроку выдаем две карты 18 | player_cards = ... 19 | # 3. Дилер берет одну карту 20 | dealer_cards = ... 21 | # 4. Отображаем в консоли карты игрока и дилера 22 | ... 23 | # 5. Проверяем нет ли у игрока блэкджека (21 очко) 24 | if sum_points(player_cards) == 21: 25 | # Выплачиваем выигрышь 3 и 2 26 | player_money += rate_value * 1.5 27 | print(f"Black Jack!!! Вы победили, ваш выигрыш {rate_value * 1.5}") 28 | # Заканчиваем игру 29 | # Если нет блэкджека, то 30 | while True: # Игрок добирает карты пока не скажет "достаточно" или не сделает перебор (>21) 31 | player_choice = input("еще(1)/достаточно(0): ") 32 | if player_choice == "1": 33 | # Раздаем еще одну карту 34 | # Если перебор (>21), заканчиваем добор 35 | if sum_points(player_cards) > 21: 36 | print(f"Перебор: {sum_points(player_cards)} очков") 37 | ... 38 | break 39 | elif player_choice == "0": 40 | # Заканчиваем добирать карты 41 | break 42 | else: # Обработка некорректного ввода 43 | print(...) 44 | 45 | # Если у игрока не 21(блэкджек) и нет перебора, то 46 | if ...: 47 | print("Диллер добирает карты") 48 | while True: # дилер начинает набирать карты. 49 | ... # Смотри подробные правила добора дилера в задании 50 | 51 | # Выясняем кто набрал больше очков. Выплачиваем/забираем ставку 52 | if sum_points(player_cards) > sum_points(dealer_cards): 53 | ... 54 | else: 55 | ... 56 | -------------------------------------------------------------------------------- /Module9/practice/BlackJack/classes.py: -------------------------------------------------------------------------------- 1 | # Возьмите классы Deck и Card с GIST'а занятия. Доработайте классы, если требуется. 2 | class Card: 3 | # Сюда копируем последнюю версию класса Карты 4 | ... 5 | 6 | # Добавляем метод, возвращающий кол-во очков для каждой карты 7 | def points(self): 8 | return Deck.card_points[self.value] 9 | 10 | 11 | class Deck: 12 | # Количество очков, которые дают карты 13 | card_points = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 14 | 'J': 10, 'Q': 10, 'K': 10, 'A': 11} 15 | # Сюда копируем последнюю версию класса Колоды 16 | ... 17 | -------------------------------------------------------------------------------- /Module9/practice/BlackJack/task.md: -------------------------------------------------------------------------------- 1 | ### Консольная игра “Black Jack” 2 | 3 | Написать консольную карточную игру Black Jack для одного игрока против дилера. 4 | 5 | 6 | #### Правила 7 | 8 | Цель — обыграть дилера (крупье). В игре используется колода из 52 карт. 9 | 10 | Значения очков каждой карты: от двойки до десятки — от 2 до 10 соответственно, у туза — 1 или 11 (11 пока общая сумма не больше 21, далее 1), у картинок (король, дама, валет) — 10. 11 | 12 | Игрок до раздачи карт делает ставку в 10 у.е. 13 | 14 | Дилер раздаёт две карты игроку и одну карту себе. Все карты открываются сразу (видны и дилеру, и игроку). 15 | 16 | Если у игрока сразу после раздачи набралось 21 очко (то есть у игрока туз и десяти очковая карта), то такая ситуация и называется _блэкджек_. В таком случае игроку сразу выплачивается выигрыш 3 к 2 (то есть в 1,5 раза превышающий его ставку). 17 | 18 | Если не блекджек, предлагается на выбор либо взять ещё карту (в таком случае игрок должен сказать дилеру «карту»), либо остаться при тех картах (и той сумме очков), которые у него на руке (в этом случае игрок должен сказать дилеру «достаточно»). 19 | 20 | Если у игрока после взятия новой карты сумма очков превышает 21, то такая ситуация называется «перебор». Дилер произносит «много» и снимает ставку игрока в пользу казино. 21 | 22 | Если у дилера в первых двух картах набирается 21 очко (блэкджек), то игрок проигрывает. 23 | 24 | После того, как все игрок завершил брать карты, дилер раздаёт карты себе. 25 | 26 | Общее правило блэкджека состоит в том, что дилер обязан остановиться, как только наберёт 17 очков или выше, и обязан брать, пока не достигнет (даже если у всех не перебравших меньше очков). 27 | 28 | При окончательном подсчете очков в конце раунда сравнивается количество очков игрока и дилера, если победил игрок ему выплачивается выигрыш 2 к 1. Если у дилера больше очков, то ставка игрока уходит в казино. 29 | 30 | Если у игрока и дилера число очков на руках равное, в такой ситуации все остаются при своих ставках, никто не выигрывает и не проигрывает. 31 | 32 | 33 | #### Рекомендации 34 | 35 | Доработайте класс карты, чтобы каждая карта знала/хранила кол-во очков. 36 | 37 | 38 | #### Материалы 39 | 40 | Можете написать код полностью с нуля, но лучше воспользоваться заготовками. 41 | 42 | Файл: **BlackJack.py** - шаблон-заготовка к программе. 43 | 44 | А классы **Deck** и **Card** возьмите с предыдущих занятий(например с GIST'а). 45 | 46 | 47 | #### Доп.задание - 1 48 | 49 | В предложенной заготовке **BlackJack.py**, реализуется только один игровой раунд, по окончанию которого игра заканчивается. Доработайте игру добавив опции игроку: 50 | 51 | 52 | 53 | * Посмотреть счет 54 | * Пополнить счет 55 | * Сыграть еще партию 56 | * Покинуть стол 57 | 58 | 59 | #### Доп.задание - 2 60 | 61 | В реальной игре используется от одной до восьми колод. Из-за того что вероятность комбинации блэкджек при большем числе колод ниже, то преимущество игрока уменьшается при увеличении числа колод. 62 | 63 | Доработайте свою реализацию игры так, чтобы можно было играть любым количеством колод. 64 | 65 | **Подсказка**: реализуйте операцию умножения колоды на целое число, тем самым дублируя все карты в колоде. По факту, три колоды - это одна колода, в которой все карты присутствуют в трех экземплярах. 66 | 67 | 68 | #### Доп.задание - 3 69 | 70 | Доработайте свою программу так, чтобы весь процесс игры логировался(записывался в текстовый файл). 71 | 72 | Открыв такой файл, всегда можно было понять как проходила та или иная игра. -------------------------------------------------------------------------------- /Module9/practice/BlackJack/tools.py: -------------------------------------------------------------------------------- 1 | def sum_points(cards): 2 | """ 3 | Напишите отдельную функцию для нахождения суммы очков всех карт в списке 4 | :param cards: список карт(рука игрока или диллера) 5 | :return: сумму очков 6 | """ 7 | # Совет: храните кол-во очков за карту внутри класса Колоды(колода "знает", сколько дает очков каждая карта) 8 | 9 | # Сначала считаем сумму карт, считая ТУЗ за 11-очков 10 | sum_points = ... 11 | # Если сумма > 21, то перечитываем сумму, считая ТУЗ за 1(единицу) 12 | if sum_points > 21: 13 | ... 14 | 15 | return sum_points 16 | -------------------------------------------------------------------------------- /Module9/practice/collection_tasks/01_task_collect.py: -------------------------------------------------------------------------------- 1 | # Частотный анализ — это подсчёт, какие символы чаще встречаются в тексте. 2 | # Это важнейший инструмент взлома многих классических шифров — 3 | # от шифра Цезаря до шифровальной машины «Энигма». 4 | # Выполним простой частотный анализ: выясним, какой символ чаще всего 5 | # встречается в данном тексте. 6 | 7 | # Входные данные: 8 | # Произвольный текст 9 | # TODO: your code here... 10 | -------------------------------------------------------------------------------- /Module9/practice/collection_tasks/02_task_collect.py: -------------------------------------------------------------------------------- 1 | # Каждый ученик в классе изучает либо английский, либо французский, либо оба этих языка. 2 | # У классного руководителя есть списки учеников, изучающих английский и французский языки. 3 | # Помогите ему выяснить, сколько учеников в классе изучают только один язык. 4 | 5 | # Входные данные: 6 | # Для каждого ученика известны: Имя Фамилия и список изучаемых языков 7 | 8 | # Для решения задачи подберите наиболее удобную структуру и заполните 9 | # Выведите: учеников, изучающих только один язык 10 | 11 | # TODO: your code here... 12 | -------------------------------------------------------------------------------- /Module9/practice/collection_tasks/03_task_collect.py: -------------------------------------------------------------------------------- 1 | # В 7-ом модуле мы изучали "алгоритм поиска в ширину(bfs)". 2 | # Перепишите предложенный алгоритм, используя в качестве очереди класс "Очередь" из модуля collections 3 | # collections.deque() 4 | 5 | # TODO: your code here... 6 | -------------------------------------------------------------------------------- /Module9/practice/collection_tasks/04_task_collect.py: -------------------------------------------------------------------------------- 1 | # Вам дан английский текст. Закодируйте его с помощью азбуки Морзе: 2 | # https://en.wikipedia.org/wiki/Morse_code#/media/File:International_Morse_Code.svg 3 | # Каждая буква заменяется на последовательность точек и тире. 4 | # В качестве тире используйте обычный дефис: «-», а в качестве точки — точку «.». Например, 5 | # буква «g» превратится в трёхсимвольную строку «—.». Между закодированными буквами нужно ставится ровно один пробел. 6 | # Например, слово «Help» превратится в «…. . .-.. .—.». 7 | # Обратите внимание, что строчные и заглавные буквы кодируются одинаково. 8 | 9 | # TODO: your code here... 10 | -------------------------------------------------------------------------------- /Module9/practice/lean_kivy/step1.py: -------------------------------------------------------------------------------- 1 | # pip install kivy 2 | from kivy.app import App 3 | 4 | app = App() 5 | 6 | app.run() 7 | -------------------------------------------------------------------------------- /Module9/practice/lean_kivy/step2.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.uix.button import Button 3 | 4 | 5 | class MyApp(App): 6 | def build(self): 7 | btn = Button( 8 | text="Click me", 9 | font_size = 40, 10 | ) 11 | btn.bind(on_press=on_btn_click) 12 | # Button: https://kivy.org/doc/stable/api-kivy.uix.button.html#module-kivy.uix.button 13 | # btn = Button(text="Click me",pos=(100, 100), size=(200, 100), size_hint=(None, None)) 14 | return btn 15 | 16 | 17 | # callback 18 | def on_btn_click(instance): 19 | print(f"Press on {instance}") 20 | instance.text = "Clicked" 21 | 22 | 23 | if __name__ == "__main__": 24 | app = MyApp() 25 | app.run() 26 | -------------------------------------------------------------------------------- /Module9/practice/lean_kivy/step3.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.uix.button import Button 3 | from kivy.uix.textinput import TextInput 4 | from kivy.uix.label import Label 5 | from kivy.uix.boxlayout import BoxLayout 6 | 7 | 8 | class MyApp(App): 9 | def build(self): 10 | box = BoxLayout(orientation='vertical', padding=15) 11 | # BoxLayout: https://kivy.org/doc/stable/api-kivy.uix.boxlayout.html#module-kivy.uix.boxlayout 12 | # Widgets: https://kivy.org/doc/stable/api-kivy.uix.html 13 | self.input1 = TextInput(hint_text ="Enter your text here...", font_size=40) 14 | self.lbl = Label(text="Base text", font_size=30, color=(0, 1, 0.1)) 15 | self.btn = Button( 16 | text="Click me", 17 | font_size=40, 18 | on_press=self.on_btn_click 19 | ) 20 | # self.btn.bind(on_press=self.on_btn_click) 21 | box.add_widget(self.input1) 22 | box.add_widget(self.lbl) 23 | box.add_widget(self.btn) 24 | return box 25 | 26 | def on_btn_click(self, instance): 27 | self.lbl.text = self.input1.text 28 | 29 | 30 | if __name__ == "__main__": 31 | app = MyApp() 32 | app.run() 33 | -------------------------------------------------------------------------------- /Module9/practice/lean_kivy/step4.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.uix.label import Label 3 | from kivy.uix.button import Button 4 | from kivy.uix.boxlayout import BoxLayout 5 | from kivy.core.window import Window 6 | from kivy.graphics import Color, Rectangle 7 | 8 | 9 | class MyLabel(Label): 10 | def __init__(self, **kwargs): 11 | bg_color = kwargs.get('bg_color') 12 | if bg_color: 13 | self.bg_color = bg_color 14 | del kwargs['bg_color'] 15 | else: 16 | self.bg_color = (0, 0, 0) 17 | super(MyLabel, self).__init__(**kwargs) 18 | 19 | def on_size(self, *args): 20 | self.canvas.before.clear() 21 | with self.canvas.before: 22 | Color(*self.bg_color) 23 | Rectangle(pos=self.pos, size=self.size) 24 | 25 | 26 | class MyApp(App): 27 | def build(self): 28 | box = BoxLayout(padding=20, spacing=40) 29 | lbl1 = MyLabel( 30 | text='Метка с фоном', 31 | font_size="40", 32 | color=(0, 1, 0), 33 | bg_color=(0, 0, 1), 34 | ) 35 | lbl2 = Label( 36 | text="Обычная метка", 37 | ) 38 | 39 | box.add_widget(lbl1) 40 | box.add_widget(lbl2) 41 | return box 42 | 43 | 44 | app = MyApp() 45 | 46 | app.run() 47 | -------------------------------------------------------------------------------- /Module9/practice/lean_kivy/task1_TicTacToe.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.uix.button import Button 3 | from kivy.uix.textinput import TextInput 4 | from kivy.uix.label import Label 5 | from kivy.uix.gridlayout import GridLayout 6 | from kivy.core.window import Window 7 | 8 | Window.size = (400, 500) 9 | 10 | 11 | class MyApp(App): 12 | def build(self): 13 | grid = GridLayout(padding=15, cols=3) 14 | # GridLayout: https://kivy.org/doc/stable/api-kivy.uix.gridlayout.html 15 | # Widgets: https://kivy.org/doc/stable/api-kivy.uix.html 16 | self.cell1 = Button(on_press=self.on_btn_click, font_size=40) 17 | self.cell2 = Button(font_size=40) 18 | self.cell3 = Button(font_size=40) 19 | self.cell4 = Button(font_size=40) 20 | self.cell5 = Button(font_size=40) 21 | self.cell6 = Button(font_size=40) 22 | self.cell7 = Button(font_size=40) 23 | self.cell8 = Button(font_size=40) 24 | self.cell9 = Button(font_size=40) 25 | self.lbl_status = Label(text="Ходит: X") 26 | grid.add_widget(self.cell1) 27 | grid.add_widget(self.cell2) 28 | grid.add_widget(self.cell3) 29 | grid.add_widget(self.cell4) 30 | grid.add_widget(self.cell5) 31 | grid.add_widget(self.cell6) 32 | grid.add_widget(self.cell7) 33 | grid.add_widget(self.cell8) 34 | grid.add_widget(self.cell9) 35 | grid.add_widget(self.lbl_status) 36 | return grid 37 | 38 | def on_btn_click(self, instance): 39 | instance.text = 'X' 40 | self.lbl_status.text = "Ходит: O" 41 | 42 | 43 | # TODO: дана заготовка игры "Крестики-нолики". Закончите игру. 44 | # TODO: Когда кто-то выстраивает вряд/по диагонали кри крестика или три нолика, в поле self.lbl_status, вывести: "победил Х". 45 | # TODO: Когда выставлены все крестики или нолики(занято все поле), в поле self.lbl_status, вывести: "Конец игры. Ничья!" 46 | if __name__ == "__main__": 47 | app = MyApp() 48 | app.run() 49 | --------------------------------------------------------------------------------