№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').
Ответвпиши то, что вывела программа
Показать разбор
- Прочитай файл, заменив запятые на точки, и собери кластеры соседями: точка ближе порога t попадает в кластер. Центр это точка с наименьшей суммой расстояний до остальных.
- Порог подбирай отдельно для каждого файла: начни с t = 1, печатай размеры кластеров. Кластеров больше, чем в условии, увеличивай t, меньше, уменьшай. Бери t из середины диапазона, где число кластеров нужное и размеры похожи на настоящие кучки.
- Красный гигант это 'M' и 'III', оранжевый гигант это 'K' и 'III', жёлтый карлик это 'G' и 'V'. Цвет смотри в h[0], светимость в h[2:].
- Файл А: в кластере с наименьшим числом точек найди красного гиганта, ближайшего к центру, и выведи модули его координат, умноженные на 10000.
- Файл Б: посчитай оранжевых гигантов в кластерах. 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))