Я сейчас пытаюсь создать расписание для разных лиг.Я прочитал вопросы о круговом приеме, а также могу составить расписание на сезон с первой и второй половиной.Однако я пытаюсь добиться:
- Лиги с 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)
Однако, как вы можете видеть, этот подход немного запутан и по-прежнему не учитываетПравило не более двух игр подряд для каждой команды.Более того, я реализовал некоторые обходные пути, которые не очень питонны.Особенно счетчик в главной функции для предотвращения попадания в бесконечный цикл (если сценарий не может найти другой матч-ап, который не включает команду, которая уже играет в тот день) и как сценарий управляет, если естьвсего несколько записей, оставленных в списке (сейчас все воспринимается как один последний день, если в списке менее девяти записей, хотя в этот день может быть команда, играющая дважды), мне кажется, что они нуждаются в улучшении.
Буду признателен за любую помощь / подсказку, как действовать лучше.