9 5

Мы уже успешно освоили программное решение целых двух типов 9 заданий из ЕГЭ по информатике. Научились работать с файлами в Python, на практике применили многие типовые шаблоны функций, а также познакомились с работой функции enumerate().

Осталось сделать последний шаг – разобрать алгоритм решения третьего типа – и балл за задание 9 у нас в кармане! Давайте же приступим.

Алгоритм решения

Вспомним, что в третьем типе 9 заданий от нас требуется не только найти нужную строку, в которой выполняются все условия, но и произвести с ней какие-либо математические действия. Обычно потребуется просто подсчитать сумму чисел в такой строке с помощью встроенной функции sum().

Алгоритм решения уже вам знаком:

1. Считываем данные из файла все той же конструкцией

with open('file.txt') as f:
    data = [list(map(int, i.split())) for i in f]

2. Пишем одну или две функции, в которых будем проверять выполнение условий

3. Проверяем в цикле все строки, как только находим нужную – суммируем числа в ней и завершаем работу цикла оператором break

for line in data:
    if f1(line) and f2(line):
        print(sum(line)) 
      break

Если же требуется найти строку с наибольшим номером и просуммировать значения в ней, то будем поступать, как при решении заданий второго типа – просто инвертируем порядок значений в data срезом [::-1].

for line in data[::-1]:
    if f1(line) and f2(line):
        print(sum(line)) 
      break

На этом все, никаких более нововведений в решении не предвидится. Приступим сразу к практике.

Пример 1

Начнём мы с такой формулировки:

Задание 915

«Откройте файл электронной таблицы, содержащей в каждой строке семь натуральных чисел. Определите сумму всех чисел в строке таблицы с наименьшим номером, для чисел которой выполнены оба условия:

— в строке есть два числа, каждое из которых повторяется дважды, остальные три числа различны;
— максимальное число строки не повторяется.

В ответе запишите только число.»

Все эти условия уже нам знакомы, сразу перейдём к созданию функций для их проверки.

Найдём все числа строки, которые повторяются дважды, вот такой конструкцией:

cnt_2 = {i for i in line if line.count(i) == 2}

Здесь у нас будет множество всех таких чисел. В подходящей нам строке в этом множестве должно быть ровно два таких элемента. Но стоит также проверить и вторую часть этого условия: все остальные числа должны быть различны.

Тогда найдём все неповторяющиеся числа:

no_repeat = [i for i in line if line.count(i) == 1]

В заключительном шаге необходимо потребовать, чтобы повторяющихся чисел было ровно 2, то есть количество элементов в cnt_2 равнялось двум, а неповторяющихся было 3, что говорит о наличии трёх элементов в списке no_repeat:

len(cnt_2) == 2 and len(no_repeat) == 3

Собираем все эти три строки в одну функцию:

def f1(line):
    cnt_2 = {i for i in line if line.count(i) == 2}
    no_repeat = [i for i in line if line.count(i) == 1]
    return len(cnt_2) == 2 and len(no_repeat) == 3

Переходим ко второму условию. Здесь все максимально просто! Находим наибольшее число функцией max():

max_num = max(line)

И проверяем, что в списке line это число встречается всего 1 раз:

line.count(max_num) == 1

Оформим все это в виде функции f2():

def f2(line):
    max_num = max(line)
    return line.count(max_num) == 1

На этом все, перед функциями вставляем блок кода для считывания данных из файла, после – цикл for с проверкой каждой строки и выводом суммы чисел первой подходящей под все условия строки.

Выглядеть наша программа будет так:

# Чтение данных из файла
with open('915.txt') as f:
    data = [list(map(int, i.split())) for i in f]

# Два числа повторяются дважды,
# остальные три числа различны
def f1(line):
    cnt_2 = {i for i in line if line.count(i) == 2}
    no_repeat = [i for i in line if line.count(i) == 1]
    return len(cnt_2) == 2 and len(no_repeat) == 3

# Mаксимальное число не повторяется
def f2(line):
    max_num = max(line)
    return line.count(max_num) == 1

for line in data:
    if f1(line) and f2(line):
        print(sum(line))
        break

В качестве результата выводится число 261, которое и запишем в ответ.

Пример 2

Рассмотрим такую формулировку:

Задание 914

«Откройте файл электронной таблицы, содержащей в каждой строке семь натуральных чисел. Определите сумму чисел в строке с наибольшим номером, для которой выполнены оба условия:

– в строке есть одно число, которое повторяется трижды, остальные четыре числа различны;
– среднее арифметическое неповторяющихся чисел строки не больше повторяющегося числа.

В ответе запишите только число.»

Первое условие до боли похоже на то, что было в прошлом примере. Только теперь нужно найти всего одно число, которое повторяется трижды. Можем воспользоваться прошлым кодом, немного скорректировав его под новые вводные.

Но обратите внимание, теперь мы собираем все повторяющиеся элементы не во множество, а в список! Чуть позже поймёте зачем.

cnt_3 = [i for i in line if line.count(i) == 3]

Далее все так же ищем неповторяющиеся числа:

no_repeat = [i for i in line if line.count(i) == 1]

И требуем, чтобы в cnt_3 было 3 элемента, а в no_repeat4.

len(cnt_3) == 3 and len(no_repeat) == 4

Оформим все в виде функции:

def f1(line):
    cnt_3 = [i for i in line if line.count(i) == 3]
    no_repeat = [i for i in line if line.count(i) == 1]
    return len(cnt_3) == 3 and len(no_repeat) == 4

Следующим шагом рассмотрим второе условие. Снова работаем все с теми же списками чисел: одно, повторяющееся 3 раза, и четыре неповторяющихся. Конструкции используем все те же:

cnt_3 = [i for i in line if line.count(i) == 3]
no_repeat = [i for i in line if line.count(i) == 1]

Найдём среднее арифметическое неповторяющихся:

mean = sum(no_repeat)/len(no_repeat)

И вот теперь тот момент, из-за которого мы и использовали список, а не множество. Нам нужно сравнить среднее арифметическое с повторяющимся числом. Но получить значение из множества через индекс мы не можем! А в случае со списком нам достаточно будет обратиться к первому элементу cnt_3 и убедиться, что он больше или равен среднему арифметическому:

mean <= cnt_3[0]

Запишем все в виде функции:

def f2(line):
    cnt_3 = [i for i in line if line.count(i) == 3]
    no_repeat = [i for i in line if line.count(i) == 1]
    mean = sum(no_repeat)/len(no_repeat)
    return mean <= cnt_3[0]

И не забудем, что в задании требуется строка с наибольшим номером! Следовательно, перевернём список data срезом [::-1].

Весь код нашей программы выглядит следующим образом:

# Чтение данных из файла
with open('914.txt') as f:
    data = [list(map(int, i.split())) for i in f]

# Одно число повторяются трижды,
# остальные три числа различны
def f1(line):
    cnt_3 = [i for i in line if line.count(i) == 3]
    no_repeat = [i for i in line if line.count(i) == 1]
    return len(cnt_3) == 3 and len(no_repeat) == 4

# среднее арифметическое неповторяющихся
# не больше повторяющегося
def f2(line):
    cnt_3 = [i for i in line if line.count(i) == 3]
    no_repeat = [i for i in line if line.count(i) == 1]
    mean = sum(no_repeat)/len(no_repeat)
    return mean <= cnt_3[0]

for line in data[::-1]:
    if f1(line) and f2(line):
        print(sum(line))
        break

И тут у вас могут возникнуть «флешбэки» прошлой статьи. Мы ранее уже работали с похожей задачей, где искали среднее арифметическое. Там пришли к выводу, что не всегда целесообразно писать разные функции, дублирующие код друг друга.

Давайте и в этот раз рассмотрим альтернативное решение, в котором избавимся от функций, а все условия запишем внутри цикла. Среднее арифметическое также будем искать функцией mean из statistics.

Преображённый код функции:

from statistics import mean

# Чтение данных из файла
with open('914.txt') as f:
    data = [list(map(int, i.split())) for i in f]

for line in data[::-1]:
    cnt_3 = [i for i in line if line.count(i) == 3]
    no_repeat = [i for i in line if line.count(i) == 1]
    if (len(cnt_3) == 3 and len(no_repeat) == 4
            and mean(no_repeat) <= cnt_3[0]):
        print(sum(line))
        break

В результате её работы получаем сумму элементов нужной строки – 901. Это число и будем ответом на наше задание.

Больше заданий данного типа с подробным решением вы можете найти в нашем тренажёре