1. Введение

В задании 17 нужно обработать последовательность целых чисел из файла. Обычно требуется рассмотреть пары, тройки, четвёрки или другие соседние группы элементов, проверить для них условие и затем вывести количество подходящих наборов и ещё одну характеристику: максимальную сумму, минимальную сумму и т.д.

Главная трудность — аккуратно перевести текст условия в код. Нужно понять, как читать файл, как правильно двигаться по соседним элементам и в каких проверках обязательно использовать abs().

Идея решения

Сначала читаем все числа в список. Потом идём по последовательности окнами нужной длины: по парам, по тройкам, по четвёркам. Для каждого окна проверяем условие, а подходящие суммы либо сохраняем, либо сразу учитываем в ответе.

2. Теория и разбор данных

Как устроен файл

В большинстве задач 17 в файле записана одна последовательность чисел: по одному целому числу в каждой строке. Поэтому Python сначала получает строки текста, а затем мы превращаем их в числа.

1

Что делает open()

open('17.txt') открывает файл и позволяет перебрать его построчно.

Когда мы пишем:

for i in open('17.txt'):

переменная i на каждом шаге содержит одну строку файла.

Если в файле в каждой строке записано одно число, то удобно сразу получить список всех чисел так:

a = [int(i) for i in open('17.txt')]

int(i) превращает строку в целое число.

Генераторы списков: мини-памятка

Списковое включение, или «генератор списка», — это короткая запись для создания нового списка.

В задачах 17 оно встречается почти постоянно: и при чтении файла, и при фильтрации элементов.

Его удобно читать по частям:

[что берём | откуда берётся элемент | по какому условию оставляем]
1

Например:

[i for i in a]

Берём каждый элемент i из списка a.

[x for x in a if x > 0]

Берём только положительные элементы.

[x for x in a if 100 <= abs(x) <= 999]

Оставляем только трёхзначные числа.

Как читать запись

В записи:

[x for x in a if условие]
  • x — то, что попадёт в новый список;
  • for x in a — откуда берутся элементы;
  • if условие — что отсеиваем.

Как идти по соседним элементам

Если список называется a, то пара соседних элементов:

a[i], a[i + 1]

Тройка:

a[i], a[i + 1], a[i + 2]

Четвёрка:

a[i], a[i + 1], a[i + 2], a[i + 3]

Поэтому в цикле нужно вычитать из длины списка размер окна минус 1:

# пары
for i in range(len(a) - 1):

# тройки
for i in range(len(a) - 2):

# четвёрки
for i in range(len(a) - 3):

Иначе на последнем шаге программа выйдет за границы списка.

1

Если в списке n элементов, то пар соседних элементов будет n - 1.

Последняя допустимая пара начинается с индекса:

len(a) - 2

Поэтому цикл для пар записываем:

for i in range(len(a) - 1):

Где abs() обязателен

abs(x) обязательно нужен в тех задачах, где проверка связана с цифрами числа или его разрядностью.

Знак минус не должен мешать, когда мы ищем:

  • последнюю цифру;
  • количество цифр;
  • двузначные числа;
  • трёхзначные числа;
  • четырёхзначные числа.

То же самое относится к условиям вида:

  • «оканчивается на 25»;
  • «оканчивается на 39»;
  • «оканчивается на 117».

Если не убрать знак через abs(), можно получить неверную проверку.

1

Примеры:

# последняя цифра равна 3
abs(x) % 10 == 3

# двузначное число
10 <= abs(x) <= 99

# трёхзначное число
100 <= abs(x) <= 999

# четырёхзначное число
1000 <= abs(x) <= 9999

# количество цифр
len(str(abs(x)))

# оканчивается на 25
abs(x) % 100 == 25

# оканчивается на 39
abs(x) % 100 == 39

# оканчивается на 117
abs(x) % 1000 == 117

Главное правило

Если условие связано с цифрами числа, длиной числа или его разрядностью, сначала применяем abs(). Без этого ответ в таких задачах может оказаться неверным.

3. Код на Python и построчный разбор

Условие примера

Основная волна 2026

В файле содержится последовательность целых чисел. Её элементы могут принимать целые значения от -100 000 до 100 000 включительно.

Определите количество пар последовательности, в которых:

  • хотя бы одно число отрицательно;
  • сумма чисел пары меньше количества чисел в последовательности, кратных 100.

В ответе запишите количество найденных пар, затем максимальную из сумм элементов таких пар.

В данной задаче под парой подразумевается два идущих подряд элемента последовательности.

Полное решение

a = [int(i) for i in open('17.txt')]

count_100 = len([x for x in a if x % 100 == 0])
otvet = []

for i in range(len(a) - 1):
    if a[i] < 0 or a[i + 1] < 0:
        if (a[i] + a[i + 1]) < count_100:
            otvet.append(a[i] + a[i + 1])

print(len(otvet), max(otvet))

Что делает каждая строка

a = [int(i) for i in open('17.txt')]

Читаем файл и сразу превращаем каждую строку в целое число. Получаем список всех элементов последовательности.

count_100 = len([x for x in a if x % 100 == 0])

Считаем количество элементов, кратных 100.

otvet = []

Создаём пустой список, куда будем складывать суммы всех подходящих пар.

for i in range(len(a) - 1):

Перебираем все пары соседних элементов. -1 нужен, потому что у последнего элемента нет соседа справа.

if a[i] < 0 or a[i + 1] < 0:

Проверяем первое условие: хотя бы одно число в паре отрицательно.

Формулировка «хотя бы одно» переводится оператором or.

if (a[i] + a[i + 1]) < count_100:

Проверяем второе условие: сумма пары меньше количества элементов, кратных 100.

otvet.append(a[i] + a[i + 1])

Если оба условия выполнены, сохраняем сумму пары.

print(len(otvet), max(otvet))

Выводим количество подходящих пар и максимальную сумму среди них.

Ответ: 4963 93

Значит, найдено 4963 подходящие пары, а наибольшая сумма среди них равна 93.

4. Практика

Ниже — пять задач, расположенных по возрастанию сложности: от самых простых условий на пары до задачи с четвёрками и более составной проверкой.

Практика 1. Остаток по модулю и соседняя пара

Источник: Основная волна 2022

В файле содержится последовательность натуральных чисел. Элементы последовательности могут принимать целые значения от 1 до 100 000 включительно.

Определите количество пар последовательности, в которых остаток от деления хотя бы одного из элементов на 117 равен минимальному элементу последовательности.

В ответе запишите количество найденных пар, затем максимальную из сумм элементов таких пар.

В данной задаче под парой подразумевается два идущих подряд элемента последовательности.

Нюанс задачи

Сначала нужно один раз найти минимальный элемент всей последовательности.

Затем перебираем пары и проверяем, есть ли в паре хотя бы один элемент, у которого остаток при делении на 117 равен этому минимуму.

Решение на Python

a = [int(i) for i in open('17.txt')]
o = []

mn = min(a)

for i in range(len(a) - 1):
    s = [a[i], a[i + 1]]
    kr117 = [x for x in s if x % 117 == mn]

    if len(kr117) >= 1:
        o.append(sum(s))

print(len(o), max(o))

Ответ: 175 173738

Практика 2. Хотя бы один трёхзначный, оканчивающийся на 3

Источник: Основная волна 2024

В файле содержится последовательность целых чисел. Её элементы по модулю не превышают 100 000 включительно.

Определите количество троек элементов последовательности, в которых:

  • хотя бы один элемент оканчивается на 3 и является трёхзначным числом;
  • сумма всех элементов меньше максимального элемента последовательности, оканчивающегося на 3 и являющегося трёхзначным числом.

В ответе запишите количество найденных троек, затем максимальную из сумм элементов таких троек.

В данной задаче под тройкой подразумевается три идущих подряд элемента последовательности.

Нюанс задачи

Здесь abs() обязателен дважды:

  • при проверке последней цифры;
  • при проверке трёхзначности.

Сначала находим максимальный подходящий элемент всей последовательности, а потом перебираем тройки.

Решение на Python

a = [int(i) for i in open('17.txt')]
o = []

mx3 = max([x for x in a if abs(x) % 10 == 3 and 100 <= abs(x) <= 999])

for i in range(len(a) - 2):
    s = [a[i], a[i + 1], a[i + 2]]

    trehzn = [
        x for x in s
        if 100 <= abs(x) <= 999 and abs(x) % 10 == 3
    ]

    if len(trehzn) >= 1 and sum(s) < mx3:
        o.append(sum(s))

print(len(o), max(o))

Ответ: 147 944

Практика 3. Не более двух четырёхзначных

Источник: Основная волна 2025

В файле содержится последовательность целых чисел. Её элементы могут принимать целые значения от -100 000 до 100 000 включительно.

Определите количество троек элементов последовательности, в которых:

  • не более двух из трёх элементов являются четырёхзначными числами;
  • сумма элементов тройки не больше максимального элемента последовательности, оканчивающегося на 25.

В ответе запишите количество найденных троек, затем максимальную из сумм элементов таких троек.

В данной задаче под тройкой подразумевается три идущих подряд элемента последовательности.

Нюанс задачи

Фраза «не более двух» переводится как:

len(chetzn) <= 2

Для окончания на 25 и для четырёхзначности используем abs(), потому что знак не должен влиять на проверку.

Решение на Python

a = [int(i) for i in open('17.txt')]
o = []

mx25 = max([x for x in a if abs(x) % 100 == 25])

for i in range(len(a) - 2):
    s = [a[i], a[i + 1], a[i + 2]]

    chetzn = [
        x for x in s
        if 1000 <= abs(x) <= 9999
    ]

    if len(chetzn) <= 2 and sum(s) <= mx25:
        o.append(sum(s))

print(len(o), max(o))

Ответ: 6315 84523

Практика 4. Ровно одно четырёхзначное и квадрат суммы

Источник: Основная волна 2023

В файле содержится последовательность целых чисел. Элементы последовательности могут принимать целые значения от -100 000 до 100 000 включительно.

Определите количество пар последовательности, в которых:

  • только один из элементов является четырёхзначным числом;
  • квадрат суммы элементов пары не больше квадрата максимального элемента последовательности, являющегося четырёхзначным числом и оканчивающегося на 39.

В ответе запишите количество найденных пар чисел, затем максимальную из сумм элементов таких пар.

В данной задаче под парой подразумевается два идущих подряд элемента последовательности.

Нюанс задачи

Здесь важно не перепутать условие «только один»:

len(zn4) == 1

Сравнение идёт не самих сумм, а их квадратов, поэтому в коде проверяем:

sum(s) ** 2 <= mx ** 2

Решение на Python

a = [int(i) for i in open('17.txt')]
o = []

mx = max([
    x for x in a
    if 1000 <= abs(x) <= 9999 and abs(x) % 100 == 39
])

for i in range(len(a) - 1):
    s = [a[i], a[i + 1]]

    zn4 = [
        x for x in s
        if 1000 <= abs(x) <= 9999
    ]

    if len(zn4) == 1 and sum(s) ** 2 <= mx ** 2:
        o.append(sum(s))

print(len(o), max(o))

Ответ: 1591 9233

Практика 5. Четвёрки и минимум среди положительных, кратных 2025

В файле содержится последовательность целых чисел. Её элементы по модулю не превышают 100 000 включительно.

Определите количество четвёрок последовательности, в которых:

  • первый и последний элементы положительны;
  • абсолютное значение разности оставшихся элементов не превышает минимальный положительный элемент последовательности, кратный 2025.

Гарантируется, что такой элемент в последовательности есть.

В ответе запишите количество найденных четвёрок, затем минимальную из сумм элементов таких четвёрок.

Под четвёркой подразумеваются четыре идущих подряд элемента последовательности.

Нюанс задачи

Это уже задача на окно длины 4, поэтому цикл идёт до:

len(a) - 3

Сначала находим минимальный положительный элемент, кратный 2025.

Затем в каждой четвёрке отдельно проверяем:

  • знак первого элемента;
  • знак последнего элемента;
  • условие для двух средних элементов:
abs(s[1] - s[2]) <= mn

Решение на Python

a = [int(i) for i in open('17.txt')]
o = []

mn = min([
    x for x in a
    if x > 0 and abs(x) % 2025 == 0
])

for i in range(len(a) - 3):
    s = [a[i], a[i + 1], a[i + 2], a[i + 3]]

    if s[0] > 0 and s[-1] > 0:
        if abs(s[1] - s[2]) <= mn:
            o.append(sum(s))

print(len(o), min(o))

Ответ: 2876 -176511