使用 Python 3 生成比赛时间表

Mar*_*ind 1 python

我正在努力制定团队之间的比赛时间表。

条件是:

  • 14 支球队在 26 天内每天打 1 场比赛(每天 7 场比赛)。
  • 每支球队都要对战两次。1个主场和1个客场。
  • 每支球队每隔一天进行一场主场比赛和一场客场比赛。
  • 一支球队不能和自己比赛。所以每支球队都有13/14个对手。

我已经用第 1-26 天作为关键替换了我的日期,并且我的团队用 ID 来说明更简单。

结果示例:

[
    {1: [((7, 8), (6, 9), (5, 10), (4, 11), (3, 12), (2, 13), (1, 14)])]},
    {2: [((8, 1), (9, 7), (10, 6), (11, 5), (12, 4), (13, 3), (14, 2)])]},
    {3: [((9, 8), (8, 9), (7, 10), (6, 11), (5, 12), (4, 13), (3, 14)])]},
    ...
]
Run Code Online (Sandbox Code Playgroud)

我当前的代码如下所示:

from collections import deque, OrderedDict


teams_all = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
teams = teams_all[:int(len(teams_all)/2)]
matches = {}

for index, team in enumerate(teams):
    # Remove self to not match against self.
    opponents = list(teams_all)
    opponents.pop(index)

    # We reverse and rotate the opponents to give a 
    # different start opponent for each team.
    opponents = deque(opponents)
    opponents.reverse()
    opponents.rotate(-index)

    start_day = 1
    end_day = 26

    # We only loop 13 times instead of 26, because we schedule 
    # 2 matches at a time.
    for i in range(0, 13):
        opponent = opponents[i]

        # Init lists
        if matches.get(start_day, None) is None:
            matches[start_day] = []
        if matches.get(end_day, None) is None:
            matches[end_day] = []

        # We create both the home and away match at the same time
        # but with different dates, opposite side of the schedule.
        matches[start_day].insert(0, (team, opponent))
        matches[end_day].insert(0, (opponent, team))
        start_day += 2
        end_day -= 2

# Print to console to check result.
od = OrderedDict(sorted(matches.items()))
for key, match in od.items():
    print(key, match)
Run Code Online (Sandbox Code Playgroud)

上面的代码生成的第一行是正确的,但下一行总是有 1 个重复(1 个团队在 1 天内进行 2 场比赛),并且由于重复,一个团队完全丢失了。

我很确定我的问题在于我如何使用opponents.rotate(). 但是,我不确定我做错了什么。

Hug*_*ell 5

这是一个简化版本:

from pprint import pprint as pp

def make_day(num_teams, day):
    # using circle algorithm, https://en.wikipedia.org/wiki/Round-robin_tournament#Scheduling_algorithm
    assert not num_teams % 2, "Number of teams must be even!"
    # generate list of teams
    lst = list(range(1, num_teams + 1))
    # rotate
    day %= (num_teams - 1)  # clip to 0 .. num_teams - 2
    if day:                 # if day == 0, no rotation is needed (and using -0 as list index will cause problems)
        lst = lst[:1] + lst[-day:] + lst[1:-day]
    # pair off - zip the first half against the second half reversed
    half = num_teams // 2
    return list(zip(lst[:half], lst[half:][::-1]))

def make_schedule(num_teams):
    """
    Produce a double round-robin schedule
    """
    # number of teams must be even
    if num_teams % 2:
        num_teams += 1  # add a dummy team for padding

    # build first round-robin
    schedule = [make_day(num_teams, day) for day in range(num_teams - 1)]
    # generate second round-robin by swapping home,away teams
    swapped = [[(away, home) for home, away in day] for day in schedule]

    return schedule + swapped

def main():
    num_teams = int(input("How many teams? "))
    schedule = make_schedule(num_teams)
    pp(schedule)

if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

运行方式

How many teams? 14
[[(1, 14), (2, 13), (3, 12), (4, 11), (5, 10), (6, 9), (7, 8)],
 [(1, 13), (14, 12), (2, 11), (3, 10), (4, 9), (5, 8), (6, 7)],
 [(1, 12), (13, 11), (14, 10), (2, 9), (3, 8), (4, 7), (5, 6)],
 [(1, 11), (12, 10), (13, 9), (14, 8), (2, 7), (3, 6), (4, 5)],
 [(1, 10), (11, 9), (12, 8), (13, 7), (14, 6), (2, 5), (3, 4)],
 [(1, 9), (10, 8), (11, 7), (12, 6), (13, 5), (14, 4), (2, 3)],
 [(1, 8), (9, 7), (10, 6), (11, 5), (12, 4), (13, 3), (14, 2)],
 [(1, 7), (8, 6), (9, 5), (10, 4), (11, 3), (12, 2), (13, 14)],
 [(1, 6), (7, 5), (8, 4), (9, 3), (10, 2), (11, 14), (12, 13)],
 [(1, 5), (6, 4), (7, 3), (8, 2), (9, 14), (10, 13), (11, 12)],
 [(1, 4), (5, 3), (6, 2), (7, 14), (8, 13), (9, 12), (10, 11)],
 [(1, 3), (4, 2), (5, 14), (6, 13), (7, 12), (8, 11), (9, 10)],
 [(1, 2), (3, 14), (4, 13), (5, 12), (6, 11), (7, 10), (8, 9)],
 [(14, 1), (13, 2), (12, 3), (11, 4), (10, 5), (9, 6), (8, 7)],
 [(13, 1), (12, 14), (11, 2), (10, 3), (9, 4), (8, 5), (7, 6)],
 [(12, 1), (11, 13), (10, 14), (9, 2), (8, 3), (7, 4), (6, 5)],
 [(11, 1), (10, 12), (9, 13), (8, 14), (7, 2), (6, 3), (5, 4)],
 [(10, 1), (9, 11), (8, 12), (7, 13), (6, 14), (5, 2), (4, 3)],
 [(9, 1), (8, 10), (7, 11), (6, 12), (5, 13), (4, 14), (3, 2)],
 [(8, 1), (7, 9), (6, 10), (5, 11), (4, 12), (3, 13), (2, 14)],
 [(7, 1), (6, 8), (5, 9), (4, 10), (3, 11), (2, 12), (14, 13)],
 [(6, 1), (5, 7), (4, 8), (3, 9), (2, 10), (14, 11), (13, 12)],
 [(5, 1), (4, 6), (3, 7), (2, 8), (14, 9), (13, 10), (12, 11)],
 [(4, 1), (3, 5), (2, 6), (14, 7), (13, 8), (12, 9), (11, 10)],
 [(3, 1), (2, 4), (14, 5), (13, 6), (12, 7), (11, 8), (10, 9)],
 [(2, 1), (14, 3), (13, 4), (12, 5), (11, 6), (10, 7), (9, 8)]]
Run Code Online (Sandbox Code Playgroud)