Курс№17. Последовательность из файла0%
Теория · номер 17 из 27

Последовательность из файла

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

10 разделов~35 минут1 первичный балл
  1. 1Что проверяет номер
  2. 2Чтение файла
  3. 3Пары
  4. 4Тройки
  5. 5Оканчивается на…
  6. 6Дополнения
  7. 7Пример с abs и максимумом до цикла
  8. 8Как решать
  9. 9Ловушки
  10. 10Домашка
Раздел 1 из 10

Что проверяет номер

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

Файл с последовательностью чисел. Проходим окном из двух или трёх соседних элементов, отбираем окна по условию. В ответ два числа: сколько окон подошло и наибольшая (или сумма) из каких-то значений.

Раздел 2 из 10

Чтение файла

Эта строка одна на все задачи номера, меняется только имя файла. После неё в a лежит обычный список чисел.

python
a = [int(line) for line in open('17_23757.txt')]

Каждая строка файла — одно число. Разделитель \r вместо \n тоже работает: Python читает файл как текст и понимает оба.

Разберём запись по частям:

Запись длинная только с виду. Вот то же самое обычным циклом, а рядом учебный файл 17-demo.txt, чтобы сразу запустить:

python
a = []
for line in open('17-demo.txt'):
    a.append(int(line))

print(len(a))
print(a[:5])

скачать 17-demo.txt

Раздел 3 из 10

Пары

Перед циклом считаем всё, что относится ко всей последовательности, а в цикле проверяем соседей. В примере минимальное двузначное считается один раз, до цикла.

python
a = [int(line) for line in open('17_23757.txt')]
c = []
mn = min(x for x in a if 10 <= x <= 99)             # минимальное двузначное

for i in range(len(a) - 1):                          # до предпоследнего идём
    if (10 <= a[i] <= 99) + (10 <= a[i + 1] <= 99) == 1:     # ровно одно двузначное
        if (a[i] + a[i + 1]) % mn == 0:
            c.append(a[i] + a[i + 1])
print(len(c), max(c))

Условие считаем сложением: True + False == 1. «Ровно два из трёх» — == 2, «хотя бы одно» — >= 1 (или or).

Весь путь на учебном файле

Условие: пары соседних чисел, где ровно одно двузначное, а сумма делится на 3. Нужны количество таких пар и наибольшая сумма. Несколько пар из файла:

a[i]a[i + 1]суммаподходит
35722783850нет
240-84156да
-84672588да
672-46626нет

Проверь каждую строку сам: сколько чисел двузначные и делится ли сумма на 3.

python
a = [int(line) for line in open('17-demo.txt')]

c = []
for i in range(len(a) - 1):
    x, y = a[i], a[i + 1]
    good = (10 <= abs(x) <= 99) + (10 <= abs(y) <= 99)
    if good == 1 and (x + y) % 3 == 0:
        c.append(x + y)

print(len(c), max(c))

скачать 17-demo.txt

Почему len(a) - 1? В списке из 5 чисел пар всего 4. Если дойти до последнего индекса, a[i + 1] выйдет за конец списка и будет ошибка.

Почему складываем условия? Python считает True за 1, а False за 0. Значит, сумма условий равна числу выполненных. Это короткая запись для «ровно одно из двух».

Попробуй самучебная задача

Дан список a = [12, -7, 25, 40, 33, -18, 9, 57, -21, 16, 70, 27]. Найди число пар соседних элементов, сумма которых делится на 3, и наибольшую такую сумму. Запиши два числа через пробел.

Подсказка

Список можно вставить в редактор прямо как есть.

Разбор на коротком списке

Возьмём [5, 12, 7]. Пар всего две: 5 и 12, 12 и 7. Поэтому цикл идёт по range(len(a) - 1), то есть i равно 0 и 1. Число 12 участвует в обеих парах, это нормально.

в условиив коде
ровно одно из двух(усл1) + (усл2) == 1
хотя бы одноусл1 or усл2
обаусл1 and усл2
двузначное, с учётом минуса10 <= abs(x) <= 99
кратно 7x % 7 == 0
Попробуй самучебная задача

Дан список a = [105, -12, 47, 8, -99, 64, 31, -250, 73, 16]. Найди число пар соседних, где ровно одно число двузначное (знак не учитываем), и наибольшую сумму такой пары. Запиши два числа через пробел.

Подсказка

10 <= abs(x) <= 99.

Раздел 4 из 10

Тройки

Тройки устроены так же, только индексов три, а цикл заканчивается на одну позицию раньше. Удобно сразу назвать элементы x1, x2, x3.

python
a = [int(x) for x in open('17_23949.txt')]

def f(x):
    return str(x)[0] == str(x)[-1]                   # первая цифра = последней

def p(x):
    return 10000 <= x <= 99999 and str(x)[-4:] == '1717'     # пятизначное, оканчивается на 1717 (пример)

c = []
for i in range(len(a) - 2):
    x1, x2, x3 = a[i], a[i + 1], a[i + 2]
    if f(x1) + f(x2) + f(x3) == 1:
        if p(x1) + p(x2) + p(x3) == 2:
            c.append(max(x1, x2, x3))
print(len(c), sum(c))

Что считать в ответ (max, sum, сумма тройки) зависит от условия. Условия оформляем функциями f, p.

Попробуй самучебная задача

Для того же списка a = [12, -7, 25, 40, 33, -18, 9, 57, -21, 16, 70, 27] найди число троек соседних элементов, в которых ровно два чётных числа, и наибольшую сумму такой тройки. Запиши два числа через пробел.

Подсказка

Отрицательные чётные тоже чётные: x % 2 == 0 работает и для них.

Раздел 5 из 10

Оканчивается на…

Отрицательные числа есть почти в каждом файле, поэтому привычка писать abs спасает от потери балла.

Проверка «оканчивается на 152», два способа:

  1. abs(x) % 1000 == 152 (abs — модуль, абсолютное значение);
  2. str(x)[-3:] == '152'.

«В числе есть тройка»: '3' in str(x).

Раздел 6 из 10

Дополнения

Эти две функции встречаются часто. Их можно просто вставлять в начало решения.

Простое число:

python
def p(x):
    return x > 1 and all(x % d != 0 for d in range(2, int(x ** 0.5) + 1))

Цифры идут по возрастанию, без повторов:

python
def up(x):
    return str(x) == ''.join(sorted(str(x))) and len(str(x)) == len(set(str(x)))

Для 147 истинно, для 122 ложно (повтор) и для 174 ложно. ''.join(...) склеивает отсортированные цифры обратно в строку: без него строку нельзя сравнить со списком.

Попробуй самучебная задача

Дан список a = [11, 4, 13, 9, 17, 6, 23, 20, 5, 8]. Найди число троек соседних, где ровно два простых числа, и наибольшую сумму такой тройки. Запиши два числа через пробел.

Подсказка

Возьми функцию p выше.

Раздел 7 из 10

Пример с abs и максимумом до цикла

Здесь собрано всё сразу: максимум с особым свойством, модуль и тройки.

python
a = [int(x) for x in open('17.txt')]
mx = max(x for x in a if str(x)[-2:] == '30')        # максимум, оканчивающийся на 30
m = []
for i in range(len(a) - 2):
    x1, x2, x3 = a[i], a[i + 1], a[i + 2]
    if len(str(abs(x1))) != 4:                       # abs: число без знака минус
        if (x1 + x2 + x3) > mx:
            m.append(x1 + x2 + x3)
print(len(m), max(m))

Максимум считаем до цикла, один раз по всей последовательности.

Попробуй самучебная задача

Для списка a = [12, -7, 25, 40, 33, -18, 9, 57, -21, 16, 70, 27] найди наибольшее число, модуль которого оканчивается на 7. Затем посчитай тройки соседних, сумма которых больше этого числа, и наибольшую такую сумму. Запиши два числа через пробел.

Подсказка

Максимум считаем до цикла, один раз.

Раздел 8 из 10

Как решать

Этот порядок подходит для любой задачи номера.

  1. Читаем файл.
  2. До цикла считаем «глобальное»: минимум, максимум с особым свойством, количество кратных.
  3. Условия окна оформляем функциями.
  4. Цикл range(len(a) - 1) для пар и range(len(a) - 2) для троек.
  5. Подходящие значения в список c, в ответ len(c) и max(c) или sum(c).
Раздел 9 из 10

Ловушки

Ловушка

Цикл до len(a) - 1 для пар и len(a) - 2 для троек, иначе выйдешь за конец списка.

Ловушка

Для знака и количества цифр отрицательного числа: len(str(abs(x))). Просто str(x) посчитает минус как символ.

Ловушка

Оканчивается на: str(x)[-3:] читает цифры без знака сам. А x % 1000 у отрицательных даёт другое число (-1152 % 1000 = 848), поэтому используем abs(x) % 1000.

Ловушка

Максимум и минимум — до цикла.

Ловушка

Скобки: (a < x < b) + (c < y < d) == 1.

Раздел 10 из 10

Домашка

Задачи с настоящих экзаменов и из банка ФИПИ. Решай прямо здесь: кнопка «Решать здесь» открывает редактор, а код каждой задачи сохраняется.

Задачи «Попробуй сам» учебные, в домашке задачи с настоящих экзаменов и из банка ФИПИ. Код в блоках можно менять и запускать, он выполняется прямо в браузере.