Reputation: 317
I'm trying to write a script that generates every possible 1v1 match from N
players and then creates N-1
groups (days) of N/2
players, so that each day everyone plays and by the end of all N-1
days, each player will have played against all other players.
In my case:
N
= 12 playersN-1
= 11 daysN/2
= 6 matches per dayNumber of matches
= formulaI wrote the script below but it doesn't work very well. I generate each possible match using player_combinations()
. Then, I iterate N-1
times to create N-1
groups (days).
I make sure to only include a given player once in each day and, before moving on to the next day, I subtract day
from combinations
and clear day
, so that I won't use the same match twice.
The problem is that, after running the script, not every group has the same number of participants and the total number of matches doesn't add up to the correct one (it's lower).
What should I do? Is there an easy way (perhaps with partitions, permutations, etc.) of solving this problem that I'm not seeing?
SCRIPT:
from itertools import combinations
def player_combinations(players):
return [' - '.join(i) for i in combinations(players, 2)]
p = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L']
combinations = player_combinations(p)
day = []
for i in range(len(p)-1):
for pair in combinations:
if not any(pair.split(' - ')[0] in participants for participants in day) and not any(pair.split(' - ')[1] in participants for participants in day):
day.append(pair)
for participants in day:
print(participants)
print()
for participants in day:
if participants in combinations:
combinations.remove(participants)
day.clear()
Upvotes: 1
Views: 1253
Reputation: 342
I have used the reference below to make a round robin type script for your example. This will pair up each player in a special way to ensure the least amount of rounds with all or almost all (in the case of odd number of players) players in each round
reference here: https://nrich.maths.org/1443
import math
def shuffle(players): # rotate the values in players so the last player is first and everyone else is shifted one down
shuffled = list(players[-1])
shuffled.extend(players[:-1])
return shuffled
def pair_up_players(players, shuffled_players): # pair up the values in players, round robin style
pairs = []
idx_left_side_players = range(math.floor(len(shuffled_players)/2))
for idx in idx_left_side_players:
p1 = shuffled_players[idx]
p2 = shuffled_players[-idx-1-len(shuffled_players)%2]
pairs.append((p1, p2))
# if even number of players, pair up the last shuffled player with the last player in players
if len(players) % 2 == 0:
p1 = shuffled_players[-1]
p2 = players[-1]
pairs.append((p1, p2))
return pairs
players = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L']
num_players = len(players)
rounds_to_play = num_players - 1 + num_players%2
result = []
# we shuffle all or all but the last player depending if num_players is even or odd
if num_players % 2 == 0: # even, shuffle all players except for the last one, which is static
shuffled_players = players[:-1]
else:
shuffled_players = players # shuffle all players around
# loop the rounds
for round in range(rounds_to_play):
print(shuffled_players)
result.append(pair_up_players(players, shuffled_players))
shuffled_players = shuffle(shuffled_players)
print(result)
Upvotes: 2
Reputation: 9085
This is answered here: https://math.stackexchange.com/questions/1477767/efficiently-partition-a-set-into-all-possible-unique-pair-combinations
The idea is to make a complete graph on N vertices, putting all but one vertex on a regular polygon, with one in the center. We then do an edge coloring s.t. each vertex is incident with each edge color exactly once. The colors then represent rounds of the tournament, with each colored edge representing a pairing of its end-vertices in that round.
Let's call the edges that include the central vertex "central edges". We form the coloring by:
E.g., 12 vertices labeled 0-11, 11 rounds labeled 0-10, 'colors'.
Round Pairings:
Upvotes: 1