Все задачи №27
№27

Красные гиганты, оранжевые гиганты

Звёзды на плоскости; кластеры — по прямоугольникам H×W; центр кластера — точка с минимальной суммой расстояний до остальных. Файл А — два кластера, файл Б — три. H=6,0, W=5,5. А: Ax, Ay — координаты красного гиганта, ближайшего к центру кластера с наименьшим числом точек. Б: B1 — расстояние между центрами кластеров с наименьшим и наибольшим числом оранжевых гигантов, B2 — наибольшее расстояние между жёлтыми карликами одного кластера. Ответ: |Ax|·10000, |Ay|·10000; B1·10000, B2·10000.

Источник: ФИПИ, № 29357

Скачать файл: task_29357_A.txt, task_29357_B.txt. В редакторе он уже лежит рядом с кодом, открывай как на экзамене: open('task_29357_A.txt').

Ответвпиши то, что вывела программа
Показать разбор
  1. Прочитай файл, заменив запятые на точки, и собери кластеры соседями: точка ближе порога t попадает в кластер. Центр это точка с наименьшей суммой расстояний до остальных.
  2. Порог подбирай отдельно для каждого файла: начни с t = 1, печатай размеры кластеров. Кластеров больше, чем в условии, увеличивай t, меньше, уменьшай. Бери t из середины диапазона, где число кластеров нужное и размеры похожи на настоящие кучки.
  3. Красный гигант это 'M' и 'III', оранжевый гигант это 'K' и 'III', жёлтый карлик это 'G' и 'V'. Цвет смотри в h[0], светимость в h[2:].
  4. Файл А: в кластере с наименьшим числом точек найди красного гиганта, ближайшего к центру, и выведи модули его координат, умноженные на 10000.
  5. Файл Б: посчитай оранжевых гигантов в кластерах. B1 это расстояние между центрами кластеров с наименьшим и наибольшим их числом. B2 это наибольшее расстояние между жёлтыми карликами одного кластера.
from math import dist

def load(name, t):
    data = []
    for line in open(name):
        x, y, h = line.replace(',', '.').split()
        data.append(([float(x), float(y)], h))
    clusters = []
    while data:
        clusters.append([data.pop(0)])
        for p in clusters[-1]:
            sosedi = [p1 for p1 in data if dist(p[0], p1[0]) < t]
            clusters[-1].extend(sosedi)
            for p1 in sosedi:
                data.remove(p1)
    return clusters

def centroids(cl):
    m = []
    for p in cl:
        sm = sum(dist(p[0], p1[0]) for p1 in cl)
        m.append([sm, p])
    return min(m)[1]

clusters = load('task_29357_A.txt', 2)
c = [centroids(cl) for cl in clusters]
i = 0 if len(clusters[0]) < len(clusters[1]) else 1
red = [p for p in clusters[i] if p[1][0] == 'M' and p[1][2:] == 'III']
star = min(red, key=lambda p: dist(p[0], c[i][0]))
print(int(abs(star[0][0]) * 10000), int(abs(star[0][1]) * 10000))

clusters = load('task_29357_B.txt', 1)
c = [centroids(cl) for cl in clusters]
counts = [sum(1 for p in cl if p[1][0] == 'K' and p[1][2:] == 'III') for cl in clusters]
a = counts.index(min(counts))
b = counts.index(max(counts))
B1 = dist(c[a][0], c[b][0])
B2 = 0
for cl in clusters:
    y = [p[0] for p in cl if p[1][0] == 'G' and p[1][2:] == 'V']
    for p1 in y:
        for p2 in y:
            B2 = max(B2, dist(p1, p2))
print(int(B1 * 10000), int(B2 * 10000))