创建循环赛,替代解决方案?

Creating a Round- Robin tournament, alternative solution?

teams = ["Atletico","Barcelona","Real Madrid", "Sevilla", "Atletic Bilbao ", "Granada", "Mallorca","Valencia"]

我们有一组团队想要创建一个锦标赛名称。可以是任何锦标赛,任何数量的球队(不是奇数)。

我想创建一个循环赛,基本上所有队伍都与其他队伍比赛。

我创建了一种解决方案:

weeks=[]
def schedule(teams):
    teams = list(teams)
    n = len(teams)
    for a in range(n - 1):
        b = zip(teams[:n // 2], reversed(teams[n // 2:]))
        weeks.append(list(b))
        teams.insert(1, teams.pop())
    print(weeks)
    return weeks

schedule(teams)

这个解决方案虽然不是最优的,因为我正在考虑周到的主场和客场状态。 1) 一组球队总是在家,另一组球队总是在外 2) 它不是随机的。

我想要一个解决方案,每周随机匹配这些对,但他们之前没有玩过。我怎样才能继续跟踪已经安排了哪些比赛?

我只是想向您指出解决方案,但我厌倦了在评论中解释,所以:

这是一个解决方案:

import random

teams = ["Atletico", "Barcelona", "Real Madrid", "Sevilla", "Atletic Bilbao ", "Granada", "Mallorca", "Valencia"]
pairs = [(i, j) for i in teams for j in teams if i != j]
random.shuffle(pairs)

numWeeks = len(teams) - 1
numPairs = len(teams)//2
matchUps = {}
for week in range(numWeeks):
    matchUps[f'Week {week}'] = []
    for _ in range(numPairs):
        for pair in pairs:
            if pair[0] not in [team for match in matchUps[f'Week {week}'] for team in match]:
                if pair[1] not in [team for match in matchUps[f'Week {week}'] for team in match]:
                    if pair not in [match for w in range(week) for match in matchUps[f'Week {w}']] and (pair[1], pair[0]) not in [match for w in range(week) for match in matchUps[f'Week {w}']]:
                        break
        matchUps[f'Week {week}'].append(pair)

print(matchUps)

输出:

{'Week 0': [('Granada', 'Sevilla'), 
            ('Mallorca', 'Barcelona'), 
            ('Real Madrid', 'Atletic Bilbao '), 
            ('Atletico', 'Valencia')], 
 'Week 1': [('Atletic Bilbao ', 'Sevilla'), 
            ('Granada', 'Atletico'), 
            ('Mallorca', 'Valencia'), 
            ('Real Madrid', 'Barcelona')], 
 'Week 2': [('Sevilla', 'Mallorca'), 
            ('Atletic Bilbao ', 'Barcelona'), 
            ('Valencia', 'Granada'), 
            ('Atletico', 'Real Madrid')], 
 'Week 3': [('Sevilla', 'Valencia'), 
            ('Atletico', 'Barcelona'), 
            ('Granada', 'Real Madrid'), 
            ('Mallorca', 'Atletic Bilbao ')], 
 'Week 4': [('Sevilla', 'Real Madrid'), 
            ('Atletico', 'Mallorca'), 
            ('Granada', 'Barcelona'), 
            ('Atletic Bilbao ', 'Valencia')], 
 'Week 5': [('Granada', 'Mallorca'), 
            ('Sevilla', 'Barcelona'), 
            ('Valencia', 'Real Madrid'), 
            ('Atletico', 'Atletic Bilbao ')], 
 'Week 6': [('Sevilla', 'Atletico'), 
            ('Barcelona', 'Valencia'), 
            ('Real Madrid', 'Mallorca'), 
            ('Atletic Bilbao ', 'Granada')]}

这会得到评论中显示的对:

teams = ["Atletico", "Barcelona", "Real Madrid", "Sevilla", "Atletic Bilbao ", "Granada", "Mallorca", "Valencia"]
pairs = [(i, j) for i in teams for j in teams if i != j]

然后随机化:

random.shuffle(pairs)

然后得到需要的周数和每周需要的对数:

numWeeks = len(teams) - 1
numPairs = len(teams)//2

然后它在周内循环(每次都创建一个新的周):

for week in range(numWeeks):
    matchUps[f'Week {week}'] = []

然后循环遍历每个需要的对:

for _ in range(numPairs):

对于每个对要求,它循环遍历 no-duplicate 列表以查找未使用的对:

        for pair in pairs:
            if pair[0] not in [team for match in matchUps[f'Week {week}'] for team in match]:
                if pair[1] not in [team for match in matchUps[f'Week {week}'] for team in match]:
                    if pair not in [match for w in range(week) for match in matchUps[f'Week {w}']] and (pair[1], pair[0]) not in [match for w in range(week) for match in matchUps[f'Week {w}']]:
                        break

一旦找到可以使用的一对,它就会把它放在一周中:

matchUps[f'Week {week}'].append(pair)

注意:这给出了随机 home/away 分配,但您可以更改:

numWeeks = len(teams) - 1

至:

numWeeks = (len(teams) - 1)*2

这将得到双倍 round-robin,其中每支球队主场各一次,每支球队客场一次。 (为此,您需要进行一些小的逻辑更改。)