Найти в Дзене

Алгоритм решения задания 9 ЕГЭ по информатике. Часть 5

Ранее мы уже не только освоили программные методы решения 9 заданий, но и научились их применять к первому типу 9 заданий. Теперь же перейдём ко второму типу и закрепим изученный материал. Но для начала нам нужно познакомиться с такой полезной функцией Python как enumerate(). Давайте незамедлительно приступим к этому! Как вы уже знаете, для решения второго типа 9 заданий нам потребуется определить наибольший или наименьший номер строки из файла. То есть необходимо как-то вести учёт индекса каждой проверяемой в цикле for строки. Можно, конечно, создать отдельную переменную-счётчик, в которой будем хранить номер текущей строки. Но это не самый практичный и удобный способ. В Python для одновременного получения как индекса, так и значения текущего элемента используется специальная функция – enumerate(). Функция имеет следующий синтаксис: Где: Функция enumerate() возвращает объект-перечислитель (enumerate object), который генерирует кортежи вида (индекс, элемент). При каждой итерации мы пол
Оглавление

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

Но для начала нам нужно познакомиться с такой полезной функцией Python как enumerate(). Давайте незамедлительно приступим к этому!

Функция enumerate()

Как вы уже знаете, для решения второго типа 9 заданий нам потребуется определить наибольший или наименьший номер строки из файла. То есть необходимо как-то вести учёт индекса каждой проверяемой в цикле for строки.

Можно, конечно, создать отдельную переменную-счётчик, в которой будем хранить номер текущей строки. Но это не самый практичный и удобный способ. В Python для одновременного получения как индекса, так и значения текущего элемента используется специальная функция – enumerate().

Функция имеет следующий синтаксис:

-2

Где:

  • iterable — любой итерируемый объект (список, кортеж, строка, файл и т.д.). В задании 9 мы работаем со списками.
  • start — начальное значение счётчика (по умолчанию 0). Этот параметр особенно важен для решения заданий ЕГЭ, так как нумерация строк обычно начинается с 1, а не с 0.

Функция enumerate() возвращает объект-перечислитель (enumerate object), который генерирует кортежи вида (индекс, элемент). При каждой итерации мы получаем два значения:

  • Порядковый номер элемента (начиная со значения параметра start)
  • Сам элемент последовательности

В большинстве заданий ЕГЭ нумерация строк в файле начинается с 1, а не с 0 (как принято в программировании). Параметр start=1 позволяет корректно соотнести номера строк в программе с номерами, указанными в условии задачи.

Давайте проверим работу этой функции на простом примере:

-3

Теперь установим значение параметра start, равное 1:

-4

И для закрепления рассмотрим пример посложнее. Представим, что у нас есть 5 строк по 3 числа в каждой:

15, 23, 41
30, 72, 55
22, 18, 60
85, 33, 21
40, 40, 15

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

-5

Теперь в цикле будем перебирать индексы строк и значения. Обратите внимание, что значения у нас будут в виде списков с числами каждой строки!

-6

Теперь в переменной total подсчитаем сумму чисел строки:

-7

Если эта сумма больше 100, то сохраняем номер строки (idx) в список indexes:

-8

В конце выведем значение переменной indexes. Весь код у нас будет такой:

-9

Теперь усложним задачу: найдём наименьший номер строки, сумма чисел в которой больше 100. Конечно, можно просто взять первое число из списка indexes. Но на практике нецелесообразно создавать отдельный список для всех индексов, тем более если нам нужен только первый из них.

Давайте поступим так: как только выполнится условие, мы сразу выведем значение номера строки (idx) на экран и на этом завершим выполнение цикла оператором break. Выглядеть это будет следующим образом:

-10

Отлично, мы добились желаемого! А что, если потребуется не наименьший, а наибольший номер строки?

Тогда давайте просто «перевернём» список: будем идти не с первой строки, а с последней. В таком случае при первом же выполнении условия у нас уже будет номер самой последней подходящей строки.

Перевернуть список можно с помощью такого среза: [::-1]. Только вспомните, что функция enumerate() возвращает нам не список, а специальный объект (enumerate object), к которому применять срезы нельзя!

Но не беда, можем просто получить из этого объекта-перечислителя список, обернув его в функцию list():

-11

Теперь мы готовы найти наибольший номер строки:

-12

Итак, давайте подведём итоги применения функции enumerate() в рамках 9 заданий. Если нам нужно найти наименьший индекс строки, то последний блок кода будем оформлять следующим образом:

-13

Здесь в line находятся числа каждой строки, а в data – все данные, считанные из файла. В функциях f1() и f2(), как обычно, результаты выполнения условий.

Если же требуется найти наибольший номер строки, то блок кода будет выглядеть так:

-14

На этом можем закончить разбор функции enumerate() и перейти к решению 9 заданий.

Пример 1

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

Задание 916

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

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

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

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

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

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

-15

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

А находить все неповторяющиеся числа мы уже умеем:

-16

Осталось лишь потребовать, чтобы во множестве cnt_2 был только один элемент, а в списке no_repeat4:

-17

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

-18

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

Только теперь нужно найти среднее арифметическое неповторяющихся чисел. Сделаем это такой записью:

-19

В конце потребуем, чтобы повторяющееся дважды число – первый элемент множества cnt_2 был больше или равен значению переменной mean:

-20

В виде функции это записывается так:

-21

Добавим к нашим двум функциям блоки кода с чтением данных и с проверкой каждой строки и выводом ответа:

-22

В результате работы программы получим ответ на это задание – число 34.

Но обратите внимание, что в обеих функциях мы используем одни и те же конструкции для поиска неповторяющихся чисел и числа, которое повторяется дважды. Так делать нехорошо: во-первых, нарушается принцип DRY (don’t repeat yourself), во-вторых, это замедляет выполнение кода, ведь мы дважды выполняем одинаковые действия.

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

И, раз уж собрались вносить изменения, то избавимся и от ручного вычисления среднего арифметического – используем лучше готовую функцию mean из модуля statistics. В итоге придём к такому виду нашей программы:

-23

В результате её работы получаем все тот же ответ – 34.

Пример 2

Следующим рассмотрим задание с такой формулировкой:

Задание 913

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

— в строке все числа различны;
— удвоенная сумма минимального и максимального чисел строки равна утроенной сумме трёх её оставшихся чисел.

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

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

-24

В целом, можно это выражение написать сразу в условие внутри цикла или же заменить на такую лямбда-функцию:

-25

Теперь перейдём ко второму условию. В прошлой статье мы уже работали с наибольшим и наименьшим значениями через функции max() и min(). В этот раз давайте пойдём через сортировку и срезы.

Отсортируем исходный список по возрастанию:

-26

Теперь найти удвоенную сумму минимального и максимального числа можно сложив первый и последний элемент списка и умножив эту сумму на 2:

-27

А утроенное значения оставшихся получим путём сложения чисел от второго до предпоследнего элемента списка и умножения этой суммы на 3:

-28

В конце потребуем равенства значений переменных doubled и tripled. Запишем все в одной функции:

-29

Решение почти готово. Осталось не забыть, что нам нужен наибольший номер строки. Так что оборачиваем enumerate() в список и инвертируем его порядок срезом [::-1]. Тогда весь код нашей программы будет выглядеть следующим образом:

-30

Запустив программу, получим ответ на это данное задание – число 13412.

В этой статье мы научились работать с функцией enumerate() и решать 9 задания второго типа. Осталось лишь закрепить полученные навыки и освоить алгоритм решения третьего типа 9 заданий. Но все это будет уже в следующей статье!

<<< Предыдущая статья Следующая статья >>>