Решение задания 1.1. Фильтрация чётных с функцией
# task1_1_solution.py
from typing import Callable
def is_even(n: int) -> bool:
"""Проверяет, является ли число чётным."""
return n % 2 == 0
def filter_by_predicate(
predicate: Callable[[int], bool],
numbers: list[int]
) -> list[int]:
"""Возвращает элементы, для которых predicate вернул True."""
return [n for n in numbers if predicate(n)]
nums = [1, 2, 3, 4, 5, 6]
print(filter_by_predicate(is_even, nums))
Логика решения: предикат отделён от фильтрации, поэтому функцию filter_by_predicate можно переиспользовать с любым условием.
Решение задания 1.2. Фильтрация чётных с filter
# task1_2_solution.py
nums = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens)
Логика решения: filter принимает функцию и итерируемый объект, возвращая только элементы, прошедшие проверку. Результат обязательно преобразуем в список для вывода.
Решение задания 2.1. Фильтрация строк по длине
# task2_1_solution.py
def filter_long_words(words: list[str], min_len: int = 3) -> list[str]:
"""Возвращает слова длиной больше min_len."""
return [word for word in words if len(word) > min_len]
words = ["hi", "Hello", "a", "python", "Ok"]
print(filter_long_words(words))
Логика решения: параметр min_len имеет значение по умолчанию 3, что соответствует условию задачи 2.1.
Решение задания 2.2. Фильтрация по настраиваемой длине
# task2_2_solution.py
def filter_by_length(
words: list[str],
min_len: int = 3
) -> list[str]:
"""Возвращает слова длиной не меньше min_len."""
return [word for word in words if len(word) >= min_len]
words = ["hi", "Hello", "a", "python", "Ok"]
min_len = 2
print(filter_by_length(words, min_len))
Логика решения: условие изменено на >=, чтобы слова длины 2 тоже попадали в результат. Параметр min_len передаётся явно.
Решение задания 2.3. Фильтрация по критерию
# task2_3_solution.py
from typing import Callable
def filter_words(
words: list[str],
predicate: Callable[[str], bool]
) -> list[str]:
"""Возвращает слова, удовлетворяющие переданному критерию."""
return [word for word in words if predicate(word)]
words = ["hi", "Hello", "a", "python", "Ok", "Radar"]
print(filter_words(words, lambda w: w.istitle()))
print(filter_words(words, lambda w: len(w) == 1))
print(filter_words(words, lambda w: w[0].lower() == w[-1].lower()))
Логика решения: функция принимает критерий как аргумент. Лямбды покрывают три разных случая без дублирования кода.
Решение задания 3. Агрегирование списка
# task3_solution.py
from functools import reduce
def product(numbers: list[int]) -> int:
"""Возвращает произведение всех элементов списка."""
return reduce(lambda acc, x: acc * x, numbers, 1)
numbers = [1, 2, 3, 4, 5]
print(product(numbers))
Логика решения: reduce накапливает произведение, начиная с 1. Начальное значение защищает от ошибки на пустом списке.
Решение задания 4. Сортировка по длине
# task4_solution.py
def sort_by_length(words: list[str]) -> list[str]:
"""Сортирует слова по возрастанию длины."""
return sorted(words, key=len)
words = ["apple", "banana", "kiwi", "grape"]
print(sort_by_length(words))
Логика решения: key=len вычисляет длину каждого слова, и сортировка происходит по этим числам.
Решение задания 5. Очередь с ограничением времени
# task5_solution.py
def schedule_within_limit(
tasks: dict[str, int],
time_limit: int
) -> dict[str, int]:
"""Возвращает задачи, которые укладываются в лимит времени."""
sorted_tasks = sorted(tasks.items(), key=lambda item: item[1], reverse=True)
selected: dict[str, int] = {}
total = 0
for name, duration in sorted_tasks:
if total + duration <= time_limit:
selected[name] = duration
total += duration
return selected
tasks = {"task1": 5, "task2": 3, "task3": 7, "task4": 2}
print(schedule_within_limit(tasks, 10))
Логика решения: задачи сортируются по убыванию времени. На каждом шаге добавляем самую долгую оставшуюся задачу, если она помещается в остаток лимита. Этот жадный подход даёт результат из примера: сначала берётся задача на 7 единиц, затем на 3, в сумме ровно 10.
Решение задания 6. Анализ оценок студентов
# task6_solution.py
def average_grades(students: list[dict]) -> dict[str, float]:
"""Возвращает словарь имя → средняя оценка, отсортированный по убыванию."""
averages = {
student["name"]: round(sum(student["grades"]) / len(student["grades"]), 2)
for student in students
}
return dict(sorted(averages.items(), key=lambda item: item[1], reverse=True))
students = [
{"name": "Alice", "grades": [90, 85, 88]},
{"name": "Bob", "grades": [78, 81, 75]},
{"name": "Charlie", "grades": [95, 92, 90]},
{"name": "Diana", "grades": [88, 84, 82]}
]
print(average_grades(students))
Логика решения: сначала вычисляются средние значения через dict comprehension, затем словарь сортируется по значению в обратном порядке.
Решение задания 7. Сортировка по сумме кодов символов
# task7_solution.py
words = ["banana", "kiwi", "grapefruit", "apple"]
sorted_words = sorted(words, key=lambda word: sum(ord(c) for c in word))
print(sorted_words)
Логика решения: лямбда вычисляет сумму кодов символов каждого слова. sorted использует это значение как ключ. Решение умещается в одну строку.
Решение задания 8. Цепочка шифрования
# task8_solution.py
from typing import Callable
def to_uppercase(text: str) -> str:
return text.upper()
def shift_encrypt(text: str, shift: int = 5) -> str:
return "".join(chr(ord(c) + shift) for c in text)
def reverse_string(text: str) -> str:
return text[::-1]
def encrypt(
text: str,
functions: list[Callable[[str], str]]
) -> str:
"""Последовательно применяет функции к строке."""
result = text
for func in functions:
result = func(result)
return result
sentence = "Functional programming is powerful"
functions = [to_uppercase, shift_encrypt, reverse_string]
print(encrypt(sentence, functions))
Логика решения: функция encrypt обобщена — она принимает любой список функций и применяет их последовательно. Это позволяет легко менять порядок или добавлять шаги шифрования.