Учёный решил провести кластеризацию некоторого множества звёзд по их расположению на карте звёздного неба. Кластер звёзд — это набор звёзд (точек) на графике. Каждый кластер имеет форму прямоугольника, причём эти прямоугольники между собой не пересекаются. Центр кластера — это одна из звёзд на графике, сумма расстояний от которой до всех остальных звёзд кластера минимальна.
В файле А хранятся данные о звёздах 2-х кластеров, в файле Б хранятся данные о звёздах 3-х кластеров. Для каждой звезды дана характеристика: тип цвета, тип светимости и её размер в соответствии с таблицей.
| Обозначение | Цвет | Обозначение | Размер |
|---|---|---|---|
| G | белый | I | сверхгигант |
| J | зеленый | II | яркий гигант |
| L | синий | III | гигант |
| N | оранжевый | IV | субгигант |
| Y | красный | V | карлик |
| S | голубой | VI | субкарлик |
| Z | желтый | VII | квазар |
Полученные значения записаны в характеристике слитно: обозначение цвета, светимость (обозначается цифрой 1–9) и обозначение размера (римские цифры).
Расстояние между двумя точками A(x1; y1) и B(x2; y2) вычисляется по формуле:
Даны два входных файла (файл А и файл Б). Для файла А определите координаты центра каждого кластера, затем найдите два числа: A1 — минимальное расстояние от центра кластера с наименьшим количеством точек до красного гиганта, и A2 — максимальное расстояние от центра кластера с наименьшим количеством точек до красного гиганта.
Для файла Б определите координаты центра каждого кластера, затем найдите два числа: B1 — минимальное расстояние между двумя различными жёлтыми карликами, расположенными в одном и том же кластере, и B2 — расстояние между центрами кластеров с минимальным и максимальным количеством жёлтых карликов.
В ответе запишите четыре числа: в первой строке — целую часть произведения A1 × 10 000, затем целую часть произведения A2 × 10 000; во второй строке — сначала целую часть произведения B1 × 10 000, затем целую часть произведения B2 × 10 000.
Ответ:
Построим диаграмму для файла А и В. Для этого откроем файлы с помощью python.
График для файла А:
График для файла В:
Приведём решение для файла А и B на языке Python.
import tkinter as tk
import math
all_stars = []
with open('27-1-B.txt') as f:
for line in f:
line = line.replace(',', '.').strip()
parts = line.split()
# Читаем координаты и тип
raw_x = float(parts[0])
raw_y = float(parts[1])
info = parts[2]
all_stars.append((raw_x, raw_y, info))
#Находим экстремумы для жесткого масштабирования
if all_stars:
xs = [s[0] for s in all_stars]
ys = [s[1] for s in all_stars]
min_x, max_x = min(xs), max(xs)
min_y, max_y = min(ys), max(ys)
# Задаем фиксированный размер окна
W, H = 1000, 700
pad = 50 # Отступ от краев, чтобы точки не прилипали к рамке
# Защита от деления на ноль, если все координаты одинаковые
dx = (max_x - min_x) if max_x != min_x else 1
dy = (max_y - min_y) if max_y != min_y else 1
# Рассчитываем SCALE
SCALE_X = (W - 2 * pad) / dx
SCALE_Y = (H - 2 * pad) / dy
SCALE = min(SCALE_X, SCALE_Y)
print(f"[+] Границы данных: X от {min_x} до {max_x}, Y от {min_y} до {max_y}")
print(f"[+] Вычисленный масштаб отрисовки (SCALE): {round(SCALE, 4)}")
else:
min_x, min_y, SCALE, pad, W, H = 0, 0, 1, 50, 1000, 700
# Перевод в пиксели
def to_px(rx, ry):
px = (rx - min_x) * SCALE + pad
py = H - ((ry - min_y) * SCALE + pad) # Инверсия Y для нормальной декартовой сетки
return px, py
# Клик-обработчик
def click_handler(event):
if not all_stars: return
# Переводим пиксели клика обратно в математику файла
cx = min_x + (event.x - pad) / SCALE
cy = min_y + (H - event.y - pad) / SCALE
closest = None
min_d = float('inf')
for star in all_stars:
rx, ry, info = star
d = math.hypot(cx - rx, cy - ry)
if d < min_d:
min_d = d
closest = star
rx, ry, info = closest
print(f"+ Клик мышкой по экрану в пикселях: ({event.x}, {event.y})")
print(f"* Ближайшая к клику реальная звезда: X = {rx}, Y = {ry}, Тип = {info}")
print("-" * 50)
# 3. Графический интерфейс Tkinter
root = tk.Tk()
root.title("Кликер Кластеров")
canvas = tk.Canvas(root, width=W, height=H, bg='black')
canvas.pack()
canvas.bind("<1>", click_handler)
# Отрисовка
for rx, ry, info in all_stars:
px, py = to_px(rx, ry)
color = 0
#print(info[0], info[2:])
# Цветовая подсветка
if 'Y' == info[0] and 'III' == info[2:]:
color = 'red' # Красный гигант
elif 'Z' == info[0] and 'V' == info[2:]:
color = 'yellow' # Желтый карлик
# Можно тегать для удобства убирая лишние звёзды
else:
color = '#444444' # Обычные серые фоновые звезды
# Рисуем жирные, заметные квадраты 2х2 пикселя
if color:
canvas.create_rectangle(px-1, py-1, px+1, py+1, fill=color, outline=color)
# Для файла A
#border_y = 10
#cluster_1 = [s for s in all_stars if s[1] < border_y]
#cluster_2 = [s for s in all_stars if s[1] > border_y]
# Выбираем тот список, у которого len() меньше:
#target_cluster = cluster_1 if len(cluster_1) < len(cluster_2) else cluster_2
# Для файла B
cluster_1 = [s for s in all_stars if s[1] < 14.2]
cluster_2 = [s for s in all_stars if s[1] > 24]
def best_centroid(target_cluster):
best_center = None
min_sum = float('inf')
for cx, cy, _ in target_cluster:
curr_sum = sum(math.hypot(cx - px, cy - py) for px, py, _ in target_cluster)
if curr_sum < min_sum:
min_sum = curr_sum
best_center = (cx, cy)
print(best_center)
# Для файла A
#best_centroid(target_cluster)
# Ответы A1 и A2
#print(int(((abs(6.6765541 - 7.0391548))**2 + (abs(12.0231751 - 12.3587258))**2)**0.5 * 10**4))
#print(int(((abs(2.8440425 - 7.0391548))**2 + (abs(6.226045 - 12.3587258))**2)**0.5 * 10**4))
# Для файла B
best_centroid(cluster_1), best_centroid(cluster_2)
# Ответы B1 и B2
print(int(((abs( 26.7044059 - 26.4871419))**2 + (abs(11.5764761 - 11.5419927))**2)**0.5 * 10**4))
print(int(((abs(26.6431823 - 13.9823808))**2 + (abs(12.4121727 - 26.4800432))**2)**0.5 * 10**4))
root.mainloop()

