Решение задания 1. Инверсия словаря
# solution_01_invert_dict.py
def invert_dict(original: dict[str, int]) -> dict[int, str]:
"""Возвращает словарь с инвертированными ключами и значениями."""
return {value: key for key, value in original.items()}
original_dict = {"a": 1, "b": 2, "c": 3}
print("Инверсированный словарь:", invert_dict(original_dict))
Логика: по каждой паре ключ-значение создаём новую пару значение-ключ.
Решение задания 2. Из чисел в слова
# solution_02_numbers_to_words.py
def translate_values(
data: dict[str, int],
mapping: dict[int, str]
) -> dict[str, str]:
"""Заменяет числовые значения словаря на строки по mapping."""
return {
key: mapping.get(value, str(value))
for key, value in data.items()
}
number_to_word = {1: "один", 2: "два", 3: "три"}
data = {"x": 1, "y": 2, "z": 3}
print(translate_values(data, number_to_word))
Логика: для каждого значения ищем соответствие в словаре перевода. Если его нет — оставляем строковое представление исходного значения.
Решение задания 3. Факториал с проверкой
# solution_03_factorial.py
def factorial(n: int) -> int:
"""Возвращает факториал неотрицательного целого числа."""
if n < 0:
raise ValueError("n must be non-negative")
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
print(factorial(0)) # 1
# factorial(-1) # ValueError
Логика: guard clause отсекает отрицательные числа, базовый случай обрабатывает 0 и 1, рекурсивный случай сводит задачу к меньшему числу.
Решение задания 4. Бинарный поиск
# solution_04_binary_search.py
from typing import Optional
def binary_search(
arr: list[int],
target: int,
left: int,
right: int
) -> Optional[int]:
"""Ищет target в отсортированном списке arr. Возвращает индекс или None."""
if left > right:
return None
mid = (left + right) // 2
if arr[mid] == target:
return mid
if arr[mid] < target:
return binary_search(arr, target, mid + 1, right)
return binary_search(arr, target, left, mid - 1)
array = [1, 3, 5, 7, 9, 11, 13]
print(binary_search(array, 5, 0, len(array) - 1)) # 2
print(binary_search(array, 13, 0, len(array) - 1)) # 6
print(binary_search(array, 8, 0, len(array) - 1)) # None
Логика: базовый случай — пустой диапазон. Иначе сравниваем target с серединой и рекурсивно ищем в нужной половине.
Решение задания 5. Сумма цифр числа
# solution_05_sum_digits.py
def sum_digits(n: int) -> int:
"""Возвращает сумму цифр неотрицательного целого числа."""
n = abs(n)
if n == 0:
return 0
return n % 10 + sum_digits(n // 10)
num = 43197
print(sum_digits(num)) # 24
Логика: на каждом шаге отрезаем последнюю цифру и прибавляем её к сумме цифр оставшегося числа.
Решение задания 6. Сумма вложенных чисел
# solution_06_sum_nested.py
from typing import Iterable
def sum_nested(numbers) -> int:
"""Суммирует все целые числа во вложенных списках."""
if isinstance(numbers, int):
return numbers
if isinstance(numbers, Iterable) and not isinstance(numbers, (str, bytes)):
return sum(sum_nested(item) for item in numbers)
return 0
nested_numbers = [1, [2, 3], [4, [5, 6]], 7]
print(sum_nested(nested_numbers)) # 28
Логика: если элемент — целое число, возвращаем его. Если — итерируемая коллекция (но не строка), рекурсивно суммируем элементы.
Решение задания 7. Собственный аналог deepcopy
# solution_07_deep_copy.py
def deep_copy(data):
"""Рекурсивно копирует списки, кортежи, множества и словари."""
if isinstance(data, list):
return [deep_copy(item) for item in data]
if isinstance(data, dict):
return {key: deep_copy(value) for key, value in data.items()}
if isinstance(data, set):
return {deep_copy(item) for item in data}
if isinstance(data, tuple):
return tuple(deep_copy(item) for item in data)
return data
original_data = [
[1, 2, 3],
(4, [5, 6], {7, 8}),
{"a": 9, "b": [10, 11]},
"Hello",
[12, (13, 14)],
15.5,
5
]
copied_data = deep_copy(original_data)
original_data[1][1][0] = 0
print(f"Исходный: {original_data}")
print(f"Копия: {copied_data}")
Логика: для каждого изменяемого контейнера создаём новый объект и рекурсивно копируем содержимое. Неизменяемые скаляры возвращаем как есть.
Решение задания 8. Объединение данных в строку
# solution_08_join_data.py
from typing import Any
def join_data(data: list[Any]) -> str:
"""Возвращает строковое представление элементов списка, разделённых ' | '."""
return " | ".join(str(item) for item in data)
data = [42, "hello", [1, 2, 3], {"a": 1, "b": 2}]
print(join_data(data))
Логика: преобразуем каждый элемент в строку и объединяем через " | ".