Статья Автор: Деникина Н.В., Деникин А.В.

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

Обработка данныхПоследовательности
Алгоритмы · теория и практикаПары и тройки · полный разбор
Пары и тройки в последовательности

Опорные элементы, скользящее окно, подсчёт и агрегация — на примере двоек и троек


1Зачем это нужно

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

Задачи на пары (окно из 2 соседей) и тройки (окно из 3 соседей) решаются по одному и тому же шаблону — меняются лишь условия внутри окна. Разберём оба случая.

Операция Пример
Фильтрация оставить числа не кратные 5; трёхзначные
Опорный элемент минимум по модулю; k-й кратный числу m
Скользящее окно 2 соседа (пара) или 3 соседа (тройка)
Агрегация количество, максимальная сумма, среднее

2Общий подход

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

ШАГ 1
Чтение
Все числа из файла в список a
ШАГ 2
Опоры
Найти опорные значения (N, S и т. п.) по всему списку
ШАГ 3
Окно
Пройти соседние пары/тройки, проверить условия
ШАГ 4
Ответ
Посчитать количество и нужную агрегацию
каркасa = [int(line) for line in open('file.txt')]   # шаг 1: число в строке
# шаг 2: опорные значения...
for i in range(len(a) - 1):     # пары: -1; тройки: -2
    w = a[i:i+2]              # окно (для тройки a[i:i+3])
    if # условия на окно:
        ...                    # шаг 3-4

3Кирпичики: делимость, цифры, разряды
Нужно Как
кратно m x % m == 0 (0 кратен любому m)
не кратно m x % m != 0
минимум по модулю min(seq, key=abs)
трёхзначное 100 ≤ abs(x) ≤ 999
сумма цифр функция ds(x) (см. ниже)
округление вниз total // count (для положительных)
сумма цифрdef ds(n):
    n = abs(n)              # на случай отрицательных
    s = 0
    while n > 0:
        s += n % 10          # последняя цифра
        n //= 10              # отбрасываем её
    return s
# ds(472) = 13,  ds(-900) = 9,  ds(100000) = 1
Часть I · Пары (окно из 2 соседей)
4Пары: пример и разбор
Условие. В файле последовательность целых чисел. Пусть N — минимальное по модулю число, не кратное 5. Определите количество пар соседних элементов, в которых оба числа кратны N. В ответе: количество таких пар, затем максимальную из их сумм.

Разбор

Сначала находим N (фильтр «не кратно 5» нужен только для этого). Затем идём по соседним парам и считаем те, где оба элемента кратны N, попутно держа максимум суммы.

парыcand = [x for x in a if x % 5 != 0]
N = min(cand, key=abs)              # опорное число

count = 0
best = -10**9                      # «минус бесконечность», не 0!
for i in range(len(a) - 1):
    if a[i] % N == 0 and a[i+1] % N == 0:
        count += 1
        best = max(best, a[i] + a[i+1])

print(count, best)
Стартовое значение максимума — −10**9, потому что суммы пар бывают отрицательными; ноль дал бы неверный ответ.

5Интерактив: анализ пар

Выбери последовательность. Программа найдёт N (золотая ячейка), подсветит кратные N (синие) и кратные 5 (серые), снизу отметит соседние пары, где оба кратны N. Над максимальной парой — золотая скоба.

N (опорное) кратно N кратно 5
Анализ парSIM · SWITCHABLE
 
 
Данные:
 
 

Нажми «сгенерировать» — появится новая случайная последовательность (в ней всегда хотя бы 3 подходящие пары), и N, пары и максимум пересчитаются сами. В примере «суммы < 0» все подходящие пары имеют отрицательные суммы — максимум там отрицательный, а не ноль. Поэтому и нужен старт best = −10**9.

Часть II · Тройки (окно из 3 соседей)
6Тройки: пример и разбор
Условие. Последовательность натуральных чисел. Определите количество троек идущих подряд элементов, для которых: есть хотя бы одно трёхзначное число; не более одного числа с суммой цифр, равной сумме цифр 13-го по счёту элемента, кратного 13; не менее двух чисел с суммой цифр, равной сумме цифр 25-го кратного 25. В ответе: количество троек и среднее их сумм, округлённое вниз.

Разбор

Опорные суммы цифр: S₁₃ — сумма цифр 13-го кратного 13 (это индекс 12 в списке кратных!), S₂₅ — сумма цифр 25-го кратного 25 (индекс 24). Затем по каждой тройке считаем три величины и проверяем три условия.

тройкиS13 = ds([x for x in a if x % 13 == 0][12])   # 13-й → индекс 12
S25 = ds([x for x in a if x % 25 == 0][24])   # 25-й → индекс 24

count = total = 0
for i in range(len(a) - 2):
    t = a[i:i+3]
    has3 = any(100 <= abs(x) <= 999 for x in t)  # ≥1, по модулю
    c13  = sum(ds(x) == S13 for x in t)       # ≤1
    c25  = sum(ds(x) == S25 for x in t)       # ≥2
    if has3 and c13 <= 1 and c25 >= 2:
        count += 1
        total += sum(t)

print(count, total // count)        # среднее вниз
Сравниваем именно суммы цифр с S₁₃/S₂₅, а не сами числа. И «13-й по счёту» — это индекс 12.

7Интерактив: опора и сканер троек

Сначала потренируйся находить k-й кратный m и его сумму цифр:

k-й элемент, делящийся на mSIM · LIVE
 
 
Делитель m:
Номер k:3
 
 

Теперь сканер троек (опорные суммы заданы: S₁₃ = 5, S₂₅ = 7). Двигай ползунок — окно из трёх соседей едет по последовательности, внизу видно выполнение трёх условий.

∑ цифр = S₂₅ = 7 ∑ цифр = S₁₃ = 5 трёхзначное
Сканер троекSIM · LIVE
 
 
 
Окно с:0
 
 

8Подводные камни
Ошибка Как правильно
искать трёх- (и др.) значные у отрицательных через 100 ≤ x ≤ 999 число берём по модулю: 100 ≤ abs(x) ≤ 999 — иначе −144 не попадёт в трёхзначные
best = 0 для максимума суммы суммы бывают отрицательными → best = −10**9
фильтр «не кратно 5» при подсчёте пар он нужен только для поиска N
взять d13[13] 13-й по счёту — это индекс 12
сравнивать сами числа вместо сумм цифр сравниваем ds(x) с опорной суммой
перепутать ≤1 и ≥2 «не более одного» = ≤1; «не менее двух» = ≥2
округлить среднее обычным round нужно вниз: total // count
искать опоры по ходу окна сначала весь список, потом окно

9Полные коды решений

Пары

парыa = [int(line) for line in open('file.txt')]
N = min((x for x in a if x % 5 != 0), key=abs)
count = 0; best = -10**9
for i in range(len(a) - 1):
    if a[i] % N == 0 and a[i+1] % N == 0:
        count += 1; best = max(best, a[i] + a[i+1])
print(count, best)

Тройки

тройкиdef ds(n):              # сумма цифр (см. раздел 3)
    n = abs(n); s = 0
    while n > 0: s += n % 10; n //= 10
    return s

a = [int(line) for line in open('file.txt')]
S13 = ds([x for x in a if x % 13 == 0][12])
S25 = ds([x for x in a if x % 25 == 0][24])
count = total = 0
for i in range(len(a) - 2):
    t = a[i:i+3]
    if (any(100 <= abs(x) <= 999 for x in t)
            and sum(ds(x) == S13 for x in t) <= 1
            and sum(ds(x) == S25 for x in t) >= 2):
        count += 1; total += sum(t)
print(count, total // count)

10Чек-лист перед ответом
№ Что проверить
1 Прочитал все числа в список, проверил первые элементы
2 Опорные значения нашёл по всему списку (N; S₁₃/S₂₅ — индексы 12 и 24)
3 Окно правильного размера: пара (i, i+1) или тройка (i..i+2)
4 Условия-счётчики не перепутаны (≥1, ≤1, ≥2)
5 Максимум суммы стартует с −10**9, среднее округляю вниз
6 В ответе сначала количество, потом агрегат (сумма/среднее)

11Квиз по файлу

Вопросы ниже — по отдельному файлу quiz.txt (приложен к странице): 600 целых чисел, по одному в строке, среди них есть отрицательные. Глазами столько не перебрать — открой файл и посчитай кодом, затем выбери ответ.

Загрузи файл в Python привычным способом и считай по нему:
a = [int(line) for line in open('quiz.txt')]
Помни про отрицательные: трёхзначные ищем по модулю (100 ≤ abs(x) ≤ 999), сумму цифр — тоже по модулю.

Вопросы вперемешку: и на пары, и на тройки.

Проверь себя10 задач по файлу
 
 
 
Обработка последовательности · пары и тройки · теория, примеры, практика по файлу
Attached files
quiz.txt
Печать