给定一定的限制随机循环联赛时间表
Randomise round-robin league schedule given certain constraints
我正在尝试编写一个脚本来随机化锦标赛的循环赛程表。
约束是:
- 8 队
- 两队对阵,一次在主场,一次在客场
- 14周,每队每周一场比赛
我的代码在理论上工作正常,但当它生成时,它有时会在某些星期冻结,因为那一周只剩下两支球队,而且两种可能的比赛都已经进行了。我使用一个 numpy 数组来检查已经进行了哪些比赛。
目前我的代码如下所示:
import random
import numpy
regular_season_games = 14
regular_season_week = 0
checker = numpy.full((8,8), 0)
for x in range (0,8):
checker[x][x] = 1
teams_left = list(range(8))
print ("Week " + str(regular_season_week+1))
while (regular_season_week < regular_season_games):
game_set = False
get_away_team = False
while get_away_team == False:
Team_A = random.choice(teams_left)
if 0 in checker[:,Team_A]:
for x in range (0,8):
if checker[x][Team_A] == 0 and x in teams_left:
teams_left.remove(Team_A)
get_away_team = True
break
while game_set == False:
Team_B = random.choice(teams_left)
if checker[Team_B][Team_A] == 0:
teams_left.remove(Team_B)
print(str(Team_A) + " vs " + str(Team_B))
checker[Team_B][Team_A] = 1
game_set = True
if not teams_left:
print ("Week " + str(regular_season_week+2))
teams_left = list(range(8))
regular_season_week = regular_season_week + 1
我使用了 here 中调度算法的改编来实现这一点。基本上,我们会生成一个团队列表 - list(range(8))
- 并选择 0 vs 4, 1 vs 5, 2 vs 6, 3 vs 7
作为我们的初始对决。然后我们旋转列表,排除第一个元素,并选择作为我们的下一场比赛 0 vs 3, 7 vs 4, 1 vs 5, 2 vs 6
。我们继续以下列方式进行,直到我们完成所有配对。
我已经为主场和客场比赛添加了处理程序 - 如果已经进行了配对,我们将进行相反的 home/away 配对。下面是代码,包括一个检查游戏列表是否有效的函数,以及一个示例输出。
代码:
import random
# Generator function for list of matchups from a team_list
def games_from_list(team_list):
for i in range(4):
yield team_list[i], team_list[i+4]
# Function to apply rotation to list of teams as described in article
def rotate_list(team_list):
team_list = [team_list[4]] + team_list[0:3] + team_list[5:8] + [team_list[3]]
team_list[0], team_list[1] = team_list[1], team_list[0]
return team_list
# Function to check if a list of games is valid
def checkValid(game_list):
if len(set(game_list)) != len(game_list):
return False
for week in range(14):
teams = set()
this_week_games = game_list[week*4:week*4 + 4]
for game in this_week_games:
teams.add(game[0])
teams.add(game[1])
if len(teams) < 8:
return False
else:
return True
# Generate list of teams & empty list of games played
teams = list(range(8))
games_played = []
# Optionally shuffle teams before generating schedule
random.shuffle(teams)
# For each week -
for week in range(14):
print(f"Week {week + 1}")
# Get all the pairs of games from the list of teams.
for pair in games_from_list(teams):
# If the matchup has already been played:
if pair in games_played:
# Play the opposite match
pair = pair[::-1]
# Print the matchup and append to list of games.
print(f"{pair[0]} vs {pair[1]}")
games_played.append(pair)
# Rotate the list of teams
teams = rotate_list(teams)
# Checks that the list of games is valid
print(checkValid(games_played))
示例输出:
Week 1
0 vs 7
4 vs 3
6 vs 1
5 vs 2
Week 2
0 vs 3
7 vs 1
4 vs 2
6 vs 5
Week 3
0 vs 1
3 vs 2
7 vs 5
4 vs 6
Week 4
0 vs 2
1 vs 5
3 vs 6
7 vs 4
Week 5
0 vs 5
2 vs 6
1 vs 4
3 vs 7
Week 6
0 vs 6
5 vs 4
2 vs 7
1 vs 3
Week 7
0 vs 4
6 vs 7
5 vs 3
2 vs 1
Week 8
7 vs 0
3 vs 4
1 vs 6
2 vs 5
Week 9
3 vs 0
1 vs 7
2 vs 4
5 vs 6
Week 10
1 vs 0
2 vs 3
5 vs 7
6 vs 4
Week 11
2 vs 0
5 vs 1
6 vs 3
4 vs 7
Week 12
5 vs 0
6 vs 2
4 vs 1
7 vs 3
Week 13
6 vs 0
4 vs 5
7 vs 2
3 vs 1
Week 14
4 vs 0
7 vs 6
3 vs 5
1 vs 2
True
我正在尝试编写一个脚本来随机化锦标赛的循环赛程表。
约束是:
- 8 队
- 两队对阵,一次在主场,一次在客场
- 14周,每队每周一场比赛
我的代码在理论上工作正常,但当它生成时,它有时会在某些星期冻结,因为那一周只剩下两支球队,而且两种可能的比赛都已经进行了。我使用一个 numpy 数组来检查已经进行了哪些比赛。
目前我的代码如下所示:
import random
import numpy
regular_season_games = 14
regular_season_week = 0
checker = numpy.full((8,8), 0)
for x in range (0,8):
checker[x][x] = 1
teams_left = list(range(8))
print ("Week " + str(regular_season_week+1))
while (regular_season_week < regular_season_games):
game_set = False
get_away_team = False
while get_away_team == False:
Team_A = random.choice(teams_left)
if 0 in checker[:,Team_A]:
for x in range (0,8):
if checker[x][Team_A] == 0 and x in teams_left:
teams_left.remove(Team_A)
get_away_team = True
break
while game_set == False:
Team_B = random.choice(teams_left)
if checker[Team_B][Team_A] == 0:
teams_left.remove(Team_B)
print(str(Team_A) + " vs " + str(Team_B))
checker[Team_B][Team_A] = 1
game_set = True
if not teams_left:
print ("Week " + str(regular_season_week+2))
teams_left = list(range(8))
regular_season_week = regular_season_week + 1
我使用了 here 中调度算法的改编来实现这一点。基本上,我们会生成一个团队列表 - list(range(8))
- 并选择 0 vs 4, 1 vs 5, 2 vs 6, 3 vs 7
作为我们的初始对决。然后我们旋转列表,排除第一个元素,并选择作为我们的下一场比赛 0 vs 3, 7 vs 4, 1 vs 5, 2 vs 6
。我们继续以下列方式进行,直到我们完成所有配对。
我已经为主场和客场比赛添加了处理程序 - 如果已经进行了配对,我们将进行相反的 home/away 配对。下面是代码,包括一个检查游戏列表是否有效的函数,以及一个示例输出。
代码:
import random
# Generator function for list of matchups from a team_list
def games_from_list(team_list):
for i in range(4):
yield team_list[i], team_list[i+4]
# Function to apply rotation to list of teams as described in article
def rotate_list(team_list):
team_list = [team_list[4]] + team_list[0:3] + team_list[5:8] + [team_list[3]]
team_list[0], team_list[1] = team_list[1], team_list[0]
return team_list
# Function to check if a list of games is valid
def checkValid(game_list):
if len(set(game_list)) != len(game_list):
return False
for week in range(14):
teams = set()
this_week_games = game_list[week*4:week*4 + 4]
for game in this_week_games:
teams.add(game[0])
teams.add(game[1])
if len(teams) < 8:
return False
else:
return True
# Generate list of teams & empty list of games played
teams = list(range(8))
games_played = []
# Optionally shuffle teams before generating schedule
random.shuffle(teams)
# For each week -
for week in range(14):
print(f"Week {week + 1}")
# Get all the pairs of games from the list of teams.
for pair in games_from_list(teams):
# If the matchup has already been played:
if pair in games_played:
# Play the opposite match
pair = pair[::-1]
# Print the matchup and append to list of games.
print(f"{pair[0]} vs {pair[1]}")
games_played.append(pair)
# Rotate the list of teams
teams = rotate_list(teams)
# Checks that the list of games is valid
print(checkValid(games_played))
示例输出:
Week 1
0 vs 7
4 vs 3
6 vs 1
5 vs 2
Week 2
0 vs 3
7 vs 1
4 vs 2
6 vs 5
Week 3
0 vs 1
3 vs 2
7 vs 5
4 vs 6
Week 4
0 vs 2
1 vs 5
3 vs 6
7 vs 4
Week 5
0 vs 5
2 vs 6
1 vs 4
3 vs 7
Week 6
0 vs 6
5 vs 4
2 vs 7
1 vs 3
Week 7
0 vs 4
6 vs 7
5 vs 3
2 vs 1
Week 8
7 vs 0
3 vs 4
1 vs 6
2 vs 5
Week 9
3 vs 0
1 vs 7
2 vs 4
5 vs 6
Week 10
1 vs 0
2 vs 3
5 vs 7
6 vs 4
Week 11
2 vs 0
5 vs 1
6 vs 3
4 vs 7
Week 12
5 vs 0
6 vs 2
4 vs 1
7 vs 3
Week 13
6 vs 0
4 vs 5
7 vs 2
3 vs 1
Week 14
4 vs 0
7 vs 6
3 vs 5
1 vs 2
True