Round Robin Tournament Algorithm in C #

I am having trouble reaching this little round robin . I'm trying to create a game preview calendar

then I want to output:

Day 1: Team 1 vs. Team 2 Team 3 vs Team 4 Team 5vs Team 6;

day 2 Team 1 against team 4; Team 6 vs Team 3 Team 2 vs. Team 5;

until the end of the championship;

Here is the code that I have received so far, but I am having trouble getting the first command to commit while the rest of the array rotates ...:

static void Main(string[] args) { string[] ListTeam = new string[] {"Equipe1", "Equipe2", "Equipe3", "Equipe4", "Equipe5", "Equipe6"}; IList<Match> ListMatch = new List<Match>(); it NumberOfDays = (ListTeam.Count()-1); int y = 2; for (int i = 1; i <= NumberOfDays; i++) { Console.WriteLine("\nDay {0} : \n",i); Console.WriteLine(ListTeam[0].ToString() + " VS " + ListTeam[i].ToString()); for (y =ListTeam.Count(); y>0 ; y--) { Console.WriteLine(ListTeam[y].ToString() + " VS " + ListTeam[y+1].ToString()); y++; } } } 

EDIT: I found sample code in java, but I cannot translate it ...

+6
c # algorithm round-robin
source share
5 answers

This should be easy enough using modular arithmetic:

UPDATE 2: (as the correct algorithm promised)

 public void ListMatches(List<string> ListTeam) { if (ListTeam.Count % 2 != 0) { ListTeam.Add("Bye"); } int numDays = (numTeams - 1); int halfSize = numTeams / 2; List<string> teams = new List<string>(); teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize)); teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse()); int teamsSize = teams.Count; for (int day = 0; day < numDays; day++) { Console.WriteLine("Day {0}", (day + 1)); int teamIdx = day % teamsSize; Console.WriteLine("{0} vs {1}", teams[teamIdx], ListTeam[0]); for (int idx = 1; idx < halfSize; idx++) { int firstTeam = (day + idx) % teamsSize; int secondTeam = (day + teamsSize - idx) % teamsSize; Console.WriteLine("{0} vs {1}", teams[firstTeam], teams[secondTeam]); } } } 

which will print matches of each team.

Let me quickly try to explain how the algorithm works:

I noticed that since we rotate all the commands except the first, if we put all the commands in the array except the first, then we just need to read the first command from this array using the index based offset on a daily basis and do modular arithmetic to properly wrap . In practice, we will consider this array as endlessly repeating in both directions, and we will gradually bring our gaze to the right (or left).

However, there is one catch, and this is the fact that we need to arrange the teams in a very specific way so that it works correctly. Otherwise, we will not get the correct rotation. Because of this, we also need to read the corresponding second command in a very strange way.

The correct way to prepare your list is as follows:

  • Never put the first team (Team # 1) on the list.
  • Take the last half of the list of commands and put them at the top of the list.
  • Take the first half of the list, cancel it and put it on the list (but not in Team # 1).

Now the correct way to read the list is as follows:

  • For each day, increase the first index you look at 1 .
  • For the first team that you see in this place, map this team to Team # 1.
  • For the next team in the list ( (day + idx) % numDays ) we usually compare it with a team that is compensated by half the number of teams minus 1 (minus 1 because we were dealing with the first match). However, since the second half of our list was prepared by return, we must match this offset in the returned second half of the list. An easier way is to notice that this is equivalent to matching the same index, but from the end of the list. Given the current day offset, which is (day + (numDays - idx)) % numDays .

UPDATE 3: I was not happy that my decision included such a collapsed selection, matching, reversing array elements. After I thought about my decision, I realized that I was too hanged to maintain the order of the teams. However, this is not a mandatory requirement, and you can get another, but equally valid schedule, without worrying about the initial order. All that matters is the selection algorithm, which I describe in the second part of my explanation.

This way you can simplify the following lines:

 teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize)); teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse()); 

in

 teams.AddRange(ListTeam); // Copy all the elements. teams.RemoveAt(0); // To exclude the first team. 
+11
source share

It looks like you want to schedule a round tournament . The wp article contains an algorithm.

I do not see where you are even trying to rotate the array. The permutation will look something like this: 1 → 2 → 3 → 4 ... → n / 2 - 1 → n - 1 → n - 2 → n - 3 → ... → n / 2 → 1 (and 0 remains fixed) . You can do this in 2 cycles (top row and bottom row).

+6
source share

I made some improvements in the response block of code that computes the schedule double round-robin

 GameEntities db = new GameEntities(); private void btnTeamFixtures_Click(object sender, RoutedEventArgs e) { txtResults.Text = null; var allTeams = db.Team.Select(t => t.TeamName); int numDays = allTeams.Count() - 1; int halfsize = allTeams.Count() / 2; List<string> temp = new List<string>(); List<string> teams = new List<string>(); teams.AddRange(allTeams); temp.AddRange(allTeams); teams.RemoveAt(0); int teamSize = teams.Count; for (int day = 0; day < numDays * 2; day++) { //Calculate1stRound(day); if (day % 2 == 0) { txtResults.Text += String.Format("\n\nDay {0}\n", (day + 1)); int teamIdx = day % teamSize; txtResults.Text += String.Format("{0} vs {1}\n", teams[teamIdx], temp[0]); for (int idx = 0; idx < halfsize; idx++) { int firstTeam = (day + idx) % teamSize; int secondTeam = ((day + teamSize) - idx) % teamSize; if (firstTeam != secondTeam) { txtResults.Text += String.Format("{0} vs {1}\n", teams[firstTeam], teams[secondTeam]); } } } //Calculate2ndRound(day); if (day % 2 != 0) { int teamIdx = day % teamSize; txtResults.Text += String.Format("\n\nDay {0}\n", (day + 1)); txtResults.Text += String.Format("{0} vs {1}\n", temp[0], teams[teamIdx]); for (int idx = 0; idx < halfsize; idx++) { int firstTeam = (day + idx) % teamSize; int secondTeam = ((day + teamSize) - idx) % teamSize; if (firstTeam != secondTeam) { txtResults.Text += String.Format("{0} vs {1}\n", teams[secondTeam], teams[firstTeam]); } } } } } 

If u wants u to be able to create 2 methods and pass in an integer (day) as I did in 2 comments to separate the code.

If you have any questions or suggestions, feel free to respond.

+2
source share

This may be a confusing method, but it can be reduced to the problem of graph theory. Create a vertex of the graph for each team and create an edge between each vertex (so this is a complete graph). Then for the algorithm:

For every day I = 1 .. n:

  • Select any two unlabeled vertices that are directly connected, and mark the border between them with i. Mark both peaks.
  • Repeat until all vertices are marked.
  • Print tags with tags (i.e. team1 vs team2, team3 vs team4, etc.)
  • Remove the marked edges from the graph and reset all vertices to unmarked.
+1
source share

How about calculating the possible combinations for every day you want, and then

  • sort them in each pair, i.e. the team with the lowest number is always the first in any pair.
  • sort the listed pairs for each day, the first in each pair.
0
source share

All Articles