Last active
September 1, 2023 16:22
-
-
Save MaxHalford/c24f50d4ed7bd7afcc87459f4fa76794 to your computer and use it in GitHub Desktop.
Sports schedule planning
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A friend of mine is a sports teacher teacher. He is organising a tournament, and gave me the following problem: | |
- 24 teams | |
- 12 sports | |
- Each sport takes place between 2 teams | |
- There are 12 time slots | |
- Each team needs to play each sports over the 12 time slots | |
- Ideally, each team should try to face every other team | |
This isn't possible, but there is a way to make each team play against 4 other teams over 3 sports. | |
It's easy to prove it isn't possible for every team to meet each other by looking at the case of 4 teams and 2 sports. If A and B play sport 1, and C opposes D on sport 2, then during the next session A will have to play B again on sport 2. The only way for all teams to meet each other is to have some sports repeat themselves. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import string | |
import numpy as np | |
import pandas as pd | |
teams = [c.upper() for c in string.ascii_lowercase[:24]] | |
activities = list(range(1, 13)) | |
groups = [teams[0:6], teams[6:12], teams[12:18], teams[18:24]] | |
matches = [] | |
for stage in range(4): | |
# Determine activities for each group during this stage | |
group_activities = np.roll([activities[0:3], activities[3:6], activities[6:9], activities[9:12]], stage, axis=0) | |
# Determine pairs within each group for this stage | |
if stage == 0: | |
group_pairs = [ | |
[(group[0], group[1]), | |
(group[2], group[3]), | |
(group[4], group[5])] | |
for group in groups | |
] | |
if stage == 1: | |
group_pairs = [ | |
[(group[0], group[2]), | |
(group[1], group[4]), | |
(group[2], group[5])] | |
for group in groups | |
] | |
if stage == 2: | |
group_pairs = [ | |
[(group[0], group[3]), | |
(group[1], group[5]), | |
(group[2], group[4])] | |
for group in groups | |
] | |
if stage == 3: | |
group_pairs = [ | |
[(group[0], group[4]), | |
(group[1], group[2]), | |
(group[3], group[5])] | |
for group in groups | |
] | |
# Determine matches for each hour of this stage | |
for hour in range(3): | |
for i, group in enumerate(group_pairs): | |
for j, pair in enumerate(group): | |
matches.append((stage, hour, pair[0], pair[1], group_activities[i][(hour + j) % 3])) | |
matches_df = pd.DataFrame(matches, columns=['stage', 'hour', 'team1', 'team2', 'activity']) | |
matches_df['step'] = matches_df['stage'] * 3 + matches_df['hour'] | |
activities = { | |
1: 'Biathlon', | |
2: 'Karting', | |
3: 'Mur interactif', | |
4: 'Ultimate', | |
5: 'Golf', | |
6: 'Handball', | |
7: 'Beach volley', | |
8: 'Escalade', | |
9: 'Badminton', | |
10: 'Molky', | |
11: 'Béret', | |
12: 'Course à l\'aveugle' | |
} | |
def to_num(team): | |
return ord(team) - ord('A') + 1 | |
# Mix it up | |
for i, step in enumerate([0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11]): | |
print((t := f'Session #{i + 1}')) | |
print('-' * len(t)) | |
for team1, team2, activity in matches_df.query('step == @step')[['team1', 'team2', 'activity']].values: | |
print(to_num(team1), 'vs', to_num(team2), '->', activities[activity]) | |
print('') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Session #1 | |
---------- | |
1 vs 2 -> Biathlon | |
3 vs 4 -> Karting | |
5 vs 6 -> Mur interactif | |
7 vs 8 -> Ultimate | |
9 vs 10 -> Golf | |
11 vs 12 -> Handball | |
13 vs 14 -> Beach volley | |
15 vs 16 -> Escalade | |
17 vs 18 -> Badminton | |
19 vs 20 -> Molky | |
21 vs 22 -> Béret | |
23 vs 24 -> Course à l'aveugle | |
Session #2 | |
---------- | |
1 vs 3 -> Molky | |
2 vs 5 -> Béret | |
3 vs 6 -> Course à l'aveugle | |
7 vs 9 -> Biathlon | |
8 vs 11 -> Karting | |
9 vs 12 -> Mur interactif | |
13 vs 15 -> Ultimate | |
14 vs 17 -> Golf | |
15 vs 18 -> Handball | |
19 vs 21 -> Beach volley | |
20 vs 23 -> Escalade | |
21 vs 24 -> Badminton | |
Session #3 | |
---------- | |
1 vs 4 -> Beach volley | |
2 vs 6 -> Escalade | |
3 vs 5 -> Badminton | |
7 vs 10 -> Molky | |
8 vs 12 -> Béret | |
9 vs 11 -> Course à l'aveugle | |
13 vs 16 -> Biathlon | |
14 vs 18 -> Karting | |
15 vs 17 -> Mur interactif | |
19 vs 22 -> Ultimate | |
20 vs 24 -> Golf | |
21 vs 23 -> Handball | |
Session #4 | |
---------- | |
1 vs 5 -> Ultimate | |
2 vs 3 -> Golf | |
4 vs 6 -> Handball | |
7 vs 11 -> Beach volley | |
8 vs 9 -> Escalade | |
10 vs 12 -> Badminton | |
13 vs 17 -> Molky | |
14 vs 15 -> Béret | |
16 vs 18 -> Course à l'aveugle | |
19 vs 23 -> Biathlon | |
20 vs 21 -> Karting | |
22 vs 24 -> Mur interactif | |
Session #5 | |
---------- | |
1 vs 2 -> Karting | |
3 vs 4 -> Mur interactif | |
5 vs 6 -> Biathlon | |
7 vs 8 -> Golf | |
9 vs 10 -> Handball | |
11 vs 12 -> Ultimate | |
13 vs 14 -> Escalade | |
15 vs 16 -> Badminton | |
17 vs 18 -> Beach volley | |
19 vs 20 -> Béret | |
21 vs 22 -> Course à l'aveugle | |
23 vs 24 -> Molky | |
Session #6 | |
---------- | |
1 vs 3 -> Béret | |
2 vs 5 -> Course à l'aveugle | |
3 vs 6 -> Molky | |
7 vs 9 -> Karting | |
8 vs 11 -> Mur interactif | |
9 vs 12 -> Biathlon | |
13 vs 15 -> Golf | |
14 vs 17 -> Handball | |
15 vs 18 -> Ultimate | |
19 vs 21 -> Escalade | |
20 vs 23 -> Badminton | |
21 vs 24 -> Beach volley | |
Session #7 | |
---------- | |
1 vs 4 -> Escalade | |
2 vs 6 -> Badminton | |
3 vs 5 -> Beach volley | |
7 vs 10 -> Béret | |
8 vs 12 -> Course à l'aveugle | |
9 vs 11 -> Molky | |
13 vs 16 -> Karting | |
14 vs 18 -> Mur interactif | |
15 vs 17 -> Biathlon | |
19 vs 22 -> Golf | |
20 vs 24 -> Handball | |
21 vs 23 -> Ultimate | |
Session #8 | |
---------- | |
1 vs 5 -> Golf | |
2 vs 3 -> Handball | |
4 vs 6 -> Ultimate | |
7 vs 11 -> Escalade | |
8 vs 9 -> Badminton | |
10 vs 12 -> Beach volley | |
13 vs 17 -> Béret | |
14 vs 15 -> Course à l'aveugle | |
16 vs 18 -> Molky | |
19 vs 23 -> Karting | |
20 vs 21 -> Mur interactif | |
22 vs 24 -> Biathlon | |
Session #9 | |
---------- | |
1 vs 2 -> Mur interactif | |
3 vs 4 -> Biathlon | |
5 vs 6 -> Karting | |
7 vs 8 -> Handball | |
9 vs 10 -> Ultimate | |
11 vs 12 -> Golf | |
13 vs 14 -> Badminton | |
15 vs 16 -> Beach volley | |
17 vs 18 -> Escalade | |
19 vs 20 -> Course à l'aveugle | |
21 vs 22 -> Molky | |
23 vs 24 -> Béret | |
Session #10 | |
----------- | |
1 vs 3 -> Course à l'aveugle | |
2 vs 5 -> Molky | |
3 vs 6 -> Béret | |
7 vs 9 -> Mur interactif | |
8 vs 11 -> Biathlon | |
9 vs 12 -> Karting | |
13 vs 15 -> Handball | |
14 vs 17 -> Ultimate | |
15 vs 18 -> Golf | |
19 vs 21 -> Badminton | |
20 vs 23 -> Beach volley | |
21 vs 24 -> Escalade | |
Session #11 | |
----------- | |
1 vs 4 -> Badminton | |
2 vs 6 -> Beach volley | |
3 vs 5 -> Escalade | |
7 vs 10 -> Course à l'aveugle | |
8 vs 12 -> Molky | |
9 vs 11 -> Béret | |
13 vs 16 -> Mur interactif | |
14 vs 18 -> Biathlon | |
15 vs 17 -> Karting | |
19 vs 22 -> Handball | |
20 vs 24 -> Ultimate | |
21 vs 23 -> Golf | |
Session #12 | |
----------- | |
1 vs 5 -> Handball | |
2 vs 3 -> Ultimate | |
4 vs 6 -> Golf | |
7 vs 11 -> Badminton | |
8 vs 9 -> Beach volley | |
10 vs 12 -> Escalade | |
13 vs 17 -> Course à l'aveugle | |
14 vs 15 -> Molky | |
16 vs 18 -> Béret | |
19 vs 23 -> Mur interactif | |
20 vs 21 -> Biathlon | |
22 vs 24 -> Karting |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment