Расписание спортивной лиги: неравномерное распределение матчей - PullRequest
2 голосов
/ 23 апреля 2019

Я сейчас пытаюсь создать расписание для разных лиг.Я прочитал вопросы о круговом приеме, а также могу составить расписание на сезон с первой и второй половиной.Однако я пытаюсь добиться:

  • Лиги с 16 или 32 командами
  • 60 игр за сезон (в 16 командах лиги играют с каждым соперником 4 раза, в 32 командных лигахсыграйте с каждым соперником дважды)
  • Пять-восемь игр в день
  • Нет нескольких игр на команду в день
  • Равномерное распределение домашних и выездных игр
  • Игрыв последовательные дни возможны, но не более двух подряд

Что я пробовал до сих пор?В качестве первого шага я создал список всех возможных сопоставлений с помощью itertools:

import itertools

p = ['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10', 'A11', 'A12', 'A13', 'A14', 'A15', 'A16', 'A17', 'A18', 'A19', 'A20', 'A21', 'A22', 'A23', 'A24', 'A25', 'A26', 'A27', 'A28', 'A29', 'A30', 'A31']

f = list(itertools.combinations(p, 2))

# [('A0', 'A1'), ('A0', 'A2'), ('A0', 'A3'), ... ]

С этого момента я мог бы выбрать неправильный путь, решив работать с индексами.Поэтому я создал список списков c, где каждый подсписок является копией f.Список f представлен n раз в c в зависимости от размера лиги (16 команд: 4x; 32 команды: 2x).

Редактировать:

Небольшое обновление какЯ все еще работаю над этим:

  • Я реализовал равномерное распределение домашних / выездных игр
  • Скрипт теперь возвращает фактическое расписание с 5-8 играми в день, хотяс исключениями

См. следующий код для лиги 32 команд:

import itertools
import random

def get_current_list(c):
    if c[0] != 0:
        if len(c[0]) != 0:
            return 0
        if len(c[0]) == 0 and len(c[1]) != 0:
            return 1
    else:
        return 1

def check_list_status(c,cl):
    if len(c[cl]) < 9:
        return True
    else:
        return False

def get_matchup(c, cl):
    games_today = []
    how_many_games_today = random.randint(5,8)

    error = False
    for game in range(how_many_games_today):
        game_not_found = True

        counter = 0
        while game_not_found:
            list_length = len(c[cl])
            index = list_length - 1

            counter += 1
            if counter > 100:
                error = True
                break

            choice_index = random.randint(0,index)

            choice = c[cl][choice_index]

            invalid = False
            for t_d in games_today:
                if choice[0] in t_d or choice[1] in t_d:
                    invalid = True
                    break
                else:
                    invalid = False

            if not invalid:
                games_today.append(choice)
                c[cl].pop(choice_index)
                game_not_found = False
            else:
                continue

        if error: break
    if error:
        list_ind_max = len(c[cl]) - 1
        single_ind = random.randint(0,list_ind_max)
        games_today = [c[cl][single_ind]]
        c[cl].pop(single_ind)

    return games_today,c

def finish_this_list(c, current_list):
    ret_list = []
    for x in c[current_list]:
        ret_list.append(x)

    c[current_list] = 0
    return c[current_list],c

p = ['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10', 'A11', 'A12', 'A13', 'A14', 'A15', 'A16', 'A17', 'A18', 'A19', 'A20', 'A21', 'A22', 'A23', 'A24', 'A25', 'A26', 'A27', 'A28', 'A29', 'A30', 'A31']

f = list(itertools.combinations(p, 2))
g = list(itertools.combinations(p, 2))
g = [x[::-1] for x in g]

c = [f, g]

schedule = {}
condition1 = True
day = 0

while condition1:
    day += 1

    current_list = get_current_list(c)
    last_round = check_list_status(c,current_list)

    if not last_round:
        todays_matchups,c = get_matchup(c, current_list)
        schedule[day] = todays_matchups
    else:
        schedule[day],c = finish_this_list(c, current_list)
        if current_list == 1:
            condition1 = False

print(schedule)

Однако, как вы можете видеть, этот подход немного запутан и по-прежнему не учитываетПравило не более двух игр подряд для каждой команды.Более того, я реализовал некоторые обходные пути, которые не очень питонны.Особенно счетчик в главной функции для предотвращения попадания в бесконечный цикл (если сценарий не может найти другой матч-ап, который не включает команду, которая уже играет в тот день) и как сценарий управляет, если естьвсего несколько записей, оставленных в списке (сейчас все воспринимается как один последний день, если в списке менее девяти записей, хотя в этот день может быть команда, играющая дважды), мне кажется, что они нуждаются в улучшении.

Буду признателен за любую помощь / подсказку, как действовать лучше.

...