Задачи пробного тура чемпионата
по программированию трека «Аналитика»
A. Рассчитать pFound
Отправить решение задачи на платформе Яндекс.Контест
Условие задачи
В архиве содержится три текстовых файла:
- qid_query.tsv — id запроса и текст запроса, разделённые табуляцией;
- qid_url_rating.tsv — id запроса, URL документа, релевантность документа запросу;
- hostid_url.tsv — id хоста и URL документа.
Нужно вывести текст запроса с максимальным значением метрики , посчитанной по топ-10 документов.
Если для запроса есть несколько документов с одним и тем же id хоста — оставить только максимально релевантный документ (а если несколько документов максимально релевантны, выбрать любой).
Документы по запросу сортируются по убыванию релевантности после выбора одного документа для хоста. Если у нескольких документов с разных хостов релевантность одинакова, их порядок может быть произвольным.
Формула для расчёта :
Формат вывода
Текст запроса с максимальным значением метрики.
Например, для open_task.zip правильный ответ:
гугл переводчик
Решение
import pandas as pd
# считываем данные
qid_query = pd.read_csv("hidden_task/qid_query.tsv", sep="\t", names=["qid", "query"])
qid_url_rating = pd.read_csv("hidden_task/qid_url_rating.tsv", sep="\t", names=["qid", "url", "rating"])
hostid_url = pd.read_csv("hidden_task/hostid_url.tsv", sep="\t", names=["hostid", "url"])
# делаем join двух таблиц, чтобы было просто брать url с максимальным рейтингом
qid_url_rating_hostid = pd.merge(qid_url_rating, hostid_url, on="url")
def plook(ind, rels):
if ind == 0:
return 1
return plook(ind-1, rels)*(1-rels[ind-1])*(1-0.15)
def pfound(group):
max_by_host = group.groupby("hostid")["rating"].max() # максимальный рейтинг хоста
top10 = max_by_host.sort_values(ascending=False)[:10] # берем топ10 урлов с наивысшим рейтингом
pfound = 0
for ind, val in enumerate(top10):
pfound += val*plook(ind, top10.values)
return pfound
qid_pfound = qid_url_rating_hostid.groupby('qid').apply(pfound) # группируем по qid и вычисляем pfound
qid_max = qid_pfound.idxmax() # берем qid с максимальным pfound
qid_query[qid_query["qid"] == qid_max]
B. Спортивный турнир
Отправить решение задачи на платформе Яндекс.Контест
Условие задачи
Ограничение времени | 2 секунды |
Ограничение памяти | 256 Mb |
Ввод | стандартный ввод или input.txt |
Вывод | стандартный вывод или output.txt |
Пока Маша была в отпуске, её коллеги организовали турнир по шахматам по олимпийской системе. За отдыхом Маша не обращала особого внимания на эту затею, так что она еле может вспомнить, кто с кем играл (о порядке игр даже речи не идёт). Внезапно Маше пришла в голову мысль, что неплохо бы привезти из отпуска сувенир победителю турнира.
Маша не знает, кто победил в финале, но сможет без труда вычислить, кто в нём играл, если только она правильно запомнила играющие пары. Помогите ей проверить, так ли это, и определить возможных кандидатов в победители.
Формат ввода
В первой строке находится целое число — количество прошедших игр. В последующих строках — по две фамилии игроков (латинскими заглавными буквами) через пробел. Фамилии игроков различны. Все фамилии уникальны, однофамильцев среди коллег нет.
Формат вывода
Выведите NO SOLUTION
, если Маша неправильно запомнила игры и по этой сетке нельзя получить турнир по олимпийской системе. Если турнирная сетка возможна, выведите в одной строке две фамилии кандидатов на первое место (порядок неважен).
Пример 2
Ввод | Вывод |
7 | IURKOVSKII GORBOVSKII |
GORBOVSKII ABALKIN | |
SIKORSKI KAMMERER | |
SIKORSKI GORBOVSKII | |
BYKOV IURKOVSKII | |
PRIVALOV BYKOV | |
GORBOVSKII IURKOVSKII | |
IURKOVSKII KIVRIN |
Пример 1
Ввод | Вывод |
3 | NO SOLUTION |
IVANOV PETROV | |
PETROV BOSHIROV | |
BOSHIROV IVANOV |
Примечания
Олимпийская система, также известная как плей-офф — система организации соревнований, при которой участник выбывает из турнира после первого же проигрыша. Подробнее о системе можно почитать в Википедии.
Схема первого теста из условия:
Решение
Из количества игр легко получить количество раундов турнира . Обозначим количество игр, которые сыграл i-й участник, через Очевидно, что финалисты сыграли максимальное количество раз (они единственные играли во всех раундах). Теперь научимся проверять, что данный нам набор встреч между участниками возможен в турнире по олимпийской системе. Заметим, что игра между участниками и могла произойти только в раунде поскольку этот раунд был последним для кого-то из них (раунды для удобства нумеруются с единицы). Назовём псевдораундом номер множество игр для которых Проверку корректности будем делать в соответствии с таким утверждением:
Утверждение. Набор из игр задаёт турнир по олимпийской системе тогда и только тогда, когда:
- В каждом псевдораунде все участники различны.
- Количество игр в псевдораунде равно
Доказательство. Необходимость этих двух условий очевидна: псевдораунды соответствуют настоящим раундам турнира, а для настоящих раундов условия верны. Достаточность докажем индукцией по . При есть одна игра с двумя различными участниками — это корректный олимпийский турнир. Проверим переход Во-первых, докажем, что каждый участник турнира играл в первом псевдораунде. Рассмотрим произвольного игрока, пусть он участвовал в играх. В каждом псевдораунде он мог сыграть не более одного раза, причём в псевдораундах после -го он не мог играть ни разу. Значит, он должен был сыграть по одному разу в каждом из псевдораундов 1, 2, ..., . Это, в частности, означает, что все люди сыграли в первом псевдораунде, а всего игроков Теперь докажем, что в каждой из игр первого псевдораунда был ровно один участник с Как минимум один такой участник в каждой игре должен быть по определению псевдораунда. С другой стороны, есть не менее человек с — это участники следующего псевдораунда. Следовательно, людей с было ровно по одному на каждую игру. Теперь легко понять, как должен выглядеть первый раунд искомого турнира: назначим в каждой игре первого псевдораунда проигравшим участника с а победителем — участника с Множество игр между победителями удовлетворяет условию для (после выбрасывания игр из первого псевдораунда все уменьшились на 1). Следовательно, этому множеству соответствует турнир по олимпийской системе.
import sys
import collections
def solve(fname):
games = []
for it, line in enumerate(open(fname)):
line = line.strip()
if not line:
continue
if it == 0:
n_games = int(line)
n_rounds = n_games.bit_length()
else:
games.append(line.split())
gamer2games_cnt = collections.Counter()
rounds = [[] for _ in range(n_rounds + 1)]
for game in games:
gamer_1, gamer_2 = game
gamer2games_cnt[gamer_1] += 1
gamer2games_cnt[gamer_2] += 1
ok = True
for game in games:
gamer_1, gamer_2 = game
game_round = min(gamer2games_cnt[gamer_1], gamer2games_cnt[gamer_2])
if game_round > n_rounds:
ok = False
break
rounds[game_round].append(game)
finalists = list((gamer for gamer, games_cnt in gamer2games_cnt.items() if games_cnt == n_rounds))
for cur_round in range(1, n_rounds):
if len(rounds[cur_round]) != pow(2, n_rounds - cur_round):
ok = False
break
cur_round_gamers = set()
for gamer_1, gamer_2 in rounds[cur_round]:
if gamer_1 in cur_round_gamers or gamer_2 in cur_round_gamers:
ok = False
break
cur_round_gamers.add(gamer_1)
cur_round_gamers.add(gamer_2)
print ' '.join(finalists) if ok else 'NO SOLUTION'
def main():
solve('input.txt')
if __name__ == '__main__':
main()
Увидимся на капе
================