К содержанию

Задание 27

Анализ данных

Точки и расстояния, чтение файла, разделение на кластеры по границам и признакам, центр перебором кандидатов и ответ по центрам и расстояниям.

6 подтем · 33 задачи + 9 дополнительных · высокий · ≈ 36 мин

Подтема 1 из 6

Точки, расстояния и файл

Что спрашивают в задании 27, точка и кластер в Python, расстояние, чтение файла с характеристиками, строка частицы и полярные координаты.

Как устроена тема

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

«Входной файл 27-4.txt содержит сведения о частицах, зарегистрированных детектором. В каждой строке записаны координаты частицы x и y, проекции её скорости vx и vy, масса m и признак частицы — римское число от I до VII; значения разделены табуляцией. Кинетическая энергия частицы E = m · (vx² + vy²) / 2. Частицы образуют четыре кластера: модуль разности энергий любых двух частиц одного кластера не превышает 2. Центром кластера назовём частицу, для которой сумма модулей разностей её энергии и энергий остальных частиц кластера минимальна. Найдите Q₁ — наибольшее расстояние между двумя частицами одного кластера с признаком II и Q₂ — наибольшую кинетическую энергию центра кластера. В ответе запишите целые части произведений Q₁ · 10 000 и Q₂ · 10 000.»

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

В условииЧто это значит
точка, звезда, частицаодна строка файла: координаты x и y и, может быть, характеристики
расстояние d(A, B) = √((x₂ − x₁)² + (y₂ − y₁)²)обычная длина отрезка: в Python — dist(a, b)
кластер, точки лежат внутри квадратовгруппы видны на рисунке, их разделяют границами
модуль разности энергий не превышает 2группы делят по вычисленной величине, а не по координатам
аномалииточки вне всех кластеров: их откладывают отдельно
центр — точка, сумма расстояний от которой до остальных минимальнаодна из точек кластера: проверяют каждую как кандидата
целая часть произведения на 10 000int(value * 10000) — дробную часть отбрасывают

Начнём с точек, расстояния и чтения файла — без них не обходится ни одна задача. Тема состоит из пяти подтем и дополнительного урока — у каждой своя страница:

  1. Точки, расстояния и файл — ты сейчас здесь: точка, расстояние, чтение строк с характеристиками.
  2. Разделение на кластеры — рисунок, границы, аномалии, деление по энергии.
  3. Центр кластера — перебор кандидатов и своя формула расстояния.
  4. Ответ по центрам — средние, наибольший и наименьший кластер, целая часть.
  5. Расстояния и пары точек — радиус, диаметр, пары одного вида; решим задачу темы.
  6. Соседи, другие центры и статистика — дополнительный урок для редких задач.

Точка и кластер

Что записано в строке файла и как хранить это в программе?

Строка файла — одна точка: пара чисел x и y. В Python точку хранят кортежем, кластер — списком точек, все кластеры — списком списков. Сюжет бывает любой — звёзды, частицы, деревья, — а программа видит пары чисел:

1.5 3.22.1 4.87.3 1.4

Координата x — положение по горизонтали, y — по вертикали. A = (2; 5) — на 2 единицы правее начала координат и на 5 выше. Отрицательная координата задаёт противоположное направление: B = (−3; 4) — на 3 левее и на 4 выше. В условиях x называют абсциссой, y — ординатой.

Пунктир от точки к осям показывает её координаты: A на 2 правее и на 5 выше начала координат, B — на 3 левее и на 4 выше.

Упорядоченная пара (2.0, 5.0) в Python — : элемент point[0] — координата x, point[1] — координата y. Точки собирают в , а кластеры — в список списков:

point = (2.0, 5.0)x, y = pointprint(point[0], y) clusters = [    [(0, 0), (1, 1), (2, 0)],    [(10, 8), (11, 9)]]clusters[1].append((12, 8)) print(len(clusters))      # сколько кластеровprint(len(clusters[1]))   # сколько точек во второмfor x, y in clusters[1]:    print(x, y)
2.0 5.0 2 3 10 8 11 9 12 8

x, y = point раскладывает пару по двум переменным, append добавляет точку в конец списка, а цикл for x, y in … перебирает точки сразу с координатами. Не путай два количества: len(clusters) — сколько групп, len(clusters[1]) — сколько точек в группе.

Расстояние

Как найти расстояние между двумя точками, зная их координаты?

Разности координат — катеты прямоугольного треугольника, а расстояние — его гипотенуза: d(A, B) = √((x₂ − x₁)² + (y₂ − y₁)²). Для A = (1; 2) и B = (4; 6) по горизонтали точки отличаются на 4 − 1 = 3, по вертикали — на 6 − 2 = 4:

Катеты треугольника — разности координат 3 и 4, гипотенуза — расстояние между точками: √(3² + 4²) = √25 = 5.

Такое расстояние называют евклидовым — это обычная длина отрезка. Формулу можно записать самому: ** 2 — квадрат, ** 0.5 — корень. Но в модуле math уже есть функция dist, ею и будем пользоваться:

from math import dist a, b = (1, 2), (4, 6)dx, dy = b[0] - a[0], b[1] - a[1]print((dx ** 2 + dy ** 2) ** 0.5)print(dist(a, b))print(int(dist((0, 0), (1, 1)) * 10000))
5.0 5.0 14142

Последняя строка — формат ответа задания 27: значение умножают на 10 000 и отбрасывают дробную часть. √2 ≈ 1,41421356, а ответ — 14142. Это делает , а не round: подробнее — в подтеме 4.

Пригодятся три свойства: d(A, B) = d(B, A), d(A, A) = 0 и d(A, B) ≥ 0.

Сравнение с порогом

Нужно ли извлекать корень, чтобы проверить, что точки ближе заданного расстояния?

Нет: при r ≥ 0 условие d(A, B) ≤ r равносильно (x₂ − x₁)² + (y₂ − y₁)² ≤ r², и корень не нужен.

a, b, r = (1, 2), (4, 6), 5 dx = a[0] - b[0]dy = a[1] - b[1] if dx * dx + dy * dy <= r * r:    print("Точки достаточно близки")
Точки достаточно близки

Почему это допустимо? Для неотрицательных чисел возведение в квадрат сохраняет порядок: если одно расстояние меньше другого, его квадрат тоже меньше. Здесь 25 ≤ 25 — ровно потому, что 5 ≤ 5.

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

Чтение файла

Как прочитать точки из файла и ни одной не потерять?

Сначала посмотри на первые строки файла, потом разбирай каждую строку в три действия: заменить запятые точками, разделить, превратить части в числа. Форматы бывают разные — выбери, чтобы увидеть, что с ним делать:

числа через пробел
1.25 3.70читаем как есть
запятая в дробях
1,25 3,70заменить запятые точками
заголовок
X Yпропустить первую строку
табуляция
1,25→3,70→K3Vsplit() делит и по табуляции

Метод меняет запятые на точки, без аргументов делит строку по пробелам и табуляциям, сколько бы их ни было подряд, а превращает текст в дробное число:

line = "1,25   3,70"parts = line.replace(",", ".").split()print(parts)print(float(parts[0]) + float(parts[1]))
['1.25', '3.70'] 4.95

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

def read_points(filename, has_header=False):    points = []    with open(filename, encoding="utf-8-sig") as f:        if has_header:            f.readline()        for line in f:            if not line.strip():                continue            parts = line.replace(",", ".").split()            points.append((float(parts[0]), float(parts[1])))    return points  points = read_points("example27.txt", has_header=True)print(len(points), points[:3])
8 [(0.0, 0.0), (0.0, 2.0), (1.0, 1.0)]
  • открывает файл и сам закрывает его после блока; for line in f перебирает строки.
  • f.readline() читает одну строку — так пропускаем заголовок, если has_header истинно. По умолчанию заголовка нет.
  • if not line.strip(): continue пропускает пустые строки — обычно пустую последнюю.
  • points[:3] — , первые три точки. После чтения всегда выводи количество и первые точки.
Заголовок:пропустить лишнее опаснее, чем забыть

Если заголовок не пропустить, программа сразу остановится: ValueError: could not convert string to float: 'X'. Это хотя бы заметно. Обратная ошибка тише: в файле 27-1.txt заголовка нет, и пропуск первой строки «на всякий случай» молча теряет точку:

print(len(read_points("27-1.txt")))print(len(read_points("27-1.txt", has_header=True)))
205 204

И ещё: латинская A и кириллическая А в имени файла выглядят одинаково, но для компьютера это разные символы.

Код звезды

Как прочитать строку, где после координат записан код звезды?

Код хранят в той же записи, что и координаты, а разбирают по позициям символов. В задачах ЕГЭ-2026 у каждой звезды записан код вроде K3V слитно: латинская буква — спектральный класс (цвет), цифра — подкласс, римское число — класс светимости. Так устроен и наш файл 27-3.txt:

4,387365 8,408613 A0III1,932849 1,048969 K3V3,921424 2,369304 VII

Буква задаёт цвет, римское число — размер звезды. Таблицы соответствия даны в условии; выбери обозначение, чтобы увидеть, что оно значит:

O
голубая
B
бело-голубая
A
белая
F
жёлто-белая
G
жёлтая
K
оранжевая
M
красная
I
сверхгигант
II
яркий гигант
III
гигант
IV
субгигант
V
карлик
VI
субкарлик
VII
белый карлик

«Красный гигант» в условии буквально переводится в две проверки: класс M и светимость III.

Обрати внимание на третью строку: у белых карликов в файле записан только класс светимости VII, без буквы и цифры. Поэтому code[0] не всегда спектральный класс.

Код разбирается по позициям символов: нулевой — класс, первый — подкласс, остальное — светимость. У VII нулевой символ — уже часть светимости.

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

def parse_kind(code):    if code[0] in "OBAFGKM":        return code[0], code[1], code[2:]    return "", "", code  print(parse_kind("M4III"))print(parse_kind("VII"))
('M', '4', 'III') ('', '', 'VII')

Для M4III выполняется строка 3: буква, цифра и всё остальное — срез code[2:]. Для VII проверка в строке 2 ложна, и функция возвращает пустой класс. Записи файла читаем так же, как точки, только сохраняем ещё и код:

def read_stars(filename):    stars = []     with open(filename, encoding="utf-8-sig") as f:        for line in f:            parts = line.replace(",", ".").split()            x, y = float(parts[0]), float(parts[1])            stars.append((x, y, parts[2]))     return stars
stars = read_stars("27-3.txt")print(len(stars))print(stars[:2])
601 [(4.387365, 8.408613, 'A0III'), (1.932849, 1.048969, 'K3V')]

Для расстояния берут только координаты — срез s[:2], первые два элемента записи: dist(s[:2], t[:2]). Код в расчёт не идёт, по нему только отбирают звёзды нужного вида.

Строка частицы

Как прочитать строку частицы из задачи темы?

Строка частицы — шесть частей: пять чисел и признак. Кластер здесь определяют не координаты, а энергия, вычисленная по скорости и массе. В файле 27-4.txt записаны координаты x и y, проекции скорости vx и vy, масса m и признак — римское число. Значения разделены табуляцией, дробная часть — запятой. split() справляется и с табуляцией:

def read_particles(filename):    particles = []     with open(filename, encoding="utf-8-sig") as f:        for line in f:            parts = line.replace(",", ".").split()            x, y, vx, vy, m = [float(v) for v in parts[:5]]            particles.append((x, y, vx, vy, m, parts[5]))     return particles

Первые пять частей становятся числами и раскладываются по именам, признак остаётся строкой. В записи частицы p номер части — номер элемента кортежа:

Первая строка файла 27-4.txt: шесть частей через табуляцию. Скорость — p[2] и p[3], масса — p[4], признак p[5] остаётся строкой.

Кинетическая энергия частицы массы m со скоростью (vx; vy) — E = m · (vx² + vy²) / 2. Например, для массы 0,8 и скорости (2; −1,5): E = 0,8 · (4 + 2,25) / 2 = 2,5. Запишем формулу функцией и проверим её на этом примере и на первой частице файла:

def energy(p):    vx, vy, m = p[2], p[3], p[4]    return m * (vx ** 2 + vy ** 2) / 2
print(energy((1.25, -3.4, 2.0, -1.5, 0.8, "III"))) particles = read_particles("27-4.txt")print(len(particles))print(particles[0], energy(particles[0]))
2.5 402 (-12.554, 9.248, 1.957, 1.743, 1.768, 'VII') 6.071221832

У первой частицы файла энергия около 6,07. По энергиям частицы и разделим на кластеры в подтеме 2.

Полярные координаты

Что делать, если в строке файла записаны не x и y, а угол и расстояние до начала координат?

Это полярные координаты: угол φ и радиус r. До всех расчётов их переводят в обычные: x = r · cos φ, y = r · sin φ. Угол отсчитывают от положительного направления оси x против часовой стрелки, радиус — расстояние от начала координат до точки:

Точка с углом 60° и радиусом 4 — это (2; 3,464), точка с углом 210° и радиусом 2 — (−1,732; −1). Пунктир — её координаты x и y.

Функции cos и sin из модуля math ждут угол в радианах, а в файле он в градусах. Переводит radians; без неё cos(60) считает косинус 60 радиан:

from math import cos, sin, radians  def polar_to_xy(phi, r):    a = radians(phi)    return r * cos(a), r * sin(a)  x, y = polar_to_xy(60, 4)print(round(x, 3), round(y, 3))print(round(cos(60), 3), round(cos(radians(60)), 3))  def read_polar(filename):    points = []    with open(filename, encoding="utf-8-sig") as f:        for line in f:            parts = line.replace(",", ".").split()            phi, r = float(parts[0]), float(parts[1])            points.append(polar_to_xy(phi, r))    return points  points = read_polar("27-7.txt")print(len(points), [round(v, 3) for v in points[0]])
2.0 3.464 -0.952 0.5 250 [5.76, 2.757]

В файле 27-7.txt первая строка — 25,581 6,386: угол 25,581°, радиус 6,386. После перевода это точка (5,76; 2,757), и дальше с ней работают как с любой другой: расстояния считают по x и y.

Итого

  • Точка и кластеркортеж (x, y), список точек, список списков
  • Расстояниеdist(a, b); с порогом сравнивают квадраты
  • Ответint(value * 10000) — целая часть
  • Чтениеreplace(",", "."), split(), float; заголовок — только если он есть
  • Характеристикирядом с координатами; код звезды — сначала проверь букву
  • Частица и полярныеE = m · (vx² + vy²) / 2; x = r · cos φ, y = r · sin φ

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1
Какая из точек (3, 4), (-4, 2), (1, -5) ближе всех к началу координат? Чему равно это расстояние?
ОтветСкрыть ответ
Ответ
(-4, 2): квадраты расстояний 25, 20 и 26, расстояние √20 ≈ 4,472.
Вопрос 2
Точки (4, 7) и (1, 3). Верно ли, что расстояние между ними не больше 5? А что оно меньше 5? Проверь без извлечения корня.
ОтветСкрыть ответ
Ответ
Не больше 5 — да: 3² + 4² = 25 ≤ 25. Меньше 5 — нет: 25 < 25 неверно.
Вопрос 3
Что вернут "-2,5\t4,75".split(" ") и "-2,5 4,75".replace(",", ".").split()?
ОтветСкрыть ответ
Ответ
Первое — ['-2,5\t4,75']: по пробелу строку с табуляцией не разделить. Второе — ['-2.5', '4.75']: split() делит по любым пробельным символам, сколько бы их ни было подряд.
Вопрос 4
Разбери коды K7V, VII и A0III: спектральный класс, цвет и класс светимости.
ОтветСкрыть ответ
Ответ
K7V — класс K (оранжевая), светимость V (карлик); VII — белый карлик без спектрального класса; A0III — класс A (белая), светимость III (гигант).
Вопрос 5
В файле записаны полярные координаты 90 5 и 180 2. Какие это точки на обычной плоскости?
ОтветСкрыть ответ
Ответ
(0; 5) и (−2; 0): x = r · cos φ, y = r · sin φ, cos 90° = 0, sin 90° = 1, cos 180° = −1, sin 180° = 0. В Python угол сначала переводят в радианы — radians(phi).

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

Кластеры как список списков

Дано clusters = [[(0, 0), (1, 1)], [(5, 5), (6, 5), (7, 6)], [(10, 0)]]. Чему равны len(clusters), len(clusters[1]) и clusters[1][2][0]?

Введите три числа через пробел в том порядке, в каком их спрашивают.

Расстояние 3–4–5

Найди евклидово расстояние между (2, 1) и (5, 5).

Введите число.

Расстояние с отрицательными координатами

Найди расстояние между (-1, -2) и (5, 6).

Введите число.

Расстояние в формате ответа

Найди расстояние между точками A (−1,5; 2,25) и B (3,1; −0,4). В ответе запиши целую часть произведения найденного расстояния на 10 000.

Введите число.

Звёзды и белые карлики

Сколько звёзд записано в файле 27-3.txt и сколько среди них белых карликов?

27-3.txtЗвёзды: координаты и характеристикаТекстовый файл · 13,6 КБ

Введите два числа через пробел: количество звёзд и количество белых карликов.

Красные гиганты

Сколько красных гигантов (класс M, светимость III) в файле 27-3.txt?

27-3.txtЗвёзды: координаты и характеристикаТекстовый файл · 13,6 КБ

Введите число.

Кинетическая энергия

Найди кинетическую энергию частицы массы 2 со скоростью (−1; 3).

Введите число.

Наибольшая энергия частицы

В файле 27-4.txt записаны частицы: координаты x и y, проекции скорости vx и vy, масса m и признак. Найди наибольшую кинетическую энергию частицы файла. В ответе запиши целую часть произведения найденной энергии на 10 000.

27-4.txtЧастицы: координаты, скорость, масса, признакТекстовый файл · 14,3 КБ

Введите число.

Полярные координаты звёзд

В файле 27-7.txt записаны звёзды в полярных координатах: в каждой строке — полярный угол φ в градусах и полярный радиус r. Переведи все точки в обычные координаты x = r · cos φ, y = r · sin φ и найди наибольшую абсциссу и наибольшую ординату. В ответе запиши целые части произведений этих чисел на 10 000.

27-7.txtЗвёзды в полярных координатах: угол и радиусТекстовый файл · 3,3 КБ

Введите два числа через пробел в том порядке, в каком их спрашивают.