体育联赛日程安排:不平衡的对决

时间:2019-04-23 09:51:55

标签: python-3.x random combinations schedule round-robin

我目前正在尝试为不同联赛创建时间表。我已经阅读了有关循环赛的问题,也能够为上半场和下半场制定一个赛季的时间表。但是,我想要实现的是:

  • 有16支或32支球队的联盟
  • 每个赛季60场比赛(在16支联赛中,每个对手踢4倍,在32支联赛中,每个对手踢2次)
  • 每天五到八场比赛
  • 每个团队每天没有多场比赛
  • 甚至分发家庭和外出游戏
  • 可以连续进行游戏,但连续两天不超过

到目前为止,我尝试了什么?第一步,我使用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中的列表c被代表n次(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)

但是,正如您所看到的,这种方法有点混乱,并且仍然没有考虑每支球队连续比赛不超过两场的规则。 此外,我实现了一些不太Python风格的解决方法。特别是main函数中的计数器,它可以防止陷入无限循环(如果脚本无法找到不包括当天已经参加比赛的团队的对决)以及脚本如何管理(如果存在)列表中只剩下几个条目(如果列表中的条目少于九个,则现在将所有内容作为最后一天,尽管当天可能会有一个团队玩两次),我觉得他们需要改进。 / p>

任何有关如何最好地进行工作的帮助/提示都将不胜感激。

0 个答案:

没有答案