Практикум по Python: задачи и варианты решений
Практические задачи на Python
Как найти максимальное число в списке?
Основное решение: использование встроенной функции max(). Это самый быстрый и читаемый способ.
numbers = [3, 7, 2, 9, 5]
maximum = max(numbers)
print(maximum) # 9задачи с кодом python (задачи с кодом на python)
Объяснение: функция max() принимает итерируемый объект и возвращает наибольший элемент. Работает за O(n) и оптимизирована на уровне C.
Как найти максимум без использования встроенной функции?
Вариант с циклом: вручную перебираем элементы, сравнивая с текущим максимумом.
numbers = [3, 7, 2, 9, 5]
maximum = numbers[0]
for num in numbers[1:]:
if num > maximum:
maximum = num
print(maximum) # 9Python практические задачи (практические задачи на python)
Объяснение: инициализируем первым элементом, затем проходим по остальным. Подходит для обучения и понимания логики.
Как найти максимум с помощью reduce?
Вариант с functools.reduce: функциональный подход.
from functools import reduce
numbers = [3, 7, 2, 9, 5]
maximum = reduce(lambda a, b: a if a > b else b, numbers)
print(maximum) # 9
Объяснение: reduce последовательно применяет лямбду к элементам, сохраняя текущий максимум. Менее читаемо, но демонстрирует функциональный стиль.
Типичные ошибки:
- Пустой список:
max([])вызоветValueError. Решение: проверять список или указывать аргументdefault:max(numbers, default=None). - Разные типы данных: если в списке смешаны числа и строки,
max()вызоветTypeError. Нужно убедиться в однородности. - При реализации вручную забыть учесть все элементы (например, начать с 0 вместо первого элемента при отрицательных числах).
Как удалить дубликаты из списка, сохранив порядок?
Основное решение: использование dict.fromkeys() (Python 3.7+ гарантирует порядок) или OrderedDict для старых версий.
items = [1, 2, 1, 3, 2, 4]
unique = list(dict.fromkeys(items))
print(unique) # [1, 2, 3, 4]
Объяснение: dict.fromkeys() создает словарь, где ключи уникальны и сохраняют порядок появления. Преобразование обратно в список дает уникальные элементы.
Как удалить дубликаты с помощью множества?
Вариант с set: быстро, но не сохраняет порядок.
items = [1, 2, 1, 3, 2, 4]
unique = list(set(items))
print(unique) # [1, 2, 3, 4] (порядок может быть любым)
Объяснение: set удаляет дубликаты, но теряет исходный порядок. Подходит, если порядок не важен.
Как вручную удалить дубликаты с сохранением порядка?
Вариант с циклом и списком:
items = [1, 2, 1, 3, 2, 4]
unique = []
for item in items:
if item not in unique:
unique.append(item)
print(unique) # [1, 2, 3, 4]
Объяснение: проходим по исходному списку и добавляем элемент только если его еще нет. Сложность O(n^2) из-за проверки in для списка, но наглядно.
Типичные ошибки:
- Порядок не сохраняется при использовании простого
set(). - Сравнение элементов с разными типами:
1 == '1'выдаст False, дубликат не удалится. - Использование
list(set(items))для большого списка – быстро, но недетерминированный порядок может быть проблемой.
Как проверить, является ли строка палиндромом?
Основное решение: сравнение строки с обратной версией с помощью среза.
s = "racecar"
if s == s[::-1]:
print("Палиндром")
else:
print("Не палиндром")
Объяснение: срез s[::-1] возвращает строку задом наперед. Сравнение производится быстро.
Как проверить палиндром с игнорированием регистра и пробелов?
Вариант с очисткой строки:
s = "A man, a plan, a canal: Panama"
clean = ''.join(c.lower() for c in s if c.isalnum())
if clean == clean[::-1]:
print("Палиндром")
else:
print("Не палиндром")
Объяснение: удаляем все не буквенно-цифровые символы и приводим к нижнему регистру. Затем проверяем обычным способом.
Как проверить палиндром с помощью двух указателей?
Вариант без дополнительной памяти:
def is_palindrome(s):
left, right = 0, len(s) - 1
while left < right:
while left < right and not s[left].isalnum():
left += 1
while left < right and not s[right].isalnum():
right -= 1
if s[left].lower() != s[right].lower():
return False
left += 1
right -= 1
return True
print(is_palindrome("A man, a plan, a canal: Panama")) # True
Объяснение: два указателя двигаются навстречу, пропуская не буквенно-цифровые символы. Эффективно по памяти – O(1).
Типичные ошибки:
- Учет регистра: "Racecar" и "racecar" при прямом сравнении не будут равны.
- Игнорирование знаков препинания: "race car" не является палиндромом из-за пробела, если не очистить.
- Пустая строка: считается палиндромом (длина 0).
- Одиночные символы – всегда палиндромы.
Как подсчитать количество строк в текстовом файле?
Основное решение: использование enumerate или просто sum() с генератором.
with open('file.txt', 'r', encoding='utf-8') as f:
line_count = sum(1 for _ in f)
print(f"Строк: {line_count}")
Объяснение: генератор считает единицы для каждой строки. Файл читается построчно, не загружается в память целиком. Подходит для больших файлов.
Как подсчитать строки, не считая пустые?
Вариант с фильтрацией:
with open('file.txt', 'r', encoding='utf-8') as f:
non_empty = sum(1 for line in f if line.strip())
print(f"Непустых строк: {non_empty}")
Объяснение: line.strip() удаляет пробельные символы, пустая строка после strip даст False.
Как подсчитать строки с помощью readlines?
Вариант для небольших файлов:
with open('file.txt', 'r', encoding='utf-8') as f:
lines = f.readlines()
line_count = len(lines)
print(f"Строк: {line_count}")
Объяснение: readlines() считывает все строки в список. Просто, но не подходит для очень больших файлов из-за потребления памяти.
Типичные ошибки:
- Не указана кодировка: может привести к
UnicodeDecodeErrorпри наличии специфичных символов. Всегда используйтеencoding='utf-8'. - Путь к файлу не существует: возникает
FileNotFoundError. Нужно проверять или использовать блок try/except. - Символ конца строки (newline) считается частью строки, поэтому метод
len(readlines())корректно считает строки.
Расширенные примеры
1. Поиск индексов всех максимальных значений
Если в списке несколько одинаковых максимумов, нужно найти их индексы.
def indices_of_max(lst):
max_val = max(lst) if lst else None
if max_val is None:
return []
return [i for i, v in enumerate(lst) if v == max_val]
numbers = [1, 5, 3, 5, 2]
print(indices_of_max(numbers)) # [1, 3]
[1, 3]
2. Поиск n наибольших элементов с помощью heapq
Используем heapq.nlargest для получения нескольких максимумов.
import heapq
numbers = [10, 3, 7, 15, 9, 20]
top3 = heapq.nlargest(3, numbers)
print(top3) # [20, 15, 10]
[20, 15, 10]
Объяснение: heapq работает за O(n log k), где k – количество искомых элементов. Эффективно для больших списков.
3. Удаление дубликатов с сохранением порядка и подсчетом количества
Используем collections.Counter для подсчета повторений.
from collections import Counter
items = [1, 2, 1, 3, 2, 4]
unique_order = list(dict.fromkeys(items))
counts = Counter(items)
print("Уникальные:", unique_order)
print("Количество:", dict(counts))
Уникальные: [1, 2, 3, 4]
Количество: {1: 2, 2: 2, 3: 1, 4: 1}
4. Проверка палиндрома для произвольной последовательности (рекурсия)
def is_palindrome_recursive(s):
if len(s) <= 1:
return True
if s[0] != s[-1]:
return False
return is_palindrome_recursive(s[1:-1])
print(is_palindrome_recursive("racecar")) # True
print(is_palindrome_recursive("hello")) # False
True False
5. Чтение файла с построчной обработкой и фильтрацией по длине
with open('sample.txt', 'r', encoding='utf-8') as f:
long_lines = [line.rstrip() for line in f if len(line) > 50]
print(f"Найдено строк длиннее 50 символов: {len(long_lines)}")
# Вывод первых трех
for line in long_lines[:3]:
print(line)
Найдено строк длиннее 50 символов: 2 Это очень длинная строка, содержащая более пятидесяти символов для демонстрации. Еще одна строка, которая явно превышает лимит в 50 символов, добавленная для примера.
6. Использование mmap для быстрого подсчета строк в большом файле
import mmap
with open('large_file.txt', 'r') as f:
with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mm:
# разбиваем по символу новой строки
count = mm.count(b'\n')
print(f"Строк: {count}")
Объяснение: mmap отображает файл в память, подсчет newlines происходит на уровне операционной системы, эффективно для гигабайтных файлов.
7. Группировка дубликатов с сохранением индексов
items = [1, 2, 1, 3, 2, 4]
from collections import defaultdict
groups = defaultdict(list)
for i, v in enumerate(items):
groups[v].append(i)
print(dict(groups))
# {1: [0, 2], 2: [1, 4], 3: [3], 4: [5]}
{1: [0, 2], 2: [1, 4], 3: [3], 4: [5]}
8. Быстрая проверка палиндрома для чисел (без преобразования в строку)
def is_palindrome_number(x):
if x < 0 or (x % 10 == 0 and x != 0):
return False
reversed_half = 0
while x > reversed_half:
reversed_half = reversed_half * 10 + x % 10
x //= 10
return x == reversed_half or x == reversed_half // 10
print(is_palindrome_number(121)) # True
print(is_palindrome_number(12321)) # True
print(is_palindrome_number(10)) # False
True True False
Объяснение: переворачиваем вторую половину числа и сравниваем с первой. Экономит память и подходит для больших чисел.
9. Чтение файла с пропуском заголовка и подсчетом статистики
with open('data.csv', 'r', encoding='utf-8') as f:
next(f) # пропустить заголовок
total = 0
count = 0
for line in f:
if line.strip():
parts = line.split(',')
try:
value = float(parts[1])
total += value
count += 1
except (IndexError, ValueError):
continue
avg = total / count if count else 0
print(f"Среднее значение второго столбца: {avg:.2f}")
10. Использование itertools.groupby для группировки последовательных дубликатов
from itertools import groupby
items = [1, 1, 2, 2, 2, 3, 1, 1]
grouped = [(k, list(g)) for k, g in groupby(items)]
print(grouped)
# [(1, [1, 1]), (2, [2, 2, 2]), (3, [3]), (1, [1, 1])]
[(1, [1, 1]), (2, [2, 2, 2]), (3, [3]), (1, [1, 1])]
Объяснение: groupby группирует только последовательные одинаковые элементы, в отличие от общего удаления дубликатов.