0

I am trying to code a match fixture app which takes a certain number of teams and puts them vs each other without repeating the same team twice successively i.e having the same team play twice in two days e.g if the teams listed are "a", "b", "c", "d" and "e" and they are to play four matches this code prints results like

a vs b

c vs d

c vs e

but I am trying to prevent it from repeating the same element twice in a row i.e

c vs d

c vs e

but rather

a vs b

c vs d

e vs a

the code is below, what changes do I need to make

import random

number_of_teams = int(input('How many teams? : '))
other_number = number_of_teams + 1
teams = []

number_of_matches = int(input("How many matches are to be played?: "))
real_number_of_matches = number_of_matches + 1

for i in range(1, other_number):
    team_name = input("Input team name: ")
    teams.append (team_name)
print('The teams participating are', teams)


for i in range(1, real_number_of_matches):
    first_team = random.choice(teams)
    second_team = random.choice(teams)
    if first_team != second_team:
        print(f'{first_team} vs {second_team}')```
M1sf1t
  • 13
  • 1
  • 1
    Keep the previously chosen team in a variable, and make sure it is not the same as one of the currently chosen ones – DeepSpace Jun 14 '22 at 20:08
  • I'm pretty sure there must be existing tables to set ideal pairs of teams in competitions that optimize the time difference between 2 plays. It's probably not random but carefully designed. – mozway Jun 14 '22 at 20:15
  • After a team is chosen, remove it from the list of available teams. – John Gordon Jun 14 '22 at 20:46

2 Answers2

1

I believe I found a way.

I created a dictionary called prev_teams which stores the previously used teams (we dont want to use them on the next turn). By default they are set to None as we dont have previous teams.

Then I create a copy of teams and store it into unique_teams. We use unique teams to create a list of teams we can select from. (Remove previous teams from this list using prev_teams i.e

unique_teams = [t for t in unique_teams if t not in prev_teams.values()]

Then, using a while loop we can check if the teams are the same, if not break out

while True:
    first_team = random.choice(unique_teams)
    second_team = random.choice(unique_teams)
    if first_team != second_team:
        break

Then we need to store the previous teams in prev_teams for later

prev_teams["first"] = first_team
prev_teams["second"] = second_team

So the final code would be

import random

while True:
    number_of_teams = int(input('How many teams? : '))
    if number_of_teams > 3:
        break
    else:
        print("Please enter a number greater than 3")
        
        
other_number = number_of_teams + 1
teams = []

number_of_matches = int(input("How many matches are to be played?: "))

for i in range(1, other_number):
    team_name = input("Input team name: ")
    teams.append (team_name)
print('The teams participating are', teams)


prev_teams = {"first": None, "second": None}
for i in range(number_of_matches):
    unique_teams = teams.copy()
    #if prev_teams values occur in unique_teams, remove them
    unique_teams = [t for t in unique_teams if t not in prev_teams.values()]
    while True:
        first_team = random.choice(unique_teams)
        second_team = random.choice(unique_teams)
        if first_team != second_team:
            break
    prev_teams["first"] = first_team
    prev_teams["second"] = second_team
    print(f'{first_team} vs {second_team}')

Output

How many teams? : 8
How many matches are to be played?: 10
Input team name: a
Input team name: b
Input team name: c
Input team name: d
Input team name: e
Input team name: f
Input team name: g
Input team name: h
The teams participating are ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
11
e vs c
h vs d
g vs b
c vs f
e vs d
h vs g
c vs e
f vs d
e vs a
h vs f
Buddy Bob
  • 5,829
  • 1
  • 13
  • 44
  • This works for me except you run into the same problem I did where if your matches and number of teams are incompatible (ie. 10 matches and 2 teams), you run into index errors (in my answer's case, an infinite loop). – crock Jun 14 '22 at 20:57
  • 1
    Well isnt 10 matches and 2 teams impossible. Do you want throw an error if this is the case? Also I just realized the same goes for 10 and 3. But this unavoidable. – Buddy Bob Jun 14 '22 at 20:59
  • Yep! I'm just suggesting input validation :) – crock Jun 14 '22 at 21:00
  • 1
    Alright sounds good! – Buddy Bob Jun 14 '22 at 21:01
  • After some more investigation, I realized that an error only occurs when the user inputs a number for teams less than or equal to 3. So a simple while loop will do. I updated the final code above. – Buddy Bob Jun 14 '22 at 21:07
  • Interesting, your comments actually made me realize I had a flawed answer. I thought duplicates were not allowed in the output, but after re-reading I realized only repeated elements twice are invalid. I updated mine to reflect the requirements, and it works with any combination of team/matches (as long as they are greater than 2 teams). – crock Jun 14 '22 at 21:24
  • 1
    Yeah! I only realized this half way through. Question was a bit tricky. – Buddy Bob Jun 14 '22 at 21:51
  • I forgot to note that duplicates are not allowed i.e if "a vs b" have played, there should be no "b vs a" – M1sf1t Jun 16 '22 at 23:59
0

This works with some fairly simple restructuring of your original code.

Firstly, there's no need to be using variables like: real_number_of_matches in your case, you can alter your loops to use the raw input values. I did so by using while loops instead of for loops because it seemed cleaner, but you can do it with for loops if you like.

I add the cached_first_team and cached_second_team variables to store the last used teams. Checking against these cached values allow us to never repeat two teams in a row, while allowing duplicate matchups and allowing the team to appear later in the matchups.

I also added the matches list which we can use to keep track of the number of matches we have so far, as a condition of our while loop.

import random

teams = []
matches = []

cached_first_team = ''
cached_second_team = ''

number_of_matches = int(input("How many matches are to be played?: "))
number_of_teams = int(input('How many teams? : '))

if number_of_teams > 1:
    while len(teams) < number_of_teams:
        team_name = input("Input team name: ")
        teams.append (team_name)
    print('The teams participating are', teams)

    while len(matches) < number_of_matches:
        first_team = random.choice(teams)
        second_team = random.choice(teams)
        matchup = set([first_team, second_team])
        if first_team != second_team and first_team not in (cached_first_team, cached_second_team) and second_team not in (cached_first_team, cached_second_team):
            print(f'{first_team} vs {second_team}')
            matches.append(matchup)
            cached_first_team = first_team
            cached_second_team = second_team
else:
    print('Not enough teams!')

Works with any number of matches (as long as the number of teams is greater than 1!)

crock
  • 423
  • 3
  • 11