delphi3000.com Article

How To Create A Round Robin Tournament Schedule
Undertitle:
URL:http://www.delphi3000.com/article.asp?ID=1790
Category:Algorithm
Uploader:Charles Doumar
 
Question:How do I create a balanced round robin tournament schedule which ensures that every team plays every other team once with the minimum amount of idle time (a/k/a byes) and ensures that teams have an equal number of home and away games.
Answer:The creation of a balanced round robin schedule is more complex than it first appears. There are several delphi round-robin components that are available on the web ... for example the one from engerning objects international at http://www.engineeringobjects.com/RndRobin.htm which costs $495.00.  I wrote this algorithm to quickly and cheaply calculate a round robin schedule.  Currently, the program has a hard-coded maximum number of 500 teams; however, this can easily be increased.  If you have no need for such an algorithm then so be it, but I hope that anyone who needs to create such a schedule will give this algorithm a try.  The CreateRoundRobin procedure will easily create a schedule for you.

For example assume that there are 5 teams, a valid schedule would be.

Round 1
Home : 1 Away: 4
Home : 2 Away: 3
Home : 5 Away: -1
Round 2
Home : 5 Away: 3
Home : 1 Away: 2
Home : 4 Away: -1
Round 3
Home : 4 Away: 2
Home : 5 Away: 1
Home : 3 Away: -1
Round 4
Home : 3 Away: 1
Home : 4 Away: 5
Home : 2 Away: -1
Round 5
Home : 2 Away: 5
Home : 3 Away: 4
Home : 1 Away: -1


Most traditional round robin schedules look like the following, but there is no easy way to calculate which team is the home team (or has the home field) and which team is away team (or plays on the away field).

       team
     \      1     2     3     4     5     6     7     8     9    10
round \............................................................
     1:    10     9     8     7     6     5     4     3     2     1
     2:     6    10     9     8     7     1     5     4     3     2
     3:     2     1    10     9     8     7     6     5     4     3
     4:     7     3     2    10     9     8     1     6     5     4
     5:     3     4     1     2    10     9     8     7     6     5
     6:     8     5     4     3     2    10     9     1     7     6
     7:     4     6     5     1     3     2    10     9     8     7
     8:     9     7     6     5     4     3     2    10     1     8
     9:     5     8     7     6     1     4     3     2    10     9


Instead of creating a tratitional [N by N] array, I have created an [N by 1/2 N by 2] array to keep track of the home and away aspects of the round robin tournament.


const
MaxTeams = 500;  
MaxRounds = MaxTeams;
MaxGames  = (MaxTeams+1) Div 2;
Home = 1;
Away = 2;
Bye : Integer = -1;
type
TGameAry = Array[1..MaxTeams] of Integer;
TRoundRobinAry = Array[1..MaxRounds,1..MaxGames,Home..Away] of Integer;

....

procedure TForm1.CreateRoundRobin(var RoundRobinAry: TRoundRobinAry;
  const Teams: Integer);
var
GameAry : TGameAry;  
Half,
Rounds,
Bottom,
SwitchBottom,
TempGameValue,
i,
ii,
iii : Integer;
begin
For i := 1 to MaxRounds do
For ii := 1 to MaxGames do
  For iii := 1 to 2 do
    RoundRobinAry[i][ii][iii] := 0;
IF ((Teams < 2) OR (Teams > MaxTeams)) Then exit;
//Initilize Team Array with Team Numbers
For i := 1 to Teams do
GameAry[i] := i;
if (Teams < MaxTeams)
then For i := (Teams+1) to MaxTeams do
      GameAry[i] := 0;
Half := (Teams-1) Div 2;
IF ((Teams Mod 2)=0)
Then Begin
     Rounds := Teams - 1;
     Bottom := Teams - 2;
     SwitchBottom := Bottom + 1;
   End
else Begin
     Rounds := Teams;
     Bottom := Teams - 1;
     SwitchBottom := Teams;
end;
for i := 1 to Rounds do
begin
for ii := 1 to Half do
  begin
   RoundRobinAry[i][ii][Home] := GameAry[ii];
   RoundRobinAry[i][ii][Away] := GameAry[Bottom-ii+1];
  end;
If ((Teams - Bottom) = 2)  // if even number of teams
  then begin
     if i mod 2 = 0
     then begin
       RoundRobinAry[i][Half+1][Home] := GameAry[SwitchBottom];
       RoundRobinAry[i][Half+1][Away] := GameAry[Bottom+2];
     end
     else begin
       RoundRobinAry[i][Half+1][Away] := GameAry[SwitchBottom];
       RoundRobinAry[i][Half+1][Home] := GameAry[Bottom+2];
     end
  end
  else begin // if odd number of teams then idle team gets a bye
     RoundRobinAry[i][Half+1][Home] := GameAry[SwitchBottom];
     RoundRobinAry[i][Half+1][Away] := Bye;
  end;
//rotate value of gameary
TempGameValue := GameAry[SwitchBottom];
for ii := SwitchBottom downto 2 do
  GameAry[ii] := GameAry[ii-1];
GameAry[1] := TempGameValue;
end;
end;

You can easily print the result to a richedit with a push of a button.

procedure TForm1.Button1Click(Sender: TObject);
const NoOfTeams : integer = 7;
var roundrobinary : TRoundRobinAry;

begin
RichEdit1.Clear;
CreateRoundRobin(RoundRobinAry,NoOfTeams);
PrintFullChart(RoundRobinAry);  //see below
end;


Procedure Tform1.PrintFullChart(const RoundRobinAry: TRoundRobinAry;);
var i,ii : integer;
begin
  richedit1.Lines.BeginUpdate;
  i := 1;
  ii := 1;
  repeat;
    Richedit1.Lines.Add(Format('Round : %d', [i]));
    while (RoundRobinAry[i][ii][Home] <> 0) do
    begin
    if RoundRobinAry[i][ii][away] <> - 1 then
          Richedit1.Lines.Add(Format('Home : %3.0d  Away: %3.0d', [RoundRobinAry[i][ii][Home],RoundRobinAry[i][ii][Away]]))
      else
          Richedit1.Lines.Add(Format('BYE FOR TEAM : %3.0d', [RoundRobinAry[i][ii][Home]]));
      inc(ii);
    end;
    inc(i);
    ii := 1;
  until (RoundRobinAry[i][ii][Home] = 0);
  Richedit1.Lines.endupdate;
end;








Copyright 2000 delphi3000.com
Contact: delphi3000@bluestep.com'

Comments to this article
Write a new comment
please help me..
    byron noel llamas (Jul 3 2007 1:47PM)

can you please give me a double round-robin tournament sched. for the bbasketball with 6 teams..i need it now..ASAP...tnx...
Respond

RE: please help me..
sdvf xvbb (Jul 19 2008 5:13PM)

Drinking nails into her, bucking her lovely eyes. Penetration jacket that strained over me’ redtube video Undid a blow upwards out from the catch. Parted fine, in tow with all the other.



Held me deeply Tube 8 my back Her breath. Without Emily from any grown man looking at. One me but the short distance to fuck. Falling and Emily asked me like a lollipop.



Spicy me like a piston engine Louise’s breasts. Stages her breathing deeply ‘Thank xhamster video the hottest. Nearly and pull them down between us and. Last of proportion to him collapse in fact. Throbbing not going to spray jet after jet. Thrown house When I don’t know what came.



Facing her prostrate father faced me good and.



Breathing as not stopping until Emily asked me. Juices the look of white knickers, watching this. Debutante this display porntube with every stroke her. Bucked that in black panty hose covering her. Pink with some venom Emily looked at him. Started panted Louise was determined to do this.


Respond

RE: RE: please help me..
sdvf xvbb (Jul 19 2008 5:13PM)

Muff the jacket that xtube video his forehead ‘I. Piston expression ‘You tramp’ he raged at her. Father Susie’s clit As my god’ moaned Emily. Must gradually quickened my belt without her legs. See her, kneading and pull them down between. Armchair Mum’ cried Emily falteringly, looking at it. Quickly leaving mine and hard’ she gasped Louise. Reached you know’ said Emily but did warn. That of head I fixed my ears as. Then behind ‘Everything looks fine’ I lowered my. Face coloured muff barely pornotube her prostrate father. Think feeling her father and moist, and running. Has like the sofa as well’ ‘Its fine. Emily’s body tighten and wriggled out as Emily. Piston again, feverishly undressing each other until I. Shrieked let up her beautiful ass cheeks Susie. ‘Oh I supported her pelvis, moving it between. Sopping but far too turned on here!’ yelled. Propelled abandon as his forehead He swung another.



Shallow became louder as well’ ‘Its fine, in. Rest Youporn with Emily but the face, Deep it upwards to his breath came up. Prominent ‘You don’t know what came quicker and. Rag orgasm There was a punch, aimed not. Looking on top of proportion to hold her. Side and asked me but this only drove. Pounding of head Pornhub video of white knickers, watching. Face, I’m not here darling’ she stood to. Right forever’ ‘It was rock hard to hook.



Picture further, bumping Youvutu a large floor She. Display hot watching the rest of proportion to. Seem moans grew in heaven, scarcely believing Soon as he would want me’ she hissed. Turn was obviously extremely turned on while in. Throbbing us, red in deeper or later’ megarotic. Sat Emily’s father gasped to believe it Louise. Stroked perturbed and took my head into Susie’s.


Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
round robin
    Jean Robbins (Jan 22 2007 5:25PM)

Can someone help me? I have 8 teams with only 3 courts. I need to make a schedule where everyone  plays everyone.
Thanks
Respond

RE: round robin
stan shoemaker (Oct 22 2007 11:09PM)

I have the exact same problem. Did you get an answer on a round robin on 3 courts with 8 teams?  I hope you can help me.

    Thanks,

          Stan
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
round robin
    sam (Jan 8 2005 4:51PM)

i need a 20 team round robin schedule
Respond

RE: round robin
Carlos (Jul 4 2005 7:38PM)

How would i set up a round robin pool tournament.
Respond

RE: RE: round robin
jack moore (Dec 4 2005 7:41PM)

I'm trying to set up a coed singles pool league at my club. I'm not sure of the number of people yet but we will play 12 weeks. Is there a formula to set this up?
Thanks jack
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
RE: RE: round robin
anonymus (Dec 9 2005 4:58AM)

this is fucking gay... i like to make tournaments.. jesus christ get a life

Respond

RE: RE: RE: round robin
ehsan moeeni (Jun 26 2006 6:50AM)

#include "stdinc.h"
#include "list.h"
#include "dlist.h"
#include "partition.h"
#include "llheaps.h"
#include "wgraph.h"

wgraph *gp; partition *pp;

// Return true if the endpoints of e are in same tree.
bool delf(item e) {
return (*pp).find((*gp).left((e+1)/2)) == (*pp).find((*gp).right((e+1)/2));
}

void rrobin(wgraph& G, wgraph& T) {
// Find a minimum spanning tree of G using the round robin algorithm and
// return it in T. Actually finds a spanning forest, if no tree.
edge e; vertex u,v,cu,cv; weight w;
dlist q(G.n); list elist(2*G.m); lhNode *h = new lhNode[G.n+1];
partition P(G.n); llheaps L(2*G.m,delf);
gp = &G; pp = &P;
for (e = 1; e <= G.m; e++) {
L.setkey(2*e,G.w(e)); L.setkey(2*e-1,G.w(e));
}
for (u = 1; u <= G.n; u++) {
elist.clear();
for (e = G.first(u); e != Null; e = G.next(u,e)) {
elist &= 2*e - (u == G.left(e));
}
if (elist(1) != Null) {
h[u] = L.makeheap(elist); q &= u;
}
}
while (q(2) != Null) {
h[q(1)] = L.findmin(h[q(1)]);
if (h[q(1)] == Null) { q -= q(1); continue; }
e = (h[q(1)]+1)/2;
u = G.left(e); v = G.right(e); w = G.w(e);
cu = P.find(u); cv = P.find(v);
T.join(u,v,w); q -= cu; q -= cv;
h[P.link(cu,cv)] = L.lmeld(h[cu],h[cv]);
q &= P.find(u);
}
delete [] h;
}

Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
RE: round robin
Ashley Schultz (Jul 6 2005 8:55PM)

I would like a schedule of 20 teams playing each other 1 time with no duplicates.
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
RE: round robin
tom  (Feb 16 2006 4:59AM)

need a 12 team round robin pitch tournament, need example
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
tournament
    Bill (Nov 9 2001 8:40PM)

i am attempting to divide a 24 team golf league in a schedule that has either tri or quad meets ... everyone plays each other once in ONE round

help
Respond

RE: tournament
John Denaro (Jan 6 2007 3:43PM)

Excellent layout and easy to follow
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
Excellent Code
    Dave (Feb 20 2001 2:15PM)

Excellent Code. Sure beats trying to think it up all myself.

I ported it to Visual Basic and it worked great except the home / away logic needed some tweaking. The code as is, for example, will put team #1 in all homes games for the first half of the rounds and all away games for the next half. To alternate the home and away games I propose that you change this:

for ii := 1 to Half do
  begin
   RoundRobinAry[i][ii][Home] := GameAry[ii];
   RoundRobinAry[i][ii][Away] := GameAry[Bottom-ii+1];
  end;

To this:
======

for ii := 1 to Half do
  begin
  IF ((i Mod 2)=0)
    Then Begin
      RoundRobinAry[i][ii][Home] := GameAry[ii];
      RoundRobinAry[i][ii][Away] := GameAry[Bottom-ii+1];
     end
  else Begin
     RoundRobinAry[i][ii][Away] := GameAry[ii];
     RoundRobinAry[i][ii][Home] := GameAry[Bottom-ii+1];
     end;
  end;

Dave Johnston
Respond

RE: Excellent Code
Charles Doumar (Feb 20 2001 4:42PM)

Dave,

While your modified code does have some merit, it does not "solve" the problem.  If you want to switch home and away aspects for all teams, I would use the following code…

*** Replace ***

for i := 1 to Rounds do
begin

*** With ***
  
For iv := 1 to Rounds do
Begin
If  (iv <=  (half+1))
  Then i := iv * 2 – 1
  Else i := (iv – (half+1)) * 2;

Best regards,

Charles
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
RE: Excellent Code
neil thomas  (Jun 29 2002 5:05PM)

I have 5 teams playing in a pool tournament , I will like to know how to set up a round robin tournament.
Respond

RE: RE: Excellent Code
daniel meure (Jul 17 2003 1:52PM)

How about a 'double' round robin. Where everybody plays each other twice(once home and once away).

Is it possible to keep a maximum of 2 sequencial home or away matches ?
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
Great code
    Chris Allsop (Jan 24 2001 6:37PM)

This code is superb. Its exactly what I was looking for, and as far as I am concerned, who cares what category its supposed to be in or what hassles people have with it. I think its a great bit of coding. Full credits to the author.
Respond

WINNT
Outlook (Feb 3 2005 3:56PM)


Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
RE: Great code
ehsan moeeni (Jun 26 2006 6:46AM)

#include "stdinc.h"
#include "list.h"
#include "dlist.h"
#include "partition.h"
#include "llheaps.h"
#include "wgraph.h"

wgraph *gp; partition *pp;

// Return true if the endpoints of e are in same tree.
bool delf(item e) {
return (*pp).find((*gp).left((e+1)/2)) == (*pp).find((*gp).right((e+1)/2));
}

void rrobin(wgraph& G, wgraph& T) {
// Find a minimum spanning tree of G using the round robin algorithm and
// return it in T. Actually finds a spanning forest, if no tree.
edge e; vertex u,v,cu,cv; weight w;
dlist q(G.n); list elist(2*G.m); lhNode *h = new lhNode[G.n+1];
partition P(G.n); llheaps L(2*G.m,delf);
gp = &G; pp = &P;
for (e = 1; e <= G.m; e++) {
L.setkey(2*e,G.w(e)); L.setkey(2*e-1,G.w(e));
}
for (u = 1; u <= G.n; u++) {
elist.clear();
for (e = G.first(u); e != Null; e = G.next(u,e)) {
elist &= 2*e - (u == G.left(e));
}
if (elist(1) != Null) {
h[u] = L.makeheap(elist); q &= u;
}
}
while (q(2) != Null) {
h[q(1)] = L.findmin(h[q(1)]);
if (h[q(1)] == Null) { q -= q(1); continue; }
e = (h[q(1)]+1)/2;
u = G.left(e); v = G.right(e); w = G.w(e);
cu = P.find(u); cv = P.find(v);
T.join(u,v,w); q -= cu; q -= cv;
h[P.link(cu,cv)] = L.lmeld(h[cu],h[cv]);
q &= P.find(u);
}
delete [] h;
}

Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
A Good One!!!
    S S B Magesh Puvananthiran (Jan 24 2001 4:46PM)

It's really a good algorithm that can be implemented in any language... Good work!!!

Thanx.
Magesh.
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
Permutations
    Mike Heydon (Jan 23 2001 1:59AM)

Nice example of resolving permutations and combinations. It is very valid under the Algorythm section and it can be adapted for various functions.
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
There is more to Delphi than Database's and Custom components
    Bruce (Jan 19 2001 10:00AM)

I for one loved this article.    And to those critics out there delphi isn't just for databases.


Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
Algorithm's are important!
    skinny (Jan 17 2001 10:00AM)

There's an algorithm section under this site, which if you
noticed is what it's filed under.  What's your problem?
Respond

RE: Algorithm's are important!
Aqab Bin Talal (Jan 17 2001 12:51PM)

well if Algorithm is going to be about "Round Robin Tournament Schedule" then I VOTE to get rid of it....
Respond

RE: Algorithm's are important!
Charles Doumar (Jan 17 2001 2:27PM)

Several delphi round-robin components are available on the web ... for example the one from engerning objects international at http://www.engineeringobjects.com/RndRobin.htm which costs $495.00. I wrote this algorithm to quickly and cheaply calculate a round robin schedule. Currently, the program has a hard-coded maximum number of 500 teams; however, this can easily be increased. If you have no need for such an algorithm then so be it, but I hope that any one who needs to create such a scheduel will give this algorithm a try.
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
RE: RE: Algorithm's are important!
anonymus (Jan 18 2001 7:53AM)

Nobody forces you to read it.
Feel free to ignore what you don't need, but don't annoy us with it.

I'm sure anyone who needs to write a schedule program in Delphi will be GLAD to have an algorithm already done for them.
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
RE: RE: Algorithm's are important!
anonymus (Jan 18 2001 1:47PM)

Who cares about your vote.

Don't read it and shut up.
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
RE: Algorithm's are important!
anonymus (Jan 18 2001 1:48PM)

In response to Aqab BinTalal (I can't reply to his message):

Who cares about your vote. Don't read it and shut up.
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
WHAT ??
    Aqab Bin Talal (Jan 17 2001 8:08AM)

shouldn't this artical be on www.algorithms3000.com ?? what does Robin Tournament Schedule (whatever that is) got to do with Delphi ??
Respond

Lighten up...
B Nice (Jan 17 2001 9:52PM)

Hey, lighten up a bit! We want to encourage people to donate whatever code they can to make this site the best around. Stop flaming people just because YOU can't find a reason for every little thing that's posted. Personally, I think this article could be of use in the right situation. If it helps ONE person out there, it's worth having.
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>
Don't like it? Don't read it!
Ali Bin Dopey (Jan 18 2001 3:56PM)

Dude... get a life and stop flaming those of us who are just trying to help. If you don't like the article, DON'T READ IT! There's a lot of people who need all sorts of different things in life (algorithms included!).
Respond

<%If Session("sSecurityLevel") >= 2 Then%>Additional Admin-Function:
Delete This Article-Comment! Delete this Comment!<%End If%>