Что проверяет задание
Дана таблица: каждая строка, набор чисел. Нужно посчитать, сколько строк удовлетворяют логическому условию на повторы, суммы, средние, чётность или отношение величин.
Определения
Строка таблицы, один набор значений. Условие проверяют независимо для каждой строки, если не сказано иное.
Повторяющиеся значения, числа, которые встречаются в строке больше одного раза. Полезно отдельно смотреть, сколько различных чисел в строке и каковы их кратности.
Кратность, сколько раз конкретное число встретилось в строке.
Среднее арифметическое, сумма чисел, делённая на их количество.
Квадрат / произведение, часто сравнивают квадрат одного числа с произведением других, чтобы не извлекать корень.
Чётность, свойство делиться на 2. Для нескольких чисел смотрят, сколько среди них чётных.
Диапазон строки, разность между максимальным и минимальным числом.
Уникальный элемент, число с кратностью 1.
Ровно / хотя бы / не более, кванторы на количество. «Ровно одно повторяющееся» не то же самое, что «есть повторяющиеся».
Как не перепутать условие
Сложное условие почти всегда, конъюнкция или дизъюнкция нескольких свойств. Нужно сохранить связки: «и», «или», «либо … либо». Особенно осторожно с фразами:
- «все числа различны»;
- «есть ровно два одинаковых, остальные различны»;
- «самое большое число встречается один раз»;
- «сумма повторяющихся больше суммы неповторяющихся».
Перед подсчётом полезно переписать условие как набор предикатов над мультимножеством чисел строки.
Общий алгоритм решения
- Понять структуру файла: сколько чисел в строке, чем они разделены, есть ли заголовок.
- Формализовать условие через кратности, суммы, максимум, минимум и чётность.
- Для каждой строки вычислить нужные характеристики и проверить предикат.
- Посчитать, сколько строк предикат истинен.
- Если просят сумму подходящих строк, номер строки или значение в строке, не подменить это количеством.
- Проверить граничные случаи: все числа равны, два максимума, ноль, отрицательные числа.
Программа построчно
На экзамене задание 9 решают в электронной таблице формулами. Но то же самое быстрее и надёжнее сделать программой на Python: прочитать файл строка за строкой и посчитать строки, которые подходят под условие.
Разберём программу на условии:
В каждой строке файла 9.csv записаны натуральные числа. Определите количество строк, в которых все числа различны и наибольшее число меньше суммы остальных.
count = 0
for line in open("9.csv", encoding="utf-8"):
arr = list(map(int, line.split(";")))
if len(arr) == len(set(arr)) and max(arr) < sum(arr) - max(arr):
count += 1
print(count)
count = 0 - счётчик подходящих строк.
for line in open("9.csv", encoding="utf-8"): - открываем файл и перебираем его строки по одной. Каждая строка файла попадает в переменную line в виде текста, например '263;79;191\n'. Подробно - в разделе «Чтение файла».
arr = list(map(int, line.split(";"))) - превращаем текст строки в список чисел [263, 79, 191]. Эта строка разобрана по шагам в разделе «Чтение файла».
if … and …: - условие из задачи. Каждая часть, соединённая словом and, - один пункт условия: «все числа различны» и «наибольшее меньше суммы остальных».
count += 1 - строка подходит, увеличиваем счётчик.
print(count) - печатаем ответ после того, как просмотрены все строки.
Чтение файла
В задании 9 таблица дана в файле электронной таблицы 9.ods (формат LibreOffice Calc; Excel его тоже открывает). Программе удобнее читать обычный текст, поэтому таблицу сначала сохраняют как CSV:
- Откройте
9.odsв LibreOffice Calc или Excel. - «Файл → Сохранить как» (в Excel - «Сохранить как → Другие форматы»).
- Тип файла - «Текст CSV (.csv)», имя -
9.csv. - В окне параметров выберите разделитель полей «;» и сохраните. На вопрос о формате ответьте «Использовать формат CSV».
Получится текстовый файл, в котором каждая строка таблицы - строка вида 263;79;191.
Файл из условия сохраняют в формате .csv (числа через ;) или .txt (числа через пробел) и кладут рядом с программой - тогда к нему можно обращаться просто по имени.
for line in open("9.csv", encoding="utf-8"):
arr = list(map(int, line.split(";")))
Как строка '263;79;191\n' превращается в список чисел:
line.split(";")- разрезает текст по точке с запятой:['263', '79', '191\n']. Получились строки, а не числа. Если числа в файле разделены пробелами, пишутline.split()без аргумента - он режет по любым пробелам и сам отбрасывает перевод строки.map(int, …)- применяетintк каждому куску:'263'→ 263,'191\n'→ 191 (intсам убирает перевод строки и пробелы по краям).list(…)- собирает результат в список:[263, 79, 191]. Список нужен, потому что дальше к числам обращаются по номеру и считают по нимsum,max,count.
encoding="utf-8" - в какой кодировке записан файл; для файлов только с цифрами её можно не указывать, но привычка полезная.
Если в файле в конце есть пустая строка, int('') вызовет ошибку. Её пропускают проверкой if not line.strip(): continue.
Подсчёт строк
count = 0
for line in open("9.csv", encoding="utf-8"):
arr = list(map(int, line.split(";")))
if условие:
count += 1
print(count)
Счётчик увеличивается только для строк, где условие истинно. Несколько условий соединяют словом and - строка подходит, только если выполнены все. Если в задаче «выполнено хотя бы одно из условий», используют or.
print(count) пишется без отступа - после цикла. С отступом число печаталось бы после каждой строки файла.
Сумма, максимум, среднее
sum(arr)- сумма всех чисел строки;max(arr),min(arr)- наибольшее и наименьшее;max(arr) - min(arr)- разность наибольшего и наименьшего («размах»);sum(arr) - max(arr)- сумма всех чисел, кроме наибольшего («сумма остальных»);sum(arr) / len(arr)- среднее арифметическое:len(arr)- количество чисел в строке;x % 5 == 0- число кратно 5 (остаток от деления на 5 равен нулю),x % 2 == 1- нечётное.
Сортировка строки
arr.sort()
sort() упорядочивает список по возрастанию прямо на месте: [263, 79, 191] → [79, 191, 263]. После сортировки arr[0] - наименьшее число, arr[-1] - наибольшее, arr[1] - среднее из трёх. Это удобно, когда условие говорит о «наибольшей стороне» или «двух меньших».
sorted(arr) делает то же, но возвращает новый список, а исходный не меняет.
Повторяющиеся числа
set(arr) - множество чисел строки: каждое значение хранится в нём один раз. Для [3, 7, 7, 2, 9, 1] множество - {1, 2, 3, 7, 9}, в нём 5 элементов, а в строке 6 чисел.
- «все числа различны» →
len(arr) == len(set(arr)): повторов нет, если множество не короче строки; - «ровно одно число повторяется дважды, остальные различны» (в строке из 6 чисел) →
len(set(arr)) == 5; arr.count(x)- сколько раз число x встречается в строке;[x for x in arr if arr.count(x) == 2]- список всех чисел, которые встречаются ровно 2 раза;[x for x in arr if arr.count(x) == 1]- неповторяющиеся.
Counter
from collections import Counter
c = Counter(arr)
Counter считает, сколько раз встречается каждое число строки. Для [5, 3, 5, 5, 8] получится Counter({5: 3, 3: 1, 8: 1}): пятёрка - 3 раза, тройка и восьмёрка - по разу.
c.values()- только количества: 3, 1, 1;- «какое-то число встречается ровно три раза» →
3 in c.values(); - «повторов нет» →
max(c.values()) == 1: даже самое частое число встречается один раз; c[5]- сколько раз встречается конкретное число 5.
any и all
any(x % 5 == 0 for x in arr)-True, если хотя бы одно число строки кратно 5;all(x % 2 == 1 for x in arr)-True, если все числа нечётные.
Внутри скобок - короткая запись цикла: «для каждого x из arr проверить условие». Это то же самое, что цикл с флажком, только в одну строку.
Геометрия в строках
Если три числа строки - длины сторон, сначала их сортируют: arr.sort(), тогда arr[2] - наибольшая сторона.
- Треугольник существует (неравенство треугольника), если сумма двух меньших сторон больше наибольшей:
arr[0] + arr[1] > arr[2]. Для других пар сторон неравенство выполняется автоматически, поэтому достаточно одной проверки. - Остроугольный треугольник: квадрат наибольшей стороны меньше суммы квадратов двух других -
arr[0] ** 2 + arr[1] ** 2 > arr[2] ** 2(**- возведение в степень). Равенство - прямоугольный, обратный знак - тупоугольный. - Параллелепипед с рёбрами a ≤ b ≤ c: площади граней -
a * b,a * c,b * c, наибольшая из нихb * c. «Площадь наибольшей грани больше суммы двух других»:arr[0] * arr[1] + arr[0] * arr[2] < arr[1] * arr[2].
