3  Цикли

Data Miorsh Ihor Miroshnychenko Youtube Monobank

Тепер ми зосередимося на циклах, можливості в Python та багатьох інших мовах програмування робити щось знову і знову, своєрідному циклі. Почнемо з мотивації, а потім перейдемо до практичних прикладів.

Створимо програму cat.py, яка буде нявкати, як кішка.

Terminal
code cat.py

Для початку зробимо так, щоб вона нявкала три рази:

print("Няв!")
print("Няв!")
print("Няв!")
Няв!
Няв!
Няв!

Все працює, але давайте подивимось на блок-схему цієї програми:

%%{init:{"theme":"base", "flowchart": {"htmlLabels": true}}}%%

flowchart TB
    A(Початок) --> B["'Няв!'"]
    B --> C["'Няв!'"]
    C --> D["'Няв!'"]
    D --> E(Кінець)
Рисунок 3.1: Блок-схема програми cat.py

Чому мій код погано спроектований? Давайте розглянемо логічне продовження. Припустимо, я хочу надрукувати “няв” чотири рази, або п’ять разів, або 50 разів, або 500 разів. В Python є ключове слово, яке називається while - це один із способів виразити те, що називається циклом, блоком коду, який буде робити щось знову, і знову.

3.1 Цикл while

Ключове слово while - це конструкція, яка дозволяє мені ставити питання знову і знову. Кожного разу, коли ми бачили питання, воно було у формі булевого виразу, True або False. Повертаючись до нашої попередньої програми, як я можу тричі надрукувати 'Няв!' і тричі поставити запитання, відповідь на яке була б True або False? Для цього нам необхідно задати змінну, яка буде відповідати за кількість нявкань. Назвемо її i (від ітерація). Ініціалізуємо її значенням 3. Потім ми можемо поставити питання: чи менше i за 0? Якщо так, то ми надрукуємо 'Няв!' і зменшимо i на одиницю. Це буде виглядати так:

i = 3
while i > 0:
    print("Няв!")
    i = i - 1
Няв!
Няв!
Няв!

Тепер давайте подивимось на блок-схему цієї програми:

%%{init:{"theme":"base", "flowchart": {"htmlLabels": true}}}%%

flowchart TB
    A(Початок) --> B["i = 3"]
    B --> C{"i > 0"}
    C -- True --> D["'Няв!'"]
    D --> E["i = i - 1"]
    E --> C
    C -- False --> F(Кінець)
Рисунок 3.2: Блок-схема програми cat.py з циклом while

Цю задачу можна вирішити дещо й іншим шляхом. Програмісти досить часто починають відлік з нуля. Це умовність, і вона має навіть свої переваги. Тож ми ініціалізуємо i значенням 0, але змінимо умову на i < 3. І тепер ми можемо збільшувати i на одиницю, а не зменшувати. Але і це ще не все, у випадках коли ми збільшуємо або зменшуємо якесь число, ми можемо скористатися спеціальними операторами += і -=. Таким чином, наш код можна спростити до наступного вигляду:

i = 0
while i < 3:
    print("Няв!")
    i += 1
Няв!
Няв!
Няв!

Такий підхід називається “синтаксичним цукром” (англ. syntactic sugar), тобто це не новий функціонал, а лише спрощений синтаксис для існуючого функціоналу. Такий підхід дозволяє зробити код трошки читабельним і зрозумілим.

Давайте подивимось на блок-схему цієї програми:

%%{init:{"theme":"base", "flowchart": {"htmlLabels": true}}}%%

flowchart TB
    A(Початок) --> B["i = 0"]
    B --> C{"i < 3"}
    C -- True --> D["'Няв!'"]
    D --> E["i += 1"]
    E --> C
    C -- False --> F(Кінець)
Рисунок 3.3: Блок-схема програми cat.py з циклом while

3.2 Цикл for та списки

Для демонстрації можливостей циклу for, нам слід познайомитися ще з однією ідеєю в Python, а саме списками list - це структура даних, яка дозволяє зберігати декілька значень у одній змінній. Списки в Python створюються за допомогою квадратних дужок [] і можуть містити будь-які значення, в тому числі інші списки.

Принцип роботи циклу for полягає в тому, що він дозволяє ітераційно перебирати список елементів, наприклад так:

for i in [0, 1, 2]:
    print("Няв!")
Няв!
Няв!
Няв!

Такий код став коротшим, ніж варіант з циклом while. Список у цій програмі - це саме [0, 1, 2]. Але що в цьому варіанті коду не так? Якщо ми захочемо змінити кількість нявкань, нам доведеться змінювати список. Це не дуже зручно. Щоб цього уникнути, ми можемо скористатися функцією range(), яка дозволяє створити список послідовності чисел. Таким чином, ми можемо переписати наш код наступним чином:

for i in range(3):
    print("Няв!")
Няв!
Няв!
Няв!

Дозвольне показати Вам ще дещо пітонічнє: зверніть увагу, що хоча я визначаю змінну i, я ніколи не використовую її. Але в Python є угода, що якщо вам потрібна змінна тільки тому, що функція програмування вимагає від неї певного підрахунку або автоматичного оновлення, але вам байдуже щодо її значення - назвіть цю змінну _. Це не змінить коректність програми, але це є сигнал колегам, які дивляться на ваш код. Це означає, що вам не потрібно буде звертати увагу на цю змінну, коли ви читаєте код:

for _ in range(3):
    print("Няв!")
Няв!
Няв!
Няв!

Чи можна зробити цей код ще більш пітонічним? Так, можна. Оскільки ми використовуємо рядки, які повторюються, ми можемо скористатися операцією множення рядків на число. При цьому слід не забувати, що ми хочемо виводити кожне "Няв!" у новому рядку (за допомогою \n та end=""). Таким чином, ми можемо переписати наш код наступним чином:

print("Няв!\n" * 3, end="")
Няв!
Няв!
Няв!

Давайте запитаємо користувача, скільки разів цей кіт має нявкнути. Але в цьому випадку слід врахувати, що користувач має вказати позитивне число. Якщо користувач введе неправильне значення, ми маємо попросити його ввести число ще раз. Для цього ми можемо скористатися циклом while True, який буде виконуватися доти, доки не буде введено коректне значення. Таким чином, ми можемо переписати наш код наступним чином:

while True:
    n = int(input("Скільки разів кіт має нявкнути? ")) # 3
        if n > 0:
            break

for _ in range(n):
    print("Няв!")
Няв!
Няв!
Няв!

Цикл while буде виконуватися доти, доки не буде введено коректне значення. Якщо користувач введе число, яке менше або дорівнює нулю, то цикл while буде виконуватися знову і знову. Якщо користувач введе коректне значення, то цикл while буде припинено за допомогою інструкції break і виконано цикл for.

Давайте ще трошки попрактикуємо писати власні функції. Напишемо функцію cat(), яка буде нявкати задану кількість разів. Для цього нам потрібно передати цю кількість як аргумент функції. Таким чином, ми можемо переписати наш код наступним чином:

def main():
    number = get_number()
    cat(number)

def get_number():
    while True:
        n = int(input("Скільки разів кіт має нявкнути? "))
        if n > 0:
            break
    return n

def cat(n):
    for _ in range(n):
        print("Няв!")

main()

3.2.1 Індексація списків

Потренуємося працювати з індексами списків. До будь-якого елемента списку можна звернутися за його індексом. Запам’ятайте, що індексація починається з нуля.

fruits = ['apple', 'banana', 'orange']
print(fruits[0])
apple

Також ми можемо робити зрізи:

fruits = ['apple', 'banana', 'orange']
print(fruits[0:2])
['apple', 'banana']

Давайте створимо файл hogwarts.py в якому створимо список учнів Гоґвортсу:

Terminal
code hogwarts.py

Змінну назвемо students і помістимо у неї список із трьох учнів:

students = ["Гаррі Поттер", "Герміона Грейнджер", "Рон Уізлі"]

Як мені роздрукувати список студентів? Для цього я можу скористатися індексом, який вказує на позицію елемента у списку за допомогою квадратних [] дужок після назви змінної. Індекси у списку починаються з нуля. Таким чином, якщо я хочу вивести першого студента, я можу використати індекс 0:

students = ["Гаррі Поттер", "Герміона Грейнджер", "Рон Уізлі"]

print(students[0])
print(students[1])
print(students[2])
Гаррі Поттер
Герміона Грейнджер
Рон Уізлі

Але ж має бути кращий спосіб, чи не так? Особливо, якщо я не знаю заздалегідь, хто буде в цьому списку. Якщо наступного року в Гоґвортсі з’являться нові учні, ми можемо використати цикл for для того, щоб вивести їх імена:

students = ["Гаррі Поттер", "Герміона Грейнджер", "Рон Уізлі"]

for student in students:
    print(student)
Гаррі Поттер
Герміона Грейнджер
Рон Уізлі

Дозвольте продемонструвати альтернативний варіант вирішення цієї задачі. Ми можемо використати комбінацію функції range() для визначення діапазону та функції len() для того, щоб отримати довжину списку. Таким чином, ми можемо переписати наш код наступним чином:

students = ["Гаррі Поттер", "Герміона Грейнджер", "Рон Уізлі"]

for i in range(len(students)):
    print(students[i])
Гаррі Поттер
Герміона Грейнджер
Рон Уізлі

А що, якщо я хочу крім імені студента вивести його номер у списку? Для цього я можу скористатися функцією enumerate(), яка дозволяє мені отримати індекс елемента у списку. Таким чином, я можу переписати наш код наступним чином:

students = ["Гаррі Поттер", "Герміона Грейнджер", "Рон Уізлі"]

for i, student in enumerate(students):
    print(f"{i + 1}: {student}")
1: Гаррі Поттер
2: Герміона Грейнджер
3: Рон Уізлі

3.2.2 Методи списків

Погляньмо на всі методи списку. Не треба заучувати їх напам’ять. Але якщо ви зіткнетеся із завданням, в якому треба буде щось зробити зі списком, то перед тим, як намагатися самому придумати рішення, подивіться, може бути потрібний метод.

  • append() - додає елемент у кінець списку. Наприклад:
fruits = ['apple', 'banana', 'orange']
fruits.append('melon')
print(fruits)
['apple', 'banana', 'orange', 'melon']
  • clear() - видаляє всі елементи списку. Наприклад:
fruits = ['apple', 'banana', 'orange']
fruits.clear()
print(fruits)
[]
  • copy() - повертає копію списку. Наприклад:
fruits = ['apple', 'banana', 'orange']
fruits_copy = fruits.copy()
print(fruits_copy)
['apple', 'banana', 'orange']
  • count(item) - повертає кількість елементів із заданим значенням. Наприклад:
fruits = ['apple', 'banana', 'orange', 'banana']
print(fruits.count('banana'))
2
  • extend(iterable) - додає елементи іншого списку до поточного. Наприклад:
fruits = ['apple', 'banana', 'orange']
fruits.extend(['melon', 'watermelon'])
print(fruits)
['apple', 'banana', 'orange', 'melon', 'watermelon']
  • index(item, start, end) - повертає індекс першого елемента, який збігається із заданим значенням (item) у діапазоні індексів від start до end. Наприклад:
fruits = ['apple', 'banana', 'orange', 'banana']
print(fruits.index('banana'))
1
  • insert(index, item) - додає елемент item на позицію index. Наприклад:
fruits = ['apple', 'banana', 'orange']
fruits.insert(1, 'melon')
print(fruits)
['apple', 'melon', 'banana', 'orange']
  • pop(index) - видаляє та повертає елемент із заданим індексом. Якщо індекс не вказано, видаляє та повертає останній елемент списку. Наприклад:
fruits = ['apple', 'banana', 'orange']
removed_fruit = fruits.pop(1)
print(removed_fruit)
banana
  • remove(item) - видаляє перший елемент із заданим значенням. Наприклад:
fruits = ['apple', 'banana', 'orange']
fruits.remove('banana')
print(fruits)
['apple', 'orange']
  • reverse() - змінює порядок елементів у списку на зворотній. Наприклад:
fruits = ['apple', 'banana', 'orange']
fruits.reverse()
print(fruits)
['orange', 'banana', 'apple']
  • sort(key, reverse) - сортує елементи списку. Наприклад:
fruits = ['banana', 'orange', 'apple']
fruits.sort()
print(fruits)
['apple', 'banana', 'orange']

3.3 Словники

Розглянемо ще один тип структури даних в Python - словники dict. Словники в Python створюються за допомогою фігурних дужок {} і містять пари ключ-значення. Ключі у словниках мають бути унікальними, тобто не можуть повторюватися. Значення у словниках можуть бути будь-якого типу, в тому числі інші словники.

Припустимо, що ми хочемо відстежувати, хто до якого гуртожитку відноситься в Гоґвортсі. Для прикладу візьмемо чотирьох учнів:

Герміона Грейнджер Гаррі Поттер Рон Уізлі Драко Малфой
Ґрифіндор Ґрифіндор Ґрифіндор Слизерин

Тож давайте додамо ще один створимо словник students:

students = {
    "Герміона Грейнджер": "Ґрифіндор",
    "Гаррі Поттер": "Ґрифіндор",
    "Рон Уізлі": "Ґрифіндор",
    "Драко Малфой": "Слизерин"
}

Тепер давайте виведемо на екран ім’я та гуртожиток кожного учня. Для цього ми можемо скористатися циклом for. Але якщо ми спробуємо використати цикл for таким чином, як ми це робили раніше, то ми отримаємо лише імена учнів:

students = {
    "Герміона Грейнджер": "Ґрифіндор",
    "Гаррі Поттер": "Ґрифіндор",
    "Рон Уізлі": "Ґрифіндор",
    "Драко Малфой": "Слизерин"
}

for student in students:
    print(student)
Герміона Грейнджер
Гаррі Поттер
Рон Уізлі
Драко Малфой

Щоб вивести ім’я та гуртожиток кожного учня, ми можемо скористатися індексацією словника за ключем. Індексація словника за ключем відбувається за допомогою квадратних дужок [] після назви змінної. Таким чином, ми можемо переписати наш код наступним чином:

students = {
    "Герміона Грейнджер": "Ґрифіндор",
    "Гаррі Поттер": "Ґрифіндор",
    "Рон Уізлі": "Ґрифіндор",
    "Драко Малфой": "Слизерин"
}

for student in students:
    print(f"{student}: {students[student]}")
Герміона Грейнджер: Ґрифіндор
Гаррі Поттер: Ґрифіндор
Рон Уізлі: Ґрифіндор
Драко Малфой: Слизерин

Давайте ускладнимо задачу і додамо ще одину характеристику до кожного учня - його Патронуса:

Ім’я Гуртожиток Патронус
Герміона Грейнджер Ґрифіндор Видра
Гаррі Поттер Ґрифіндор Олень
Рон Уізлі Ґрифіндор Тер’єр
Драко Малфой Слизерин

Для цього ми можемо використати список, який містить словники. Таким чином, ми можемо переписати наш код наступним чином:

students = [
    {
        "ім'я": "Герміона Грейнджер",
        "гуртожиток": "Ґрифіндор",
        "патронус": "Видра"
    },
    {
        "ім'я": "Гаррі Поттер",
        "гуртожиток": "Ґрифіндор",
        "патронус": "Олень"
    },
    {
        "ім'я": "Рон Уізлі",
        "гуртожиток": "Ґрифіндор",
        "патронус": "Тер'єр"
    },
    {
        "ім'я": "Драко Малфой",
        "гуртожиток": "Слизерин",
        "патронус": None
    }
]

Зверніть увагу, що згідно канонічного варіанту Драко Малфой не має Патронуса. Тому ми вказали його значення як None - це спеціальне значення, яке означає “нічого”.

Для виводу інформації про учнів ми можемо скористатися циклом for:

students = [
    {
        "ім'я": "Герміона Грейнджер",
        "гуртожиток": "Ґрифіндор",
        "патронус": "Видра"
    },
    {
        "ім'я": "Гаррі Поттер",
        "гуртожиток": "Ґрифіндор",
        "патронус": "Олень"
    },
    {
        "ім'я": "Рон Уізлі",
        "гуртожиток": "Ґрифіндор",
        "патронус": "Тер'єр"
    },
    {
        "ім'я": "Драко Малфой",
        "гуртожиток": "Слизерин",
        "патронус": None
    }
]

for student in students:
    print(student["ім'я"], student["гуртожиток"], student["патронус"], sep=", ")
Герміона Грейнджер, Ґрифіндор, Видра
Гаррі Поттер, Ґрифіндор, Олень
Рон Уізлі, Ґрифіндор, Тер'єр
Драко Малфой, Слизерин, None

Альтернативний варіант створення словника students - це використання вкладених словників:

students = {
    "Герміона Грейнджер": {
        "гуртожиток": "Ґрифіндор",
        "патронус": "Видра"
    },
    "Гаррі Поттер": {
        "гуртожиток": "Ґрифіндор",
        "патронус": "Олень"
    },
    "Рон Уізлі": {
        "гуртожиток": "Ґрифіндор",
        "патронус": "Тер'єр"
    },
    "Драко Малфой": {
        "гуртожиток": "Слизерин",
        "патронус": None
    }
}

for student in students:
    print(student, students[student]["гуртожиток"], students[student]["патронус"], sep=", ")
Герміона Грейнджер, Ґрифіндор, Видра
Гаррі Поттер, Ґрифіндор, Олень
Рон Уізлі, Ґрифіндор, Тер'єр
Драко Малфой, Слизерин, None

3.3.1 Створення словника

У Python є кілька способів створення словників. Ось деякі з них:

  1. Літерали словника

Літерали словника являють собою список ключів і значень, укладених у фігурні дужки. Ключ і значення розділяються двокрапкою, а пари ключ-значення розділяються комою. Наприклад:

my_dict = {'ім\'я': 'Аліса', 'вік': 25, 'місто': 'Київ'}
print(my_dict)
{"ім'я": 'Аліса', 'вік': 25, 'місто': 'Київ'}
  1. Вбудована функція dict()

Функцію dict() можна використовувати для створення словників з інших послідовностей або для створення порожнього словника. Наприклад:

empty_dict = dict()
print(empty_dict)
{}
fruit_dict = dict([('яблуко', 5), ('банан', 3), ('апельсин', 2)])
print(fruit_dict)
{'яблуко': 5, 'банан': 3, 'апельсин': 2}
  1. Генератор словників

Генератори словників дозволяють створювати словники на основі інших послідовностей. Наприклад:

fruit_list = ['яблуко', 'банан', 'апельсин']
fruit_dict = {fruit: len(fruit) for fruit in fruit_list}
print(fruit_dict)
{'яблуко': 6, 'банан': 5, 'апельсин': 8}
  1. Метод fromkeys()

Метод fromkeys() дає змогу створити словник із зазначеними ключами й одним і тим самим значенням для всіх ключів. Наприклад:

fruit_list = ['яблуко', 'банан', 'апельсин']
fruit_dict = {}.fromkeys(fruit_list, 0)
print(fruit_dict)
{'яблуко': 0, 'банан': 0, 'апельсин': 0}

Пам’ятаєте, ми з вами говорили про frozenset (див. 10.1.2)? Одна з його корисних особливостей - frozenset можна використовувати як ключ словника. Припустимо, ми хочемо як ключ, зберігати одразу кілька значень - ім’я користувача і його вік.

students_courses = {}
name_age = frozenset(['Anatoly', 32])
students_courses.update({name_age: ['Python', 'C++']})
print(students_courses)
{frozenset({32, 'Anatoly'}): ['Python', 'C++']}

Це один із прикладів практичного застосування frozenset, якщо ми хочемо створити словник, де сам ключ - це масив із кількох елементів, то frozenset зможе нам допомогти. Список або звичайний set використовувати як ключ для словника не вийде.

Це лише деякі зі способів створення словників у Python. Кожен із них має свої особливості та може використовуватися залежно від конкретного завдання.

3.3.2 Основні методи словників

  1. get() - дає змогу отримати значення за ключем, але на відміну від звернення через [], не викликає виняток KeyError, якщо ключ відсутній у словнику. Приклад:
my_dict = {"one": 1, "two": 2, "three": 3}
print(my_dict.get("two"))
print(my_dict.get("four", "Key not found"))
2
Key not found
  1. keys() - дає змогу отримати список ключів словника. Приклад:
my_dict = {"one": 1, "two": 2, "three": 3}
print(my_dict.keys())
dict_keys(['one', 'two', 'three'])
  1. values() - дає змогу отримати список значень словника. Приклад:
my_dict = {"one": 1, "two": 2, "three": 3}
print(my_dict.values())
dict_values([1, 2, 3])
  1. items() - дає змогу отримати список пар ключ-значення словника. Приклад:
my_dict = {"one": 1, "two": 2, "three": 3}
print(my_dict.items())
dict_items([('one', 1), ('two', 2), ('three', 3)])
  1. pop() - дає змогу видалити пару ключ-значення за ключем. Якщо ключ відсутній, викликає виняток KeyError або повертає другий аргумент, якщо він переданий. Приклад:
my_dict = {"one": 1, "two": 2, "three": 3}
print(my_dict.pop("two"))
print(my_dict.pop("four", "Key not found"))
2
Key not found
  1. clear() - дає змогу видалити всі пари ключ-значення зі словника. Приклад:
my_dict = {"one": 1, "two": 2, "three": 3}
my_dict.clear()
print(my_dict)
{}
  1. update() - дає змогу оновити словник із іншого словника або із послідовності пар ключ-значення. Приклад:
my_dict = {"one": 1, "two": 2, "three": 3}
new_dict = {"two": 22, "four": 4}
my_dict.update(new_dict)
print(my_dict)
{'one': 1, 'two': 22, 'three': 3, 'four': 4}
  1. copy() - дає змогу створити копію словника. Приклад:
my_dict = {"one": 1, "two": 2, "three": 3}
new_dict = my_dict.copy()
print(new_dict)
{'one': 1, 'two': 2, 'three': 3}
  1. setdefault() - повертає значення за ключем. Якщо ключ відсутній, то він буде вставлений у словник із зазначеним значенням (або None, якщо значення не вказано). Приклад:
my_dict = {"one": 1, "two": 2, "three": 3}
print(my_dict.setdefault("two", 22))
print(my_dict.setdefault("four"))
print(my_dict)
2
None
{'one': 1, 'two': 2, 'three': 3, 'four': None}

3.3.3 pop() vs. remove()

Давайте знову зупинимося на різниці цих методів. Методи pop() і remove() застосовуються для видалення елементів зі списків Python.

  • Метод pop() видаляє та повертає останній елемент зі списку. Якщо в дужках вказати індекс елемента, буде видалено елемент із зазначеним індексом. Наприклад:
fruits = ['apple', 'banana', 'orange']
removed_fruit = fruits.pop()
print(fruits)
['apple', 'banana']
print(removed_fruit)
orange

А якщо ми хочемо видалити елемент за індексом, то потрібно вказати індекс у дужках методу:

fruits = ['apple', 'banana', 'orange']
removed_fruit = fruits.pop(1)
print(fruits)
['apple', 'orange']
print(removed_fruit)
banana
  • Метод remove() видаляє перший елемент зі списку, який збігається з переданим значенням. Наприклад:
fruits = ['apple', 'banana', 'orange']
fruits.remove('banana')
print(fruits)
['apple', 'orange']

Важливо, що якщо у списку не буде елемента із зазначеним індексом або значенням, методи pop() та remove() повернуть помилки. Таким чином, основна відмінність між методами pop() і remove() полягає в тому, що pop() видаляє елемент за індексом, повертаючи його значення, а remove() видаляє перший знайдений елемент із заданим значенням.

3.4 Цикли та Маріо

Одна з найпопулярніших ігор минулого століття - це Super Mario Bros. Це двовимірний світ, де персонажі рухаються вгору, вниз і вправо, не так часто вліво, перестрибуючи через піраміди і перешкоди на кшталт цих:

Давайте просто реалізуємо дуже просту версію цих перешкод за допомогою Python, використовуючи просто # для позначення цеглинок.

Створимо програму mario.py:

Terminal
code mario.py

Почнемо з максимально простої версії, де ми просто виведемо на екран один стовпчик з трьох цеглинок:

print("#")
print("#")
print("#")
#
#
#

Але ви можете собі уявити, що в грі стовпчики можуть ставати вищими або нижчими, тож було б непогано написати код, який був би трохи динамічнішим:

for _ in range(3):
    print("#")
#
#
#

Давайте подивимося, чи можемо ми зараз об’єднати наші знання написання власних функцій, щоб почати писати щось більш динамічне і вирішувати більш складні проблеми. Однією з приємних речей у функціях є те, що вони дозволяють нам не просто писати код, який ми можемо повторно використовувати. Вони дозволяють нам створювати абстракції, якщо хочете. Абстракція - це спрощення потенційно більш складної ідеї.

Припустимо, що я додумався створити функцію з назвою print_сolumn(), яка приймає один аргумент height - висота блоку, яка має бути надрукована. Таким чином, я можу переписати наш код наступним чином:

def main():
    print_column(3)

def print_column(height):
    for _ in range(height):
        print("#")

main()
#
#
#

Або без використання циклу for:

def main():
    print_column(3)

def print_column(height):
    print("#\n" * height, end="")

main()
#
#
#

У певний момент Маріо зустрічає в небі нові цеглинки, які, якщо він підстрибне під ними, перетворяться на монети:

Давайте спробуємо вивести ці чотири блоки у вигляді знаків питання ?. Створимо функцію print_row() з аргументом width - ширина. Таким чином, ми можемо переписати наш код наступним чином:

def main():
    print_row(4)

def print_row(width):
    print("?" * width)

main()
????

Пізніше Маріо спускається вниз, у світ лабіринтів з новими блоками, наприклад 3 на 3:

Спробуємо відтворити цей блок за допомогою функції print_square() з аргументом size - розмір. Таким чином, ми можемо переписати наш код наступним чином:

def main():
    print_square(3)

def print_square(size):
    for i in range(size):
        for j in range(size):
            print("#", end="")
        print()

main()
###
###
###

У цьому коді ми використовуємо вкладені цикли for. Перший цикл for відповідає за виведення рядків, а другий цикл for відповідає за виведення стовпчиків. Таким чином, ми можемо вивести блоки, які складаються з рядків і стовпчиків.

Як ми можемо покращити код? Для початку ми можемо позбутися вкладеного циклу і замінити його просто функцією print():

def main():
    print_square(3)

def print_square(size):
    for i in range(size):
        print("#" * size)

main()
###
###
###

3.5 List comprehension

List comprehension в Python - це компактний спосіб створення нового списку на основі наявного списку або іншої ітерованої послідовності, наприклад, рядка. Він дає змогу більш елегантно і стисло написати код, роблячи його більш читабельним і ефективним.

Загальний синтаксис для створення list comprehension виглядає наступним чином:

```{python}
new_list = [expression for item in iterable if condition]
```

де:

  • expression - вираз, який застосовуватиметься до кожного елемента списку або послідовності
  • item - змінна, що представляє поточний елемент послідовності, що ітерується;
  • iterable - список або інша послідовність, що ітерується;
  • condition (необов’язково) - умова, за якою буде фільтруватися вихідна послідовність.

Нижче наведено кілька прикладів для кращого розуміння:

  1. Припустимо, у нас є список із числами, ми хочемо створити новий список із квадратами цих чисел. Варіант рішення:
numbers = [1, 2, 3, 4, 5]
squares = []
for i in numbers:
    squares.append(i**2)

print(squares)
[1, 4, 9, 16, 25]

А ось так виглядало б рішення за допомогою list comprehension:

numbers = [1, 2, 3, 4, 5]
squares = [x ** 2 for x in numbers]

print(squares)
[1, 4, 9, 16, 25]

Інакше кажучи, результат роботи нашого циклу відразу поміщається в список.

  1. Створення нового списку, що містить тільки парні числа з вихідного списку:

Стандартний розв’язок:

numbers = [1, 2, 3, 4, 5]
even_numbers = []
for i in numbers:
    if i % 2 == 0:
        even_numbers.append(i)

print(even_numbers)
[2, 4]

List comprehension:

numbers = [1, 2, 3, 4, 5]
even_numbers = [x for x in numbers if x % 2 == 0]

print(even_numbers)
[2, 4]
  1. Створення нового списку, що містить довжини слів із вихідного списку:
words = ["hello", "world", "python", "list"]
word_lengths = [len(word) for word in words]

print(word_lengths)
[5, 5, 6, 4]

3.6 Функція enumerate

Функція enumerate() у Python використовується для додавання індексів до елементів послідовності (наприклад, списку або рядка) під час ітерації по цій послідовності. Вона повертає об’єкт-лічильник, який містить пари (індекс, елемент).

Припустимо, у нас є список замовлень, кожне з яких представлено у вигляді словника з різними властивостями, такими як "номер", "клієнт", "дата" тощо. Наше завдання - вивести на екран інформацію за кожним замовленням, а також додати порядкові номери до кожної властивості цього замовлення.

orders = [
    {"номер": "001", "клієнт": "John", "дата": "2022-01-01", "статус": "в обробці"},
    {"номер": "002", "клієнт": "Alice", "дата": "2022-01-02", "статус": "виконано"},
    {"номер": "003", "клієнт": "Bob", "дата": "2022-01-03", "статус": "виконано"},
    {"номер": "004", "клієнт": "Eva", "дата": "2022-01-04", "статус": "в обробці"},
]
for index, order in enumerate(orders, start=1):
    print(f"Замовлення {index}:")
    for key, value in order.items():
        print(f"{key}: {value}")
    print()
Замовлення 1:
номер: 001
клієнт: John
дата: 2022-01-01
статус: в обробці

Замовлення 2:
номер: 002
клієнт: Alice
дата: 2022-01-02
статус: виконано

Замовлення 3:
номер: 003
клієнт: Bob
дата: 2022-01-03
статус: виконано

Замовлення 4:
номер: 004
клієнт: Eva
дата: 2022-01-04
статус: в обробці
Увага

Зверніть увагу, ми явно вказали, що хочемо почати нумерацію з 1 за допомогою enumerate(orders, start=1). Функція enumerate() допомагає нам додати порядкові номери до кожного замовлення в списку ітерацією по ньому. Це може бути особливо корисно, коли нам потрібно обробляти й аналізувати дані з урахуванням їхніх позицій у структурі даних.

3.7 Оператори continue та break

Оператор continue і оператор break є керуючими операторами в циклах, їх використовують для зміни поведінки виконання циклу.

Оператор continue використовується для пропуску частини тіла циклу, що залишилася, і переходу до наступної ітерації циклу. Якщо зустрінеться оператор continue, то код нижче за нього в поточній ітерації циклу не буде виконано, а виконання циклу продовжиться відразу з наступної ітерації.

Приклад:

for i in range(1, 6):
    if i == 3:
        continue
    print(i)
1
2
4
5

У цьому прикладі в циклі for ми перебираємо значення від 1 до 5. Якщо значення i дорівнює 3, оператор continue пропустить решту тіла циклу і перейде до наступної ітерації. У результаті у виводі буде пропущено число 3.

Оператор break використовується для переривання виконання циклу. Якщо зустрінеться оператор break, виконання циклу буде припинено і відбувається вихід із циклу.

Приклад:

for i in range(1, 6):
    if i == 3:
        break
    print(i)
1
2

У цьому прикладі в циклі for ми також перебираємо значення від 1 до 5. Однак, якщо значення i дорівнює 3, оператор break перериває виконання циклу. У результаті у виводі будуть тільки числа 1 і 2.

Таким чином, оператор continue і оператор break дають змогу керувати потоком виконання циклів залежно від заданих умов. Ці оператори можуть бути дуже корисними при розв’язанні різних задач на програмування.

Давайте розглянемо приклад їхнього спільного використання:

employees = [
    {'name': 'John', 'qualification': 'low'},
    {'name': 'Alice', 'qualification': 'high'},
    {'name': 'Bob', 'qualification': 'medium'},
    {'name': 'Eva', 'qualification': 'low'},
    {'name': 'Mike', 'qualification': 'high'},
    {'name': 'Lisa', 'qualification': 'medium'}
]
found_high_qualification_employee = False
for employee in employees:
    qualification = employee['qualification']
    if qualification == 'low':
        continue # Пропускаємо працівника з низькою кваліфікацією
    elif qualification == 'high':
        found_high_qualification_employee = True
        high_qualification_employee = employee
        break # Знайдено працівника з високою кваліфікацією, припиняємо пошук
if found_high_qualification_employee:
    print("Працівника з високою кваліфікацією знайдено!")
    print(high_qualification_employee)
else:
    print("Працівника з високою кваліфікацією не знайдено.")
Працівника з високою кваліфікацією знайдено!
{'name': 'Alice', 'qualification': 'high'}

У цьому прикладі ми створюємо список employees, який містить дані про працівників. Потім ми проходимося по кожному працівнику в циклі for. Якщо рівень кваліфікації працівника низький (low), ми використовуємо оператор continue для пропуску поточного працівника і переходимо до наступного. Якщо рівень кваліфікації працівника високий (high), ми використовуємо оператор break для переривання циклу і запису інформації про знайденого працівника. Після виконання циклу ми перевіряємо, чи було знайдено працівника з високою кваліфікацією, і виводимо відповідну інформацію.

3.8 WHILE vs. FOR

while і for - це два основні типи циклів у мові програмування Python. Цикл while виконує набір інструкцій доти, доки вказана умова істинна. Наприклад, якщо вам потрібно виконати певну дію доти, доки користувач не введе правильне значення, ви можете використовувати цикл while. Приклад:

```{python}
secret_number = 7
guess = 0
while guess != secret_number:
    guess = int(input("Вгадайте число від 1 до 10: "))
print("Вітаю, ви вгадали число!")
```

Цикл for, з іншого боку, виконує набір інструкцій для кожного елемента в послідовності (наприклад, рядку, списку, кортежі тощо). Приклад:

fruits = ["яблуко", "банан", "груша"]
for fruit in fruits:
    print(fruit)
яблуко
банан
груша

Цикл while зазвичай використовується, коли невідома точна кількість повторень, а ви здебільшого покладаєтеся на перевірку умови для зупинки циклу. З іншого боку, цикл for зазвичай використовується, коли ви заздалегідь знаєте, скільки разів цикл повинен виконатися, і ви хочете працювати з елементами послідовності.

Вибір між циклом while і циклом for залежить від специфіки завдання. Якщо у вас є явно певна кількість елементів або потрібно опрацювати кожен елемент у послідовності, то цикл for може бути більш зручним вибором. Якщо ж ви чекаєте певної події або хочете повторювати дію до виконання певної умови, то цикл while буде більш підходящим.

3.9 Завдання

Завдання 3.1
У змінних a і b збережено два цілих додатних числа, таких що a <= b. Напишіть програму, яка знаходить суму всіх чисел від a до b, кратних 3 або 5. Збережіть суму у змінну result. Якщо між a і b немає таких чисел, то збережіть у result нуль.

Приклад:

```{python}
# Приклад 1
a = 1
b = 10
result = 33

# Приклад 2
a = 9
b = 9
result = 9

# Приклад 3
a = 1
b = 2
result = 0
```
Рішення
a = 1
b = 10

result = 0
for i in range(a, b + 1):
    if i % 3 == 0 or i % 5 == 0:
        result += i

Завдання 3.2
Напишіть програму на Python, яка визначає, чи є задане число num простим.

Якщо num - просте число, то збережіть у змінну result рядок "це просте число". Якщо число не просте, то збережіть у змінну result рядок "це не просте число".

Використовуйте цикл для розв’язання цієї задачі.

Приклад:

```{python}
# Приклад 1
num = 7
result = "це просте число"

# Приклад 2
num = 8
result = "це не просте число"
```

Просте число - це число, яке ділиться тільки на 1 і на саме себе.

Рішення
num = 7

result = "це просте число"
for i in range(2, num):
    if num % i == 0:
        result = "це не просте число"
        break

Завдання 3.3
У змінній number збережено число, напишіть код, який перевірить, чи є number ступенем двійки? Ряд ступенів двійки:

1, 2, 4, 8, 16, 32, 64 ...

Результат перевірки True або False збережіть у змінну is_two_power.

Просте число - це число, яке ділиться тільки на 1 і на саме себе.

Рішення
number = 64

if number < 1:
    is_two_power = False
elif number == 1:
    is_two_power = True    
else:
    while number % 2 == 0:
        number = number / 2
    is_two_power = number == 1

# або
is_two_power = False
for i in range(1, int(number) + 1):
    if 2 ** i == number or number == 1:
        is_two_power = True
        break

Завдання 3.4
Для приготування однієї порції еспресо потрібно приблизно 7 г. меленої кави. Для приготування лате необхідно збити 180 мл. молока і додати до еспресо, а для приготування капучино - 100 мл. молока.

Задано дві змінні:

  • coffee - запас меленої кави в кав’ярні (у кілограмах);
  • milk - запас молока в кав’ярні (у літрах).

Напишіть програму, яка порахує, скільки відвідувачів зможе обслужити кав’ярня, якщо відомо, що: 1. У кав’ярні готують три напої на вибір: американо (еспресо + вода), лате і капучино. 2. Кожен відвідувач замовляє тільки один напій. 3. Відомо, що кожен третій замовлений напій - капучино, а кожен п’ятий - лате. 4. Якщо молоко закінчилося, то кав’ярня працює, доки не прийде відвідувач, який бажає замовити каву з молоком. 5. Запас води для американо не обмежений.

Результат збережіть у змінну visitors.

Не забудьте перевести кілограми в грами, а літри - в мілілітри.

Приклад:

```{python}
# Приклад 1
coffee = 0.1
milk = 1
visitors = 14

# Приклад 2
coffee = 0.07
milk = 0.1
visitors = 4
```
Рішення
coffee = 1
milk = 2

coffee *= 1000
milk *= 1000
visitors = 0
while coffee >=7:
    if (visitors+1) % 3 == 0:
        if milk >=100:
            milk -= 100
            coffee -= 7
            visitors += 1
        else:
            break
    elif (visitors+1) % 5 == 0:
        if milk >= 180:
            milk -= 180
            coffee -= 7
            visitors += 1
        else:
            break
    else:
        coffee -= 7
        visitors += 1

# або
coffee *= 1000
milk *= 1000
visitors = 0
while True:
    if coffee < 7 or ((visitors + 1) % 3 == 0 and milk < 100) or ((visitors + 1) % 5 == 0 and milk < 180):
        break
    visitors += 1
    coffee -= 7
    if visitors % 3 == 0 :
        milk -= 100
    elif visitors % 5 == 0:
        milk -= 180

Завдання 3.5
Дано список чисел a. Напишіть програму, яка поверне True, якщо у списку більше непарних чисел, і False - у всіх інших випадках. Результат збережіть у result.

Приклад:

```{python}
# Приклад 1
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
result = True

# Приклад 2
a = [1, 2, 3, 4, 5, 6, 7, 8, 10]
result = False

# Приклад 3
a = [1, 2, 3, 4]
result = False
```
Рішення
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]

count_odd = 0
count_even = 0
for i in a:
    if i % 2 == 0:
        count_even += 1
    else:
        count_odd += 1

result = count_odd > count_even

# або
result = sum(1 if int(i) % 2 else -1 for i in a) > 0

Завдання 3.6
Є словник grades, що містить інформацію про шкільні предмети та їхні оцінки. У список good_subjects збережіть назви всіх предметів, у яких оцінка більша або дорівнює 7.

Приклад:

```{python}
grades = {"Математика": 9, "Історія": 6, "Біологія": 6, "Географія": 8}
good_subjects = ["Математика", "Географія"]

grades = {"Алгебра": 6, "Геометрія": 6}
good_subjects = []
```
Рішення
grades = {"Математика": 9, "Історія": 6, "Біологія": 6, "Географія": 8}

good_subjects = []
for subject, grade in grades.items():
    if grade >= 7:
        good_subjects.append(subject)        

Завдання 3.7
Напишіть програму, яка прийматиме список чисел nums і повертатиме два числа, абсолютна різниця яких мінімальна. Пару чисел збережіть у змінну result у вигляді списку, відсортованого за зростанням.

Якщо кілька пар дають мінімальну абсолютну різницю, виберіть ту пару елементів, сума яких більша.

Приклад:

```{python}
# Приклад 1
nums = [40, 16, 8, 17, 15]
result = [16, 17]
# пара 16 і 15 не підходить, оскільки сума 16 і 17 більша за

# Приклад 2
nums = [0, 2, 35, 42, 45, 14, -6, -1]
result = [-1, 0]
```
  1. Створіть змінну min_diff і збережіть у неї позитивну нескінченність. Це буде змінна зі значенням мінімальної абсолютної різниці. Далі почніть рахувати абсолютну різницю між числами в списку, на кожній ітерації перевіряйте, чи менша поточна різниця, ніж значення у змінній min_diff, якщо це так, то зберігайте в min_diff поточне значення і продовжуйте пошуки.
  2. Запис нескінченності у Python: float("inf") або float("-inf").
Рішення
nums = [40, 16, 8, 17, 15]

min_diff = float("inf")
result = []
for i in range(len(nums)):
    for j in range(i + 1, len(nums)):
        diff = abs(nums[i] - nums[j])
        if diff < min_diff:
            min_diff = diff
            result = [nums[i], nums[j]]
        elif diff == min_diff:
            if sum(result) < nums[i] + nums[j]:
                result = [nums[i], nums[j]]

# або
nums.sort() 
min_diff = float('inf')  
result = []
for i in range(len(nums) - 1):
    diff = abs(nums[i] - nums[i+1])  
    if diff < min_diff:
        min_diff = diff
        result = [nums[i], nums[i+1]]
    elif diff == min_diff and sum([nums[i], nums[i+1]]) > sum(result):
        result = [nums[i], nums[i+1]]

Завдання 3.8
Напишіть програму, що приймає у вигляді аргументів два списки lst_1 і lst_2 і визначає, чи є вони протилежними один одному. Результат перевірки збережіть у result у форматі True або False.

Кожна пара списків складатиметься з однакових елементів (типу a і b). Список вважається анти-списком, якщо всі елементи в ньому протилежні відповідним елементам у першому списку.

Приклад:

```{python}
lst_1 = ["1", "0", "0", "1"]
lst_2 = ["0", "1", "1", "0"]
result = True

lst_1 = ["1", "0", "0", "1"]
lst_2 = ["0", "1", "1", "1"]
result = False
```
Рішення
lst_1 = ["1", "0", "0", "1"]
lst_2 = ["0", "1", "1", "0"]

result = True
for i in range(len(lst_1)):
    if lst_1[i] == lst_2[i]:
        result = False
        break

# або
result = all({a, b} == set(lst_1) for a, b in zip(lst_1, lst_2))

Завдання 3.9
Задано змінну m - список зі списків однакової довжини. Перевірте, що суми елементів на діагоналях рівні.

Результат перевірки збережіть у result у форматі True або False.

Приклад:

```{python}
# Приклад 1
m = [[1, 23, 4], 
     [3, 2, 1],
     [6, 3, 4]]
result = False

# Приклад 2
m = [[1, 23, 4], 
     [3, 2, 1],
     [1, 3, 4]]
result = True
```
Рішення
m = [[1, 23, 4], 
     [3, 2, 1],
     [6, 3, 4]]

n = len(m)
main_diagonal_sum = sum(m[i][i] for i in range(n))
secondary_diagonal_sum = sum(m[i][n-i-1] for i in range(n))
result = main_diagonal_sum == secondary_diagonal_sum

# або

result = sum([m[i][i] for i in range(len(m))]) == sum([m[i][len(m[i]) - i - 1] for i in range(len(m))])

Завдання 3.10
Напишіть програму, яка приймає словник input_dict і повертає рядок вигляду: ключ=значення&ключ=значення

Рядок має бути лексикографічно відсортований за ключами вихідного словника. Збережіть отриману відповідь у result.

Приклад:

```{python}
input_dict = {'lesson': 2, 'task': 21, 'course': 'python'}
result = 'course=python&lesson=2&task=21'
```
Рішення
input_dict = {'lesson': 2, 'task': 21, 'course': 'python'}

result = '&'.join([f'{key}={value}' for key, value in sorted(input_dict.items())])

Завдання 3.11
Напишіть програму, яка приймає один рядок input_str і повертає інший result, у якому кожна буква вихідного рядка повторюється двічі.

Приклад:

```{python}
input_str = "String"
result = "SSttrriinngg"
```
Рішення
input_str = "String"

result = ''.join([char * 2 for char in input_str])

Завдання 3.12
Напишіть програму, яка прийматиме число n і перевірятиме, чи кратна кожна його цифра цифрі, що стоїть ліворуч від неї. Відповідь збережіть у result у вигляді масиву булевих значень результатів перевірок.

result завжди має починатися з False, оскільки ліворуч від першої цифри нічого немає.

Приклад:

```{python}
n = 54412
result = [False, False, True, False, True]
```
Рішення
n_str = str(n)
result = [False]
for i in range(1,len(n_str)):
    if int(n_str[i-1]) == 0 or int(n_str[i]) % int(n_str[i-1]) != 0:
        result.append(False)
    else:
        result.append(True)

Завдання 3.13
Уявімо, що ми організовуємо іспит, у нас є список студентів, які мають виступити з усною доповіддю. Для виступу відбираються тільки ті студенти, які набрали понад 90 балів за письмову роботу. Наше завдання зробити так, щоб студенти виступали по черзі, відсортовані за прізвищем.

Наприклад, якщо в нас є учасники Бабак, Андющенко, Власенко, то виступати вони мають у такому порядку: Андющенко, Бабак, Власенко.

У словнику students збережено дані про студентів, ключ - прізвище, значення - кількість балів за іспит, створіть список students_order, у якому кожен елемент - це кортеж (tuple) з номером виступу студента та його прізвищем. У students_order мають бути тільки ті студенти, у яких понад 90 балів. Порядок визначається сортуванням за прізвищем.

Приклад:

```{python}
students = {'Бабак': 80, 'Андющенко': 99, 'Власенко': 100}
students_order = [(1, 'Андющенко'), (2, 'Власенко')]
```
Рішення
students = {'Бабак': 80, 'Андющенко': 99, 'Власенко': 100}

students_order = [name for name in sorted(students.keys()) if students[name] > 90]
students_order = list(enumerate(students_order, 1))

Завдання 3.14
Давайте навчимося розгадувати таємні шифри! У my_string зберігається зашифрований рядок, наприклад:

```{python}
my_string = 'qircxfcgwxeciscwgwvzlfrciclibecpfvqzg'
```

У словнику secret_dict зберігається ключ до шифру, набір символів, які потрібно замінити:

```{python}
secret_dict = {
 'b': 'k',
 'c': ' ',
 'g': 'n',
 'q': 'h',
 'z': 'o',
 'v': 't',
 'w': 'a',
 'f': 'y',
 'x': 'm',
 'r': ','}
```

Таким чином, словник secret_dict каже нам, що в рядку my_string літеру “b” потрібно замінити на “k”, “c” на “пробіл” тощо. Якщо ми зробимо такі заміни в рядку my_string, то 'qircxfcgwxeciscwggwwvzlfrciclibecpfvvqzg' перетвориться на 'hi, my name is anatoly, i like python'.

Напишіть програму, яка розшифровує рядок my_string за допомогою словника secret_dict. Розшифрований рядок збережіть у змінну decrypted_string.

Приклад:

```{python}
my_string = 'zis jqd qbdx qjjgsd bcd zjm fbc bvbx'
secret_dict = {
'v': 'w',
'x': 'y',
'i': 'h',
'q': 'l',
'c': 'n',
'b': 'a',
'f': 'r',
'j': 'o',
's': 'e',
'z': 't',
'g': 'k'}

decrypted_string = 'the old lady looked and tom ran away'
```
Рішення
my_string = 'zis jqd qbdx qjjgsd bcd zjm fbc bvbx'
secret_dict = {
'v': 'w',
'x': 'y',
'i': 'h',
'q': 'l',
'c': 'n',
'b': 'a',
'f': 'r',
'j': 'o',
's': 'e',
'z': 't',
'g': 'k'}

decrypted_string = ''
for letter in my_string:
    if letter in secret_dict:
        decrypted_string += secret_dict[letter]
    else:
        decrypted_string += letter

Завдання 3.15
У змінну cities_population збережіть словник із трьома ключами: 'Київ', 'Париж', 'Токіо'. Як значення збережіть населення цих міст у млн. осіб: 2.88, 2.16, 13.96. Ключами нашого словника будуть рядки, значеннями - числа у форматі float.

Рішення
cities_population = {
    'Київ': 2.88,
    'Париж': 2.16,
    'Токіо': 13.96
}

Завдання 3.16
Дано словник dict_input. Поміняйте ключі та значення місцями. Результат збережіть у result.

Приклад:

```{python}
dict_input = {"1": 11, "2": 22, "3": 33}
result = {11: "1", 22:"2", 33:"3"}
```

Варіантів рішення може бути декілька. Згадайте про методи словників, які ви вивчили у цьому уроці. Також згадайте про функцію zip(), яка дозволяє об’єднати дві послідовності у послідовність пар див. 10.11. Або використайте генератор словників.

Рішення
dict_input = {"1": 11, "2": 22, "3": 33}
result = dict(zip(dict_input.values(), dict_input.keys()))
result = {value: key for key, value in dict_input.items()}

Завдання 3.17
Катя - власник невеликого кондитерського виробництва, на якому виготовляють еклери. У нас є словник data, у якому міститься інформація про собівартість одиниці товару cost_price, ціну продажу sell_price та кількість товару eclairs. Потрібно порахувати, який прибуток Катя отримує після продажу своєї продукції. Результат збережіть у змінну result, округливши суму до цілого числа.

Приклад:

```{python}
data = {
  "cost_price": 225.89,
  "sell_price": 550.00,
  "eclairs": 100
}
result = 32411
```

Прибуток = продажна ціна - собівартість

Рішення
data = {
  "cost_price": 225.89,
  "sell_price": 550.00,
  "eclairs": 100
}

result = round((data["sell_price"] - data["cost_price"]) * data["eclairs"])

Завдання 3.18
Є словник student, у якому зберігаються ім’я студента і список його оцінок. У result збережіть словник з ім’ям студента та найвищою його оцінкою.

Приклад:

```{python}
student = {"name": "Ihor", "notes": [4, 5, 4]}
result = {"name": "Ihor", "max_note": 5}
```
Рішення
student = {"name": "Ihor", "notes": [4, 5, 4]}
result = {"name": student["name"], "max_note": max(student["notes"])}

Завдання 3.19
Антон навчається на Data Scientist. У словнику anton_courses зберігається інформація про завершені ним курси та кількість набраних балів. Дані в словнику зберігаються у форматі ключ - назва курсу, значення - кількість балів у числовому форматі. Антон завершив навчання на курсі Machine Learning і набрав 120 балів. Додайте до словника anton_courses цю інформацію. У змінну courses збережіть список пройдених курсів. У змінну DataAnalyst збережіть кількість балів, набрану Антоном на однойменному курсі, ця інформація є в словнику.

Приклад:

```{python}
anton_courses = {'Python for Data Science': 56, 
                 'Statistics': 87, 
                 'Data Analyst': 140}
# -> 
anton_courses = {'Python for Data Science': 56, 
                 'Statistics': 87, 
                 'Data Analyst': 140, 
                 'Machine Learning': 120}
courses = ['Python for Data Science', 'Statistics', 'Data Analyst', 'Machine Learning']
DataAnalyst = 87
```
Рішення
anton_courses = {'Python for Data Science': 56, 
                 'Statistics': 87, 
                 'Data Analyst': 140}

anton_courses['Machine Learning'] = 120
courses = list(anton_courses.keys())
DataAnalyst = anton_courses['Data Analyst']

Завдання 3.20
У нас є магазин одягу LARA. У словнику shop_stock зберігається інформація про товари, наявні на складі магазину. Інформація вказана у форматі ключ - артикул товару, значення - кількість одиниць. У магазин поставили нову партію товарів, у словнику shop_new_goods записано інформацію про поставлені товари та їхню кількість. Створіть словник result, який міститиме інформацію і про товари на складі, і про товари з нової поставки. Відомо, що якщо на складі залишалася хоча б одна одиниця якогось типу товару, то товару цього типу не було в поставці.

Приклад:

```{python}
shop_stock = {"2358241350-50": 1, "2358000350-30": 24, "2358241350-00": 3}
shop_new_goods = {"2358241350-60": 10}
# -> 
result = {"2358241350-50": 1, "2358000350-30": 24, "2358241350-00": 3, "2358241350-60": 10}
```
Рішення
shop_stock = {"2358241350-50": 1, "2358000350-30": 24, "2358241350-00": 3}
shop_new_goods = {"2358241350-60": 10}

result = shop_stock.copy()
result.update(shop_new_goods)

Завдання 3.21
Магазин Avocado зберігає інформацію про наявні фрукти та овочі у словнику input_dict у форматі ключ - назва фрукта або овоча, значення - кількість кілограмів у наявності. Порахуйте, скільки всього кілограмів фруктів і овочів є в магазині. Результат збережіть у змінну result.

Приклад:

```{python}
input_dict = {"морква": 10.44, "капуста": 5.06, "полуниця": 3}
# -> 
result = 18.5
```
Рішення
input_dict = {"морква": 10.44, "капуста": 5.06, "полуниця": 3}
result = sum(input_dict.values())

Завдання 3.22
Є словник courses, що містить інформацію про вартість навчання в різних курсах. Інформація вказана у форматі: ключ - назва курсу, значення - вартість навчання.

Знайдіть ціну найдорожчого курсу. Результат збережіть у result.

Приклад:

```{python}
courses = {"Python": 80000, "SQL": 300000}
# -> 
result = 300000
```
Рішення
courses = {"Python": 80000, "SQL": 300000}
result = max(courses.values())

Завдання 3.23
У базі даних КНЕУ інформація про студентів і кафедри, до яких вони прикріплені, зберігається в словнику kaf_sudents у форматі: ключ - ПІ студента, значення - код кафедри.

Після другого курсу за підсумками останніх двох сесій було складено рейтинг студентів, на основі якого стався перерозподіл студентів за кафедрами. Частина студентів продовжила навчання на своїй кафедрі, а деякі студенти перейшли з однієї кафедри на іншу. Інформація про студентів, які перейшли на нову кафедру, зберігається в словнику new_kaf_students.

Оновіть інформацію в словнику kaf_sudents, додавши в словник дані з new_kaf_students.

Приклад:

```{python}
kaf_sudents = {'Дробина Юлія': 100}
new_kaf_students = {'Нечаєнко Георгій': 200}

kaf_sudents = {'Дробина Юлія': 100, 'Нечаєнко Георгій': 200}
```
Рішення
kaf_sudents = {'Дробина Юлія': 100}
new_kaf_students = {'Нечаєнко Георгій': 200}

kaf_sudents.update(new_kaf_students)

Завдання 3.24
my_list зберігає список як мінімум з двома елементами.

Створіть змінні:

  • first_item з першим елементом списку.
  • last_item з останнім елементом списку.
  • reversed_list з елементами списку my_list у зворотному порядку.
  • even_items з елементами списку my_list із парними індексами.

Приклади:

my_list = ['apple', 123, True, 3.14, 'cherry', 45, 22]

first_item = 'apple'
last_item = 22
reversed_list = [22, 45, 'cherry', 3.14, True, 123, 'apple']
even_items = ['apple', True, 'cherry', 22]
Рішення
my_list = ['apple', 123, True, 3.14, 'cherry', 45, 22]

first_item = my_list[0]
last_item = my_list[-1]
reversed_list = my_list[::-1]
even_items = my_list[::2]

Завдання 3.25
У змінній my_list збережено не порожній список, де є число 11.

Знайдіть перший індекс числа 11 my_list, збережіть індекс в змінну eleven_index.

У змінну ten_count збережіть скільки разів у списку my_list зустрічається число 10.

Приклад:

```{python}
my_list = [1, 10, 0, 10, 11]
eleven_index = 4
ten_count = 2


my_list = [11, 2, 0, 6]
eleven_index = 0
ten_count = 0
```
Рішення
my_list = [11, 2, 0, 6]
eleven_index = my_list.index(11)
ten_count = my_list.count(10)

Завдання 3.26
У student_names збережено список з іменами студентів, додайте до списку два імені 'Anatoly' та 'Oksana'.

У scores збережено список із десяти цілих чисел, видаліть із нього другий, п’ятий та останній елемент.

У lessons збережений список з назвою уроків, відсортуйте назви уроків у списку за абеткою.

Приклад:

```{python}
student_names = ['Ian', 'Ivan']
scores = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
lessons = ['Python', 'Analytics']

# =>

student_names = ['Ian', 'Ivan', 'Anatoly', 'Oksana']
scores = [0, 2, 3, 5, 6, 7, 8, 9]
lessons = ['Analytics', 'Python']
```

Зверніть увагу, що потрібно видалити другий, п’ятий та останній елемент із списку. Коли ви видалили один елемент, індекси інших елементів змінились.

Рішення
student_names = ['Ian', 'Ivan']
student_names.append('Anatoly')
student_names.append('Oksana')

scores = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
scores.pop(1)
scores.pop(3)
scores.pop()

lessons = ['Python', 'Analytics']
lessons.sort()

Завдання 3.27
Дано два списки list_1 і list_2. Відсортуйте list_1 за зростанням, а list_2 за спаданням. Поєднайте list_1 та list_2 в один відсортований за зростанням список list_3. У змінну list_3_len збережіть довжину list_3.

Приклад:

```{python}
list_1 = [1, 5, 3]
list_2 = [2, 8]
# -> 
list_1 = [1, 3, 5]
list_2 = [8, 2]
list_3 = [1, 2, 3, 5, 8]
list_3_len = 5
```
Рішення
list_1 = [1, 5, 3]
list_2 = [2, 8]
list_1.sort()
list_2.sort(reverse=True)
list_3 = sorted(list_1 + list_2)
list_3_len = len(list_3)

Завдання 3.28
У змінній a зберігається список цілих невід’ємних чисел. Кількість чисел парна. Напишіть програму, яка ділитиме цей список навпіл, визначатиме суми чисел у половинах списку (sum_left і sum_right). Якщо sum_left дорівнює sum_right, то збережіть у змінну result значення True, в іншому випадку - False.

Приклад:

```{python}
a = [1, 2, 4, 3]

sum_left = 3
sum_right = 7
result = False
```
Рішення
a = [1, 2, 4, 3]
half = len(a) // 2
sum_left = sum(a[:half])
sum_right = sum(a[half:])
result = sum_left == sum_right

Завдання 3.29
Дано список цілих чисел a і число b. Видаліть з a перше й останнє входження числа b.

Приклад:

```{python}
a = [1, 2, 2, 1, 3, 2, 3]
b = 1 
# -> a = [2, 2, 3, 2, 3]

a = [1, 2, 2, 1, 3, 2, 3]
b = 2 
# -> a = [1, 2, 1, 3, 3]
```
Рішення
a = [1, 2, 2, 1, 3, 2, 3]
b = 1
a.remove(b)
a.reverse()
a.remove(b)
a.reverse()

Data Miorsh Ihor Miroshnychenko Youtube Monobank