I'm working on assigning groups in Python using rules.
You could think about it like building a season for a three player based game.
Each player needs to face the other players on the list exactly once.
So suppose I have this list:
players = ['a','b','c','d','e','f','g','h','i','j','k']
Here's the expected output if we start with 'a':
game schedule for a:
game 1 = a, b, c
game 2 = a, d, e
game 3 = a, f, g
game 4 = a, h, i
game 5 = a, j, k
I'll need a schedule like that above for each player.
What I've got right now gets me 45 combinations for player 'a'... trying to figure out how to whittle it down:
players = ['a','b','c','d','e','f','g','h','i','j','k']
from itertools import combinations
num = 3
all_games = list(combinations(players, num))
a_s = []
for i in all_games:
if 'a' in i:
a_s.append(i)
I'm just not sure how to build in the condition I want.
I suppose I could (in pseudo code):
create a list without the player I want:
player = ['a']
opponents = ['b','c','d','e','f','g','h','i','j','k']
extract/get every 2 elements from the list
add player a to the extracted opponent pairs
But I don't know if that's close to the best way to solve this.
Here is a way to solve this problem; using for loops.
players = ['a','b','c','d','e','f','g','h','i','j','k']
player_games = {}
for opponent in range(1, len(players), 2):
player_games[f"game {int((opponent + 1) / 2)}"] = ["a", players[opponent], players[opponent+1]] # Replace "a" with your criteria of finding the player
print(player_games)
Output:
{'game 1': ['a', 'b', 'c'], 'game 2': ['a', 'd', 'e'], 'game 3': ['a', 'f', 'g'], 'game 4': ['a', 'h', 'i'], 'game 5': ['a', 'j', 'k']}
This code works assuming you have an odd amount of players (even number after excluding the player.). If you just want something like [a,l]
in the end, here is a tweaked version of the code:
players = ['a','b','c','d','e','f','g','h','i','j','k',"l"]
player_games = {}
for opponent in range(1, len(players), 2):
try:
player_games[f"game {int((opponent + 1) / 2)}"] = ["a", players[opponent], players[opponent+1]]
except IndexError:
player_games[f"game {int((opponent + 1) / 2)}"] = ["a", players[opponent]]
print(player_games)
we just add a try..except block to catch an IndexError
which we get with the above code.
Output:
{'game 1': ['a', 'b', 'c'], 'game 2': ['a', 'd', 'e'], 'game 3': ['a', 'f', 'g'], 'game 4': ['a', 'h', 'i'], 'game 5': ['a', 'j', 'k'], 'game 6': ['a', 'l']}
Here is a short explanation for how this code works.
We use a range
to include every other letter's index (skip the first one since that is the player). We then include the current index and the index after the current one in a list. For example, ['b', 'c']
and then squash an a at the front: ['a', 'b', 'c']
The key increases by one for every iteration, but we are using range with 2 step, meaning we have to divide the opponent by two to get the game number. But, since we started at 1, we also have to add one.