Round-robin tournament schedule: Difference between revisions
(42 intermediate revisions by 21 users not shown) | |||
Line 1: | Line 1: | ||
{{ |
{{task}} |
||
A round-robin tournament is also known as an all-play-all-tournament; each participant plays every other participant once. |
A round-robin tournament is also known as an all-play-all-tournament; each participant plays every other participant once. |
||
Line 11: | Line 11: | ||
<br> |
<br> |
||
=={{header| |
=={{header|Ada}}== |
||
<syntaxhighlight lang="ada"> |
|||
<lang freebasic>function nob( n as uinteger, i as uinteger, bye as boolean ) as string |
|||
-- Create a round-robin schedule |
|||
-- J. Carter 2023 May |
|||
-- Circle method |
|||
with Ada.Text_IO; |
|||
procedure Round_Robin is |
|||
type Player_ID is range 1 .. 12; |
|||
type Player_List is array (Player_ID) of Player_ID; |
|||
Circle : Player_List; |
|||
J : Player_ID; |
|||
begin -- Round_Robin |
|||
Fill : for I in Circle'Range loop |
|||
Circle (I) := I; |
|||
end loop Fill; |
|||
All_Rounds : for Round in 1 .. Player_ID'Last - 1 loop |
|||
Ada.Text_IO.Put_Line (Item => "Round" & Round'Image); |
|||
J := Player_ID'Last; |
|||
Pairs : for I in 1 .. Player_ID'Last / 2 loop |
|||
Order : declare |
|||
Min : constant Player_ID := Player_ID'Min (Circle (I), Circle (J) ); |
|||
Max : constant Player_ID := Player_ID'Max (Circle (I), Circle (J) ); |
|||
begin -- Order |
|||
Ada.Text_IO.Put_Line (Item => Min'Image & " v" & Max'Image); |
|||
J := J - 1; |
|||
end Order; |
|||
end loop Pairs; |
|||
Ada.Text_IO.New_Line; |
|||
Circle := Circle (Circle'First) & Circle (Circle'Last) & Circle (Circle'First + 1 .. Circle'Last - 1); |
|||
end loop All_Rounds; |
|||
end Round_Robin; |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Round 1 |
|||
1 v 12 |
|||
2 v 11 |
|||
3 v 10 |
|||
4 v 9 |
|||
5 v 8 |
|||
6 v 7 |
|||
Round 2 |
|||
1 v 11 |
|||
10 v 12 |
|||
2 v 9 |
|||
3 v 8 |
|||
4 v 7 |
|||
5 v 6 |
|||
Round 3 |
|||
1 v 10 |
|||
9 v 11 |
|||
8 v 12 |
|||
2 v 7 |
|||
3 v 6 |
|||
4 v 5 |
|||
Round 4 |
|||
1 v 9 |
|||
8 v 10 |
|||
7 v 11 |
|||
6 v 12 |
|||
2 v 5 |
|||
3 v 4 |
|||
Round 5 |
|||
1 v 8 |
|||
7 v 9 |
|||
6 v 10 |
|||
5 v 11 |
|||
4 v 12 |
|||
2 v 3 |
|||
Round 6 |
|||
1 v 7 |
|||
6 v 8 |
|||
5 v 9 |
|||
4 v 10 |
|||
3 v 11 |
|||
2 v 12 |
|||
Round 7 |
|||
1 v 6 |
|||
5 v 7 |
|||
4 v 8 |
|||
3 v 9 |
|||
2 v 10 |
|||
11 v 12 |
|||
Round 8 |
|||
1 v 5 |
|||
4 v 6 |
|||
3 v 7 |
|||
2 v 8 |
|||
9 v 12 |
|||
10 v 11 |
|||
Round 9 |
|||
1 v 4 |
|||
3 v 5 |
|||
2 v 6 |
|||
7 v 12 |
|||
8 v 11 |
|||
9 v 10 |
|||
Round 10 |
|||
1 v 3 |
|||
2 v 4 |
|||
5 v 12 |
|||
6 v 11 |
|||
7 v 10 |
|||
8 v 9 |
|||
Round 11 |
|||
1 v 2 |
|||
3 v 12 |
|||
4 v 11 |
|||
5 v 10 |
|||
6 v 9 |
|||
7 v 8 |
|||
</pre> |
|||
=={{header|ALGOL 68}}== |
|||
{{Trans|XPL0}} |
|||
<syntaxhighlight lang="algol68"> |
|||
BEGIN # round-robin tournament schedule - translation of XPL0 # |
|||
INT n = 12; # number of players (must be even) # |
|||
[ 1 : n ]INT player; |
|||
FOR i TO n DO player[ i ] := i OD; |
|||
FOR round TO n - 1 DO |
|||
print( ( whole( round, 0 ), ":" ) ); |
|||
FOR i TO n OVER 2 DO |
|||
print( ( REPR 9, whole( player[ i ], 0 ) ) ) |
|||
OD; |
|||
print( ( newline ) ); |
|||
FOR i FROM n BY -1 TO ( n OVER 2 ) + 1 DO |
|||
print( ( REPR 9, whole( player[ i ], 0 ) ) ) |
|||
OD; |
|||
print( ( newline, newline ) ); |
|||
INT nth player = player[ n ]; |
|||
player[ 3 : n ] := player[ 2 : n - 1 ]; |
|||
player[ 2 ] := nth player |
|||
OD |
|||
END |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
Same as the XPL0 sample. |
|||
=={{header|APL}}== |
|||
<syntaxhighlight lang="APL"> |
|||
∇ SCHEDULER N;R;I |
|||
R←(⍳N),(2|N)⍴'-' |
|||
I←0 ⋄ N←⍴(R) |
|||
L:⎕←'ROUND',I←I+1 |
|||
⎕←((N÷2)↑R),[0.5]⌽(N÷2)↓R |
|||
R←(1↑R),1⌽1↓R |
|||
→(I<N-1)/L |
|||
∇ |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
SCHEDULER 4 |
|||
ROUND 1 |
|||
1 2 |
|||
4 3 |
|||
ROUND 2 |
|||
1 3 |
|||
2 4 |
|||
ROUND 3 |
|||
1 4 |
|||
3 2 |
|||
</pre> |
|||
=={{header|AWK}}== |
|||
<syntaxhighlight lang="awk"> |
|||
# syntax: GAWK -f ROUND-ROBIN_TOURNAMENT_SCHEDULE.AWK |
|||
BEGIN { |
|||
main(1) |
|||
main(2) |
|||
main(5,"The Bizzaros") |
|||
main(12) |
|||
exit(0) |
|||
} |
|||
function main(n,description, arr,i,j,leng,tmp) { |
|||
if (n < 2) { |
|||
printf("\n%d is too few participants\n",n) |
|||
return |
|||
} |
|||
printf("\n%d players %s\n",n,description) |
|||
for (i=1; i<=n; i++) { |
|||
arr[i] = i |
|||
} |
|||
if (n % 2 == 1) { |
|||
arr[++n] = 0 # a "bye" |
|||
} |
|||
leng = length(n-1) |
|||
for (i=1; i<n; i++) { |
|||
printf("\nround %*d:",leng,i) |
|||
for (j=1; j<=n/2; j++) { |
|||
printf("%4s",arr[j]==0?"bye":arr[j]) |
|||
} |
|||
printf("\n%*s",leng+7,"") |
|||
for (j=n; j>n/2; j--) { |
|||
printf("%4s",arr[j]==0?"bye":arr[j]) |
|||
} |
|||
printf("\n") |
|||
tmp = arr[n] |
|||
for (j=n; j>2; j--) { |
|||
arr[j] = arr[j-1] |
|||
} |
|||
arr[2] = tmp |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 is too few participants |
|||
2 players |
|||
round 1: 1 |
|||
2 |
|||
5 players The Bizzaros |
|||
round 1: 1 2 3 |
|||
bye 5 4 |
|||
round 2: 1 bye 2 |
|||
5 4 3 |
|||
round 3: 1 5 bye |
|||
4 3 2 |
|||
round 4: 1 4 5 |
|||
3 2 bye |
|||
round 5: 1 3 4 |
|||
2 bye 5 |
|||
12 players |
|||
round 1: 1 2 3 4 5 6 |
|||
12 11 10 9 8 7 |
|||
round 2: 1 12 2 3 4 5 |
|||
11 10 9 8 7 6 |
|||
round 3: 1 11 12 2 3 4 |
|||
10 9 8 7 6 5 |
|||
round 4: 1 10 11 12 2 3 |
|||
9 8 7 6 5 4 |
|||
round 5: 1 9 10 11 12 2 |
|||
8 7 6 5 4 3 |
|||
round 6: 1 8 9 10 11 12 |
|||
7 6 5 4 3 2 |
|||
round 7: 1 7 8 9 10 11 |
|||
6 5 4 3 2 12 |
|||
round 8: 1 6 7 8 9 10 |
|||
5 4 3 2 12 11 |
|||
round 9: 1 5 6 7 8 9 |
|||
4 3 2 12 11 10 |
|||
round 10: 1 4 5 6 7 8 |
|||
3 2 12 11 10 9 |
|||
round 11: 1 3 4 5 6 7 |
|||
2 12 11 10 9 8</pre> |
|||
=={{header|BASIC}}== |
|||
==={{header|BASIC256}}=== |
|||
{{trans|FreeBASIC}} |
|||
<syntaxhighlight lang="qbasic">arraybase 1 |
|||
print "Twelve teams" |
|||
call roundrob(12) |
|||
print "Nine teams with byes" |
|||
call roundrob(9) |
|||
end |
|||
function nob(n,i,byes) |
|||
#helper function to allow byess to be printed intelligently |
|||
if n > 9 then pad = " " else pad = "" |
|||
if n = i and byes then |
|||
return pad + "B" |
|||
else |
|||
if i < 10 then return pad + string(i) else return string(i) |
|||
end if |
|||
end function |
|||
subroutine roundrob(n) |
|||
byes = 0 |
|||
if n mod 2 = 1 then #if there is an odd number of competitors |
|||
byes = 1 #make note of this fact |
|||
n += 1 #and treat the tournament as having one more competitor |
|||
end if |
|||
dim schd(n) |
|||
for i = 1 to n |
|||
schd[i] = i #initial population of the array with numbers 1-n |
|||
next i |
|||
for r = 1 to n-1 |
|||
print "Round "; rjust(string(r), 2); ": "; |
|||
for i = 1 to n/2 #print the pairings according to the scheme |
|||
#1 2 3 4 |
|||
#5 6 7 8 |
|||
print "("; nob(n,schd[i],byes); " -"; nob(n,schd[i+n/2],byes); " ) "; |
|||
next i |
|||
print |
|||
#now move positions 2-n around clockwise |
|||
temp1 = schd[n/2] #need to track two temporary variables |
|||
temp2 = schd[n/2+1] |
|||
for i = n/2 to 3 step -1 #top row |
|||
schd[i] = schd[i-1] |
|||
next i |
|||
for i = n/2+1 to n-1 #bottom row |
|||
schd[i] = schd[i+1] |
|||
next i |
|||
schd[n] = temp1 #end ifll in the ones that "jumped" between rows |
|||
schd[2] = temp2 |
|||
next r |
|||
end subroutine</syntaxhighlight> |
|||
==={{header|FreeBASIC}}=== |
|||
<syntaxhighlight lang="freebasic">function nob( n as uinteger, i as uinteger, bye as boolean ) as string |
|||
'helper function to allow byes to be printed intelligently |
'helper function to allow byes to be printed intelligently |
||
dim as string pad |
dim as string pad |
||
Line 59: | Line 395: | ||
print "Nine teams with byes" |
print "Nine teams with byes" |
||
roundrob(9) |
roundrob(9) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}}<pre> |
{{out}}<pre> |
||
Twelve teams |
Twelve teams |
||
Line 84: | Line 420: | ||
Round 9: ( 1 - 2) ( 3 - 6) ( 4 - 7) ( 5 - 8) ( B - 9) |
Round 9: ( 1 - 2) ( 3 - 6) ( 4 - 7) ( 5 - 8) ( B - 9) |
||
</pre> |
</pre> |
||
==={{header|uBasic/4tH}}=== |
|||
{{trans|FreeBASIC}} |
|||
<syntaxhighlight lang="ubasic-4th">Print "Twelve teams" |
|||
Proc _Roundrob(12) |
|||
Print |
|||
Print "Nine teams with byes" |
|||
Proc _Roundrob(9) |
|||
End |
|||
_Roundrob |
|||
Param (1) |
|||
Local (5) |
|||
b@ = 0 |
|||
' if there is an odd number of competitors |
|||
If a@ % 2 = 1 Then b@ = 1 : a@ = a@ + 1 |
|||
' make note of this fact and treat the tournament |
|||
For d@ = 1 To a@ ' as having one more competitor |
|||
@(d@) = d@ ' initial population of the array with numbers 1-n |
|||
Next |
|||
For c@ = 1 To a@-1 ' print the pairings according to the scheme |
|||
Print Using "Round __: ";c@; |
|||
' 1 2 3 4 |
|||
For d@ = 1 To a@/2 ' 5 6 7 8 |
|||
Print Show(Iif (a@ = @(d@) * b@, " ( B - ", Str(" (_# - ", @(d@)))); |
|||
Print Show(Iif (a@ = @(d@+a@/2) * b@, " B) ", Str("_#) ", @(d@+a@/2)))); |
|||
Next |
|||
Print ' now move positions 2-n around clockwise |
|||
e@ = @(a@/2) ' need to track two temporary variables |
|||
f@ = @(a@/2+1) |
|||
' top row |
|||
For d@ = a@/2 To 3 Step -1 |
|||
@(d@) = @(d@-1) |
|||
Next |
|||
' bottom row |
|||
For d@ = a@/2+1 To a@-1 |
|||
@(d@) = @(d@+1) |
|||
Next |
|||
@(a@) = e@ ' fill in the ones that "jumped" between rows |
|||
@(2) = f@ |
|||
Next |
|||
Return</syntaxhighlight> |
|||
==={{header|Yabasic}}=== |
|||
{{trans|FreeBASIC}} |
|||
<syntaxhighlight lang="vb">print "Twelve teams" |
|||
roundrob(12) |
|||
print "Nine teams with byes" |
|||
roundrob(9) |
|||
end |
|||
sub nob$(n,i,byes) |
|||
//helper sub to allow byess to be printed intelligently |
|||
//dim as string pad |
|||
if n > 9 then pad$ = " " else pad$ = "" : fi |
|||
if n = i and byes then |
|||
return pad$+"B" |
|||
else |
|||
if i < 10 then return pad$+str$(i) else return str$(i) : fi |
|||
fi |
|||
end sub |
|||
sub roundrob(n) |
|||
byes = 0 |
|||
if mod(n, 2) = 1 then //if there is an odd number of competitors |
|||
byes = 1 //make note of this fact |
|||
n = n+1 //and treat the tournament as having one more competitor |
|||
fi |
|||
dim schd(n) |
|||
//, r, i, temp1, temp2 |
|||
for i = 1 to n |
|||
schd(i) = i //initial population of the array with numbers 1-n |
|||
next i |
|||
for r = 1 to n-1 |
|||
print "Round ", r using "##", ": "; |
|||
for i = 1 to n/2 //print the pairings according to the scheme |
|||
//1 2 3 4 |
|||
//5 6 7 8 |
|||
print "(", nob$(n,schd(i),byes), " -", nob$(n,schd(i+n/2),byes), " ) "; |
|||
next i |
|||
print |
|||
//now move positions 2-n around clockwise |
|||
temp1 = schd(n/2)//need to track two temporary variables |
|||
temp2 = schd(n/2+1) |
|||
for i = n/2 to 3 step -1 //top row |
|||
schd(i) = schd(i-1) |
|||
next i |
|||
for i = n/2+1 to n-1 //bottom row |
|||
schd(i) = schd(i+1) |
|||
next i |
|||
schd(n) = temp1 //fill in the ones that "jumped" between rows |
|||
schd(2) = temp2 |
|||
next r |
|||
end sub</syntaxhighlight> |
|||
=={{header|C++}}== |
|||
<syntaxhighlight lang="c++"> |
|||
#include <algorithm> |
|||
#include <cstdint> |
|||
#include <iomanip> |
|||
#include <iostream> |
|||
#include <numeric> |
|||
#include <stdexcept> |
|||
#include <vector> |
|||
void round_robin(uint32_t team_count) { |
|||
if ( team_count < 2 ) { |
|||
throw std::invalid_argument("Number of teams must be greater than 2: " + team_count); |
|||
} |
|||
std::vector<uint32_t> rotating_list(team_count); |
|||
std::iota(rotating_list.begin(), rotating_list.end(), 2); |
|||
if ( team_count % 2 == 1 ) { |
|||
rotating_list.emplace_back(0); |
|||
team_count++; |
|||
} |
|||
for ( uint32_t round = 1; round < team_count; ++round ) { |
|||
std::cout << "Round " << std::setw(2) << round << ":"; |
|||
std::vector<uint32_t> fixed_list(1, 1); |
|||
fixed_list.insert(fixed_list.end(), rotating_list.begin(), rotating_list.end()); |
|||
for ( uint32_t i = 0; i < team_count / 2; ++i ) { |
|||
std::cout << " ( " << std::setw(2) << fixed_list[i] |
|||
<< " vs " << std::setw(2) << fixed_list[team_count - 1 - i] << " )"; |
|||
} |
|||
std::cout << std::endl; |
|||
std::rotate(rotating_list.rbegin(), rotating_list.rbegin() + 1, rotating_list.rend()); |
|||
} |
|||
} |
|||
int main() { |
|||
std::cout << "Round robin for 12 players:" << std::endl; |
|||
round_robin(12); |
|||
std::cout << std::endl << std::endl; |
|||
std::cout << "Round robin for 5 players, 0 denotes a bye:" << std::endl; |
|||
round_robin(5); |
|||
} |
|||
</syntaxhighlight> |
|||
{{ out }} |
|||
<pre> |
|||
Round robin for 12 players: |
|||
Round 1: ( 1 vs 12 ) ( 2 vs 11 ) ( 3 vs 10 ) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) |
|||
Round 2: ( 1 vs 11 ) ( 13 vs 10 ) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) |
|||
Round 3: ( 1 vs 10 ) ( 12 vs 9 ) ( 13 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) |
|||
Round 4: ( 1 vs 9 ) ( 11 vs 8 ) ( 12 vs 7 ) ( 13 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 5: ( 1 vs 8 ) ( 10 vs 7 ) ( 11 vs 6 ) ( 12 vs 5 ) ( 13 vs 4 ) ( 2 vs 3 ) |
|||
Round 6: ( 1 vs 7 ) ( 9 vs 6 ) ( 10 vs 5 ) ( 11 vs 4 ) ( 12 vs 3 ) ( 13 vs 2 ) |
|||
Round 7: ( 1 vs 6 ) ( 8 vs 5 ) ( 9 vs 4 ) ( 10 vs 3 ) ( 11 vs 2 ) ( 12 vs 13 ) |
|||
Round 8: ( 1 vs 5 ) ( 7 vs 4 ) ( 8 vs 3 ) ( 9 vs 2 ) ( 10 vs 13 ) ( 11 vs 12 ) |
|||
Round 9: ( 1 vs 4 ) ( 6 vs 3 ) ( 7 vs 2 ) ( 8 vs 13 ) ( 9 vs 12 ) ( 10 vs 11 ) |
|||
Round 10: ( 1 vs 3 ) ( 5 vs 2 ) ( 6 vs 13 ) ( 7 vs 12 ) ( 8 vs 11 ) ( 9 vs 10 ) |
|||
Round 11: ( 1 vs 2 ) ( 4 vs 13 ) ( 5 vs 12 ) ( 6 vs 11 ) ( 7 vs 10 ) ( 8 vs 9 ) |
|||
Round robin for 5 players, 0 denotes a bye: |
|||
Round 1: ( 1 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) |
|||
Round 3: ( 1 vs 4 ) ( 6 vs 3 ) ( 0 vs 2 ) |
|||
Round 4: ( 1 vs 3 ) ( 5 vs 2 ) ( 6 vs 0 ) |
|||
Round 5: ( 1 vs 2 ) ( 4 vs 0 ) ( 5 vs 6 ) |
|||
</pre> |
|||
=={{header|C#}}== |
|||
{{trans|Java}} |
|||
<syntaxhighlight lang="C#"> |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
public class RoundRobinTournamentSchedule |
|||
{ |
|||
public static void Main(string[] args) |
|||
{ |
|||
Console.WriteLine("Round robin for 12 players:"); |
|||
RoundRobin(12); |
|||
Console.WriteLine("\n"); |
|||
Console.WriteLine("Round robin for 5 players, 0 denotes a bye:"); |
|||
RoundRobin(5); |
|||
} |
|||
private static void RoundRobin(int teamCount) |
|||
{ |
|||
if (teamCount < 2) |
|||
{ |
|||
throw new ArgumentException($"Number of teams must be greater than 2: {teamCount}"); |
|||
} |
|||
List<int> rotatingList = Enumerable.Range(2, teamCount - 1).ToList(); |
|||
if (teamCount % 2 == 1) |
|||
{ |
|||
rotatingList.Add(0); |
|||
teamCount += 1; |
|||
} |
|||
for (int round = 1; round < teamCount; round++) |
|||
{ |
|||
Console.Write($"Round {round,2}:"); |
|||
List<int> fixedList = new List<int> { 1 }; |
|||
fixedList.AddRange(rotatingList); |
|||
for (int i = 0; i < teamCount / 2; i++) |
|||
{ |
|||
Console.Write($" ( {fixedList[i],2} vs {fixedList[teamCount - 1 - i],2} )"); |
|||
} |
|||
Console.WriteLine(); |
|||
Rotate(rotatingList, 1); |
|||
} |
|||
} |
|||
private static void Rotate(List<int> list, int rotationCount) |
|||
{ |
|||
int count = list.Count; |
|||
if (count == 0) return; |
|||
rotationCount %= count; |
|||
if (rotationCount < 0) |
|||
{ |
|||
rotationCount += count; |
|||
} |
|||
list.Reverse(); |
|||
list.Reverse(0, rotationCount); |
|||
list.Reverse(rotationCount, count - rotationCount); |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Round robin for 12 players: |
|||
Round 1: ( 1 vs 12 ) ( 2 vs 11 ) ( 3 vs 10 ) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) |
|||
Round 2: ( 1 vs 11 ) ( 12 vs 10 ) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) |
|||
Round 3: ( 1 vs 10 ) ( 11 vs 9 ) ( 12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) |
|||
Round 4: ( 1 vs 9 ) ( 10 vs 8 ) ( 11 vs 7 ) ( 12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 5: ( 1 vs 8 ) ( 9 vs 7 ) ( 10 vs 6 ) ( 11 vs 5 ) ( 12 vs 4 ) ( 2 vs 3 ) |
|||
Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) ( 10 vs 4 ) ( 11 vs 3 ) ( 12 vs 2 ) |
|||
Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) ( 10 vs 2 ) ( 11 vs 12 ) |
|||
Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12 ) ( 10 vs 11 ) |
|||
Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12 ) ( 8 vs 11 ) ( 9 vs 10 ) |
|||
Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12 ) ( 6 vs 11 ) ( 7 vs 10 ) ( 8 vs 9 ) |
|||
Round 11: ( 1 vs 2 ) ( 3 vs 12 ) ( 4 vs 11 ) ( 5 vs 10 ) ( 6 vs 9 ) ( 7 vs 8 ) |
|||
Round robin for 5 players, 0 denotes a bye: |
|||
Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) |
|||
Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) |
|||
Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) |
|||
Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 ) |
|||
</pre> |
|||
=={{header|D}}== |
|||
<syntaxhighlight lang="go"> |
|||
import std.stdio; |
|||
import std.range; |
|||
import std.array; |
|||
import std.conv; |
|||
import std.algorithm; |
|||
void main() { |
|||
12.generatePlayers.generateSchedule.displaySchedule; |
|||
} |
|||
string[] generatePlayers(int n) { |
|||
("\nRound-Robin for "~(n).text~" players:\n").writeln; |
|||
// |
|||
return (n%2 == 0) ? iota(1, n+1).map!(a => a.text).array : iota(1, n+1).map!(a => a.text).array~"bye"; |
|||
} |
|||
string[] mutate(string[] arr) { |
|||
return arr[0]~arr[$-1]~ arr[1..$-1].array; |
|||
} |
|||
string[][] generateSchedule(string[] players) { |
|||
auto nbPlayer = players.length; |
|||
string[][]schedule; |
|||
schedule ~= players; |
|||
for(int i = 1; i <= nbPlayer-2; i++) |
|||
{ |
|||
schedule ~= schedule[$-1].mutate; |
|||
} |
|||
// |
|||
return schedule; |
|||
} |
|||
void displaySchedule(string[][] schedule) { |
|||
auto nbPlayer = schedule[0].length; |
|||
foreach(i, row; schedule.array) |
|||
{ |
|||
writef("Round %2s: ", i+1); |
|||
for(int k=0; k<nbPlayer/2; k++) |
|||
{ |
|||
writef("(%2s vs %2s)", row[k], row[nbPlayer-(k+1)]); |
|||
if (k==(nbPlayer/2)-1) writeln; else " ".write; |
|||
} |
|||
} |
|||
// |
|||
writeln; |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Round-Robin for 12 players: |
|||
Round 1: ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9) ( 5 vs 8) ( 6 vs 7) |
|||
Round 2: ( 1 vs 11) (12 vs 10) ( 2 vs 9) ( 3 vs 8) ( 4 vs 7) ( 5 vs 6) |
|||
Round 3: ( 1 vs 10) (11 vs 9) (12 vs 8) ( 2 vs 7) ( 3 vs 6) ( 4 vs 5) |
|||
Round 4: ( 1 vs 9) (10 vs 8) (11 vs 7) (12 vs 6) ( 2 vs 5) ( 3 vs 4) |
|||
Round 5: ( 1 vs 8) ( 9 vs 7) (10 vs 6) (11 vs 5) (12 vs 4) ( 2 vs 3) |
|||
Round 6: ( 1 vs 7) ( 8 vs 6) ( 9 vs 5) (10 vs 4) (11 vs 3) (12 vs 2) |
|||
Round 7: ( 1 vs 6) ( 7 vs 5) ( 8 vs 4) ( 9 vs 3) (10 vs 2) (11 vs 12) |
|||
Round 8: ( 1 vs 5) ( 6 vs 4) ( 7 vs 3) ( 8 vs 2) ( 9 vs 12) (10 vs 11) |
|||
Round 9: ( 1 vs 4) ( 5 vs 3) ( 6 vs 2) ( 7 vs 12) ( 8 vs 11) ( 9 vs 10) |
|||
Round 10: ( 1 vs 3) ( 4 vs 2) ( 5 vs 12) ( 6 vs 11) ( 7 vs 10) ( 8 vs 9) |
|||
Round 11: ( 1 vs 2) ( 3 vs 12) ( 4 vs 11) ( 5 vs 10) ( 6 vs 9) ( 7 vs 8) |
|||
</pre> |
|||
=={{header|EasyLang}}== |
|||
{{trans|AWK}} |
|||
<syntaxhighlight> |
|||
proc roundrobin n . . |
|||
numfmt 0 2 |
|||
print n & " players" |
|||
for i to n |
|||
arr[] &= i |
|||
. |
|||
if n mod 2 = 1 |
|||
n += 1 |
|||
arr[] &= 0 |
|||
. |
|||
for i = 1 to n - 1 |
|||
print "" |
|||
write "round " & i & ": " |
|||
for j = 1 to n / 2 |
|||
write arr[j] & " " |
|||
. |
|||
print "" |
|||
write " " |
|||
for j = n downto n / 2 + 1 |
|||
write arr[j] & " " |
|||
. |
|||
print "" |
|||
h = arr[n] |
|||
for j = n downto 3 |
|||
arr[j] = arr[j - 1] |
|||
. |
|||
arr[2] = h |
|||
. |
|||
. |
|||
roundrobin 12 |
|||
</syntaxhighlight> |
|||
=={{header|Go}}== |
|||
{{trans|Wren}} |
|||
<syntaxhighlight lang="go">package main |
|||
import "fmt" |
|||
func rotate(lst []int) { |
|||
len := len(lst) |
|||
last := lst[len-1] |
|||
for i := len - 1; i >= 1; i-- { |
|||
lst[i] = lst[i-1] |
|||
} |
|||
lst[0] = last |
|||
} |
|||
func roundRobin(n int) { |
|||
lst := make([]int, n-1) |
|||
for i := 0; i < len(lst); i++ { |
|||
lst[i] = i + 2 |
|||
} |
|||
if n%2 == 1 { |
|||
lst = append(lst, 0) // 0 denotes a bye |
|||
n++ |
|||
} |
|||
for r := 1; r < n; r++ { |
|||
fmt.Printf("Round %2d", r) |
|||
lst2 := append([]int{1}, lst...) |
|||
for i := 0; i < n/2; i++ { |
|||
fmt.Printf(" (%2d vs %-2d)", lst2[i], lst2[n-1-i]) |
|||
} |
|||
fmt.Println() |
|||
rotate(lst) |
|||
} |
|||
} |
|||
func main() { |
|||
fmt.Println("Round robin for 12 players:\n") |
|||
roundRobin(12) |
|||
fmt.Println("\n\nRound robin for 5 players (0 denotes a bye) :\n") |
|||
roundRobin(5) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Same as Wren example. |
|||
</pre> |
|||
=={{header|J}}== |
|||
Implementation (using the wikipedia [[wikipedia:Round-robin_tournament#Circle_method|circle method]]): |
|||
<syntaxhighlight lang=J>circ=: {{ |
|||
if. 1=2|y do. |
|||
assert. 1<y |
|||
<:(#~ [: */"1 *)"2 circ y+1 |
|||
else. |
|||
ids=. i.y |
|||
(-:y) ({.,.|.@}.)"_1] 0,.(}:ids)|."0 1}.ids |
|||
end. |
|||
}}</syntaxhighlight> |
|||
Task example: |
|||
<syntaxhighlight lang=J> rplc&'j:'"1":j./"1>:circ 12 |
|||
1:12 2:11 3:10 4:9 5:8 6:7 |
|||
1:2 3:12 4:11 5:10 6:9 7:8 |
|||
1:3 4:2 5:12 6:11 7:10 8:9 |
|||
1:4 5:3 6:2 7:12 8:11 9:10 |
|||
1:5 6:4 7:3 8:2 9:12 10:11 |
|||
1:6 7:5 8:4 9:3 10:2 11:12 |
|||
1:7 8:6 9:5 10:4 11:3 12:2 |
|||
1:8 9:7 10:6 11:5 12:4 2:3 |
|||
1:9 10:8 11:7 12:6 2:5 3:4 |
|||
1:10 11:9 12:8 2:7 3:6 4:5 |
|||
1:11 12:10 2:9 3:8 4:7 5:6</syntaxhighlight> |
|||
(Here, <code>circ</code> uses index values which start at zero, so we need to add 1 to every index. Then we form the id pairs as complex numbers and replace the 'j' used to separate real from imaginary in their character representation with ':' for a hopefully compact and easy-to-read display.) |
|||
((Note that we could have instead centered each id pair on the ':' with only slightly more work. But it's not clear that that results in a more pleasing display.)): |
|||
<syntaxhighlight lang=J> ,/"2(' ',_2&{.@[,':',2&{.@])&":/"1>:circ 12 |
|||
1:12 2:11 3:10 4:9 5:8 6:7 |
|||
1:2 3:12 4:11 5:10 6:9 7:8 |
|||
1:3 4:2 5:12 6:11 7:10 8:9 |
|||
1:4 5:3 6:2 7:12 8:11 9:10 |
|||
1:5 6:4 7:3 8:2 9:12 10:11 |
|||
1:6 7:5 8:4 9:3 10:2 11:12 |
|||
1:7 8:6 9:5 10:4 11:3 12:2 |
|||
1:8 9:7 10:6 11:5 12:4 2:3 |
|||
1:9 10:8 11:7 12:6 2:5 3:4 |
|||
1:10 11:9 12:8 2:7 3:6 4:5 |
|||
1:11 12:10 2:9 3:8 4:7 5:6 |
|||
</syntaxhighlight> |
|||
=={{header|Java}}== |
|||
<syntaxhighlight lang="java"> |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
import java.util.stream.IntStream; |
|||
public final class RoundRobinTournamentSchedule { |
|||
public static void main(String[] args) { |
|||
System.out.println("Round robin for 12 players:"); |
|||
roundRobin(12); |
|||
System.out.println(System.lineSeparator()); |
|||
System.out.println("Round robin for 5 players, 0 denotes a bye:"); |
|||
roundRobin(5); |
|||
} |
|||
private static void roundRobin(int teamCount) { |
|||
if ( teamCount < 2 ) { |
|||
throw new IllegalArgumentException("Number of teams must be greater than 2: " + teamCount); |
|||
} |
|||
List<Integer> rotatingList = IntStream.rangeClosed(2, teamCount).boxed().collect(Collectors.toList()); |
|||
if ( teamCount % 2 == 1 ) { |
|||
rotatingList.add(0); |
|||
teamCount += 1; |
|||
} |
|||
for ( int round = 1; round < teamCount; round++ ) { |
|||
System.out.print(String.format("%s%2d%s", "Round ", round, ":")); |
|||
List<Integer> fixedList = IntStream.rangeClosed(1, 1).boxed().collect(Collectors.toList()); |
|||
fixedList.addAll(rotatingList); |
|||
for ( int i = 0; i < teamCount / 2; i++ ) { |
|||
System.out.print(String.format("%s%2d%s%2d%s", |
|||
" ( ", fixedList.get(i), " vs ", fixedList.get(teamCount - 1 - i), " )")); |
|||
} |
|||
System.out.println(); |
|||
Collections.rotate(rotatingList, +1); |
|||
} |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{ out }} |
|||
<pre> |
|||
Round robin for 12 players: |
|||
Round 1: ( 1 vs 12 ) ( 2 vs 11 ) ( 3 vs 10 ) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) |
|||
Round 2: ( 1 vs 11 ) ( 12 vs 10 ) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) |
|||
Round 3: ( 1 vs 10 ) ( 11 vs 9 ) ( 12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) |
|||
Round 4: ( 1 vs 9 ) ( 10 vs 8 ) ( 11 vs 7 ) ( 12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 5: ( 1 vs 8 ) ( 9 vs 7 ) ( 10 vs 6 ) ( 11 vs 5 ) ( 12 vs 4 ) ( 2 vs 3 ) |
|||
Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) ( 10 vs 4 ) ( 11 vs 3 ) ( 12 vs 2 ) |
|||
Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) ( 10 vs 2 ) ( 11 vs 12 ) |
|||
Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12 ) ( 10 vs 11 ) |
|||
Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12 ) ( 8 vs 11 ) ( 9 vs 10 ) |
|||
Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12 ) ( 6 vs 11 ) ( 7 vs 10 ) ( 8 vs 9 ) |
|||
Round 11: ( 1 vs 2 ) ( 3 vs 12 ) ( 4 vs 11 ) ( 5 vs 10 ) ( 6 vs 9 ) ( 7 vs 8 ) |
|||
Round robin for 5 players, 0 denotes a bye: |
|||
Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) |
|||
Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) |
|||
Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) |
|||
Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 ) |
|||
</pre> |
|||
=={{header|jq}}== |
|||
{{Works with|jq}} |
|||
'''Works with gojq, the Go implementation of jq''' |
|||
'''Adapted from [[#Wren|Wren]]''' |
|||
<syntaxhighlight lang="jq"> |
|||
def lpad($len): tostring | ($len - length) as $l | (" " * $l) + .; |
|||
def rotate: .[-1:] + .[:-1]; |
|||
def roundRobin($n): |
|||
{$n, lst: [range(2; $n+1)]} |
|||
| if $n % 2 == 1 |
|||
then .lst += [0] # 0 denotes a bye |
|||
| .n += 1 |
|||
end |
|||
| foreach range(1; .n) as $r (.; |
|||
.emit = "Round \($r|lpad(3)): " |
|||
| ([1] + .lst) as $lst2 |
|||
| reduce range(0; .n/2) as $i (.; |
|||
.emit += " (\($lst2[$i]|lpad(2)) vs \($lst2[.n - 1 - $i]|lpad(2)))") |
|||
| .lst |= rotate ) |
|||
| .emit ; |
|||
"Round robin for 12 players:", |
|||
roundRobin(12), |
|||
"\n\nRound robin for 5 players (0 denotes a bye):\n", |
|||
roundRobin(5) |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
Essentially the same as for [[#Wren|Wren]]. |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia">""" https://rosettacode.org/mw/index.php?title=Round-robin_tournament_schedule """ |
||
function schurig(N, verbose = true) |
function schurig(N, verbose = true) |
||
Line 117: | Line 1,009: | ||
print("\n\nSchurig table for round robin with 7 players:") |
print("\n\nSchurig table for round robin with 7 players:") |
||
schurig(7) |
schurig(7) |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
Schurig table for round robin with 12 players: |
Schurig table for round robin with 12 players: |
||
Line 140: | Line 1,032: | ||
Round 6: (Bye - 7) (1 - 6) (2 - 5) (3 - 4) |
Round 6: (Bye - 7) (1 - 6) (2 - 5) (3 - 4) |
||
Round 7: (Bye - 4) (3 - 5) (2 - 6) (1 - 7) |
Round 7: (Bye - 4) (3 - 5) (2 - 6) (1 - 7) |
||
</pre> |
|||
=={{header|Nim}}== |
|||
<syntaxhighlight lang="Nim">import std/[algorithm, sequtils, strformat] |
|||
proc roundRobin(n: Positive) = |
|||
assert n >= 2 |
|||
var n = n |
|||
var list1 = toSeq(2..n) |
|||
if n mod 2 == 1: |
|||
list1.add 0 # 0 denotes a "bye". |
|||
inc n |
|||
for r in 1..<n: |
|||
stdout.write &"Round {r:2}:" |
|||
let list2 = 1 & list1 |
|||
for i in 0..<(n div 2): |
|||
stdout.write &" ({list2[i]:>2} vs {list2[n - i - 1]:<2})" |
|||
echo() |
|||
list1.rotateLeft(-1) |
|||
echo "Round robin for 12 players:\n" |
|||
roundRobin(12) |
|||
echo "\n\nRound robin for 5 players (0 denotes a bye) :\n" |
|||
roundRobin(5) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Round robin for 12 players: |
|||
Round 1: ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) |
|||
Round 2: ( 1 vs 11) (12 vs 10) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) |
|||
Round 3: ( 1 vs 10) (11 vs 9 ) (12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) |
|||
Round 4: ( 1 vs 9 ) (10 vs 8 ) (11 vs 7 ) (12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 5: ( 1 vs 8 ) ( 9 vs 7 ) (10 vs 6 ) (11 vs 5 ) (12 vs 4 ) ( 2 vs 3 ) |
|||
Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) (10 vs 4 ) (11 vs 3 ) (12 vs 2 ) |
|||
Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) (10 vs 2 ) (11 vs 12) |
|||
Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12) (10 vs 11) |
|||
Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12) ( 8 vs 11) ( 9 vs 10) |
|||
Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12) ( 6 vs 11) ( 7 vs 10) ( 8 vs 9 ) |
|||
Round 11: ( 1 vs 2 ) ( 3 vs 12) ( 4 vs 11) ( 5 vs 10) ( 6 vs 9 ) ( 7 vs 8 ) |
|||
Round robin for 5 players (0 denotes a bye) : |
|||
Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) |
|||
Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) |
|||
Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) |
|||
Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 ) |
|||
</pre> |
|||
=={{header|Pascal}}== |
|||
A console program in Free Pascal. Uses the circle method, but not exactly as in Wikipedia: the fixed player is the dummy, if present, otherwise the last; and the rotation is anticlockwise. |
|||
<syntaxhighlight lang="pascal"> |
|||
program RoundRobin; |
|||
(* |
|||
Rosetta Code: write list of matches in a round robin tournament. |
|||
Command line: |
|||
RoundRobin number_of_players |
|||
*) |
|||
{$mode objfpc}{$H+} |
|||
uses SysUtils; |
|||
var |
|||
nrPlayers, round : integer; |
|||
n, m, c, j, k : integer; |
|||
a : array of integer; |
|||
// Write the matches in a round, formatting nicely |
|||
procedure WriteRound(); |
|||
var |
|||
t, u : integer; |
|||
begin |
|||
Write( 'Round', round:3, ': '); |
|||
u := 0; |
|||
for t := 0 to m - 2 do begin |
|||
Write( '(', a[u]:2); inc(u); |
|||
Write( ' v', a[u]:3, ') '); inc(u); |
|||
end; |
|||
Write( '(', a[u]:2); // u = n - 2 |
|||
if c > 0 then |
|||
WriteLn( ' v', c:3, ')') |
|||
else |
|||
WriteLn( ' bye)'); |
|||
end; |
|||
begin |
|||
if ParamCount < 1 then begin |
|||
WriteLn( 'Number of players is required'); |
|||
exit; |
|||
end; |
|||
nrPlayers := SysUtils.StrToIntDef( ParamStr(1), -1); |
|||
// if string can't be converted, nrPlayers := -1 |
|||
if (nrPlayers < 2) then begin |
|||
WriteLn( 'Invalid number of players'); |
|||
exit; |
|||
end; |
|||
WriteLn( 'Round robin with ', nrPlayers, ' players'); |
|||
m := (nrPlayers + 1) div 2; |
|||
n := 2*m; |
|||
if Odd( nrPlayers) then c := 0 // dummy player, opponent gets a bye |
|||
else c := n; // genuine player |
|||
SetLength( a, n); |
|||
k := 0; |
|||
for j := 0 to m - 2 do begin |
|||
a[k] := m - j; inc(k); |
|||
a[k] := m + 1 + j; inc(k); |
|||
end; |
|||
a[k] := 1; |
|||
a[n - 1] := c; // a[n - 1] stays = c throughout |
|||
round := 1; |
|||
WriteRound(); |
|||
for round := 2 to n - 1 do begin |
|||
for j := 0 to n - 2 do begin // increment all entries except a[n - 1] |
|||
inc(a[j]); |
|||
if a[j] = n then a[j] := 1; // wrap round if necessary |
|||
end; |
|||
WriteRound(); |
|||
end; |
|||
end. |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Round robin with 12 players |
|||
Round 1: ( 6 v 7) ( 5 v 8) ( 4 v 9) ( 3 v 10) ( 2 v 11) ( 1 v 12) |
|||
Round 2: ( 7 v 8) ( 6 v 9) ( 5 v 10) ( 4 v 11) ( 3 v 1) ( 2 v 12) |
|||
Round 3: ( 8 v 9) ( 7 v 10) ( 6 v 11) ( 5 v 1) ( 4 v 2) ( 3 v 12) |
|||
Round 4: ( 9 v 10) ( 8 v 11) ( 7 v 1) ( 6 v 2) ( 5 v 3) ( 4 v 12) |
|||
Round 5: (10 v 11) ( 9 v 1) ( 8 v 2) ( 7 v 3) ( 6 v 4) ( 5 v 12) |
|||
Round 6: (11 v 1) (10 v 2) ( 9 v 3) ( 8 v 4) ( 7 v 5) ( 6 v 12) |
|||
Round 7: ( 1 v 2) (11 v 3) (10 v 4) ( 9 v 5) ( 8 v 6) ( 7 v 12) |
|||
Round 8: ( 2 v 3) ( 1 v 4) (11 v 5) (10 v 6) ( 9 v 7) ( 8 v 12) |
|||
Round 9: ( 3 v 4) ( 2 v 5) ( 1 v 6) (11 v 7) (10 v 8) ( 9 v 12) |
|||
Round 10: ( 4 v 5) ( 3 v 6) ( 2 v 7) ( 1 v 8) (11 v 9) (10 v 12) |
|||
Round 11: ( 5 v 6) ( 4 v 7) ( 3 v 8) ( 2 v 9) ( 1 v 10) (11 v 12) |
|||
Round robin with 9 players |
|||
Round 1: ( 5 v 6) ( 4 v 7) ( 3 v 8) ( 2 v 9) ( 1 bye) |
|||
Round 2: ( 6 v 7) ( 5 v 8) ( 4 v 9) ( 3 v 1) ( 2 bye) |
|||
Round 3: ( 7 v 8) ( 6 v 9) ( 5 v 1) ( 4 v 2) ( 3 bye) |
|||
Round 4: ( 8 v 9) ( 7 v 1) ( 6 v 2) ( 5 v 3) ( 4 bye) |
|||
Round 5: ( 9 v 1) ( 8 v 2) ( 7 v 3) ( 6 v 4) ( 5 bye) |
|||
Round 6: ( 1 v 2) ( 9 v 3) ( 8 v 4) ( 7 v 5) ( 6 bye) |
|||
Round 7: ( 2 v 3) ( 1 v 4) ( 9 v 5) ( 8 v 6) ( 7 bye) |
|||
Round 8: ( 3 v 4) ( 2 v 5) ( 1 v 6) ( 9 v 7) ( 8 bye) |
|||
Round 9: ( 4 v 5) ( 3 v 6) ( 2 v 7) ( 1 v 8) ( 9 bye) |
|||
</pre> |
</pre> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
===Even=== |
|||
<lang perl>#!/usr/bin/perl |
|||
<syntaxhighlight lang="perl">#!/usr/bin/perl |
|||
use strict; # https://rosettacode.org/wiki/Round-robin_tournament_schedule |
use strict; # https://rosettacode.org/wiki/Round-robin_tournament_schedule |
||
Line 154: | Line 1,194: | ||
@teams[0,$n-1,1..$n-2] = @teams; |
@teams[0,$n-1,1..$n-2] = @teams; |
||
printf 'Round %2d:' . '%4d vs %2d'x($n/2) . "\n", $_, @teams[ map { $_, $n-1-$_} 0..($n/2)-1 ]; |
printf 'Round %2d:' . '%4d vs %2d'x($n/2) . "\n", $_, @teams[ map { $_, $n-1-$_} 0..($n/2)-1 ]; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 169: | Line 1,209: | ||
Round 11: 1 vs 12 2 vs 11 3 vs 10 4 vs 9 5 vs 8 6 vs 7 |
Round 11: 1 vs 12 2 vs 11 3 vs 10 4 vs 9 5 vs 8 6 vs 7 |
||
</pre> |
</pre> |
||
===Even and Odd=== |
|||
<syntaxhighlight lang="perl">use strict; |
|||
use warnings; |
|||
use feature 'say'; |
|||
use List::AllUtils <pairwise all>; |
|||
sub round_robin { |
|||
my($n) = @_; |
|||
my($round,@pairings); |
|||
my @players = (1,0)[$n%2] .. $n; |
|||
my $half = +@players / 2; |
|||
while () { |
|||
my @a = @players[ 0 .. $half-1]; |
|||
my @b = reverse @players[$half .. $#players]; |
|||
push @pairings, sprintf "Round %2d: %s\n", ++$round, join ' ', pairwise { sprintf "%3d vs %2d", $a, $b } @a, @b; |
|||
push @players, splice @players, 1, @players-2; |
|||
last if all { $players[$_-1] < $players[$_] } 1..$#players; |
|||
} |
|||
@pairings |
|||
} |
|||
say join '', round_robin 12; |
|||
say ''; |
|||
say join '', map { s/0 vs /Bye: /r } round_robin 7;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Round 1: 1 vs 12 2 vs 11 3 vs 10 4 vs 9 5 vs 8 6 vs 7 |
|||
Round 2: 1 vs 11 12 vs 10 2 vs 9 3 vs 8 4 vs 7 5 vs 6 |
|||
Round 3: 1 vs 10 11 vs 9 12 vs 8 2 vs 7 3 vs 6 4 vs 5 |
|||
Round 4: 1 vs 9 10 vs 8 11 vs 7 12 vs 6 2 vs 5 3 vs 4 |
|||
Round 5: 1 vs 8 9 vs 7 10 vs 6 11 vs 5 12 vs 4 2 vs 3 |
|||
Round 6: 1 vs 7 8 vs 6 9 vs 5 10 vs 4 11 vs 3 12 vs 2 |
|||
Round 7: 1 vs 6 7 vs 5 8 vs 4 9 vs 3 10 vs 2 11 vs 12 |
|||
Round 8: 1 vs 5 6 vs 4 7 vs 3 8 vs 2 9 vs 12 10 vs 11 |
|||
Round 9: 1 vs 4 5 vs 3 6 vs 2 7 vs 12 8 vs 11 9 vs 10 |
|||
Round 10: 1 vs 3 4 vs 2 5 vs 12 6 vs 11 7 vs 10 8 vs 9 |
|||
Round 11: 1 vs 2 3 vs 12 4 vs 11 5 vs 10 6 vs 9 7 vs 8 |
|||
Round 1: Bye: 7 1 vs 6 2 vs 5 3 vs 4 |
|||
Round 2: Bye: 6 7 vs 5 1 vs 4 2 vs 3 |
|||
Round 3: Bye: 5 6 vs 4 7 vs 3 1 vs 2 |
|||
Round 4: Bye: 4 5 vs 3 6 vs 2 7 vs 1 |
|||
Round 5: Bye: 3 4 vs 2 5 vs 1 6 vs 7 |
|||
Round 6: Bye: 2 3 vs 1 4 vs 7 5 vs 6 |
|||
Round 7: Bye: 1 2 vs 7 3 vs 6 4 vs 5</pre> |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Based on the circle with rotor diagrams on the wikipedia page, and implements home/away. |
Based on the circle with rotor diagrams on the wikipedia page, and implements home/away. |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
Line 203: | Line 1,288: | ||
<span style="color: #000000;">n</span> <span style="color: #0000FF;">-=</span> <span style="color: #7060A8;">even</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (circle must be odd)</span> |
<span style="color: #000000;">n</span> <span style="color: #0000FF;">-=</span> <span style="color: #7060A8;">even</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (circle must be odd)</span> |
||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
<span style="color: #004080;">sequence</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
||
<span style="color: #008080;">for</span> <span style="color: #000000;">rownd</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (since "round" is a |
<span style="color: #008080;">for</span> <span style="color: #000000;">rownd</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (since "round" is a builtin)</span> |
||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">games</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">even</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rownd</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #000000;">rotor</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?{</span><span style="color: #000000;">rownd</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rotor</span><span style="color: #0000FF;">}:{</span><span style="color: #000000;">rotor</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rownd</span><span style="color: #0000FF;">})}</span> |
<span style="color: #004080;">sequence</span> <span style="color: #000000;">games</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">even</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rownd</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #000000;">rotor</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?{</span><span style="color: #000000;">rownd</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rotor</span><span style="color: #0000FF;">}:{</span><span style="color: #000000;">rotor</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rownd</span><span style="color: #0000FF;">})}</span> |
||
<span style="color: #004080;">integer</span> <span style="color: #000000;">opponent</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span> <span style="color: #000080;font-style:italic;">-- pair rest off from last inwards,</span> |
<span style="color: #004080;">integer</span> <span style="color: #000000;">opponent</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span> <span style="color: #000080;font-style:italic;">-- pair rest off from last inwards,</span> |
||
Line 231: | Line 1,316: | ||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 254: | Line 1,339: | ||
While I "optimised away" the need for a physical rotate, obviously not because I was concerned with performance but more in the hope of creating shorter and more elegant code, in the end it made little difference. |
While I "optimised away" the need for a physical rotate, obviously not because I was concerned with performance but more in the hope of creating shorter and more elegant code, in the end it made little difference. |
||
Should it be more to your taste, you can remove "l" and replace the inner loop above with: |
Should it be more to your taste, you can remove "l" and replace the inner loop above with: |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">circle</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> |
<span style="color: #004080;">sequence</span> <span style="color: #000000;">circle</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> |
||
<span style="color: #008080;">for</span> <span style="color: #000000;">rownd</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (since "round" is a bultin)</span> |
<span style="color: #008080;">for</span> <span style="color: #000000;">rownd</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (since "round" is a bultin)</span> |
||
Line 270: | Line 1,355: | ||
<span style="color: #000000;">circle</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">circle</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]&</span><span style="color: #000000;">circle</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- (physically rotate it)</span> |
<span style="color: #000000;">circle</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">circle</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]&</span><span style="color: #000000;">circle</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- (physically rotate it)</span> |
||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
=={{header|Picat}}== |
|||
===Constraint modelling=== |
|||
<syntaxhighlight lang="picat">import sat. |
|||
main => |
|||
nolog, |
|||
N = 12, |
|||
tournament_cp(N, NumRounds,NumPairs,_,X,Bye), |
|||
print_tournament(X,NumRounds,NumPairs,Bye), |
|||
nl. |
|||
tournament_cp(N, NumRounds,NumPairs,Extras, X,Bye) => |
|||
% Adjust for odd number of players. |
|||
% The bye (Dummy) player is N+1. |
|||
if N mod 2 == 1 then |
|||
N := N + 1, |
|||
Bye = N |
|||
end, |
|||
NumRounds = N-1, |
|||
NumPairs = N div 2, |
|||
X = new_array(NumRounds,NumPairs,2), |
|||
X :: 1..N, |
|||
% ensure that all players play each other |
|||
foreach(P1 in 1..N, P2 in P1+1..N) |
|||
sum([X[Round,P,1] #= P1 #/\ X[Round,P,2] #= P2 : Round in 1..NumRounds, P in 1..NumPairs]) #= 1 |
|||
end, |
|||
foreach(Round in 1..NumRounds) |
|||
all_different([X[Round,I,J] : I in 1..NumPairs, J in 1..2]), |
|||
% symmetry breaking |
|||
% - all first players in increasing order |
|||
increasing_strict([X[Round,I,1] : I in 1..NumPairs]), |
|||
% - player 1 < player 2 |
|||
foreach(P in 1..NumPairs) |
|||
X[Round,P,1] #< X[Round,P,2] |
|||
end |
|||
end, |
|||
if Extras != [] then |
|||
foreach([P1,P2,Round] in Extras) |
|||
sum([X[Round,P,1] #= P1 #/\ X[Round,P,2] #= P2 : P in 1..NumPairs]) #= 1 |
|||
end |
|||
end, |
|||
solve($[ff,split],X). |
|||
print_tournament(X,NumRounds,NumPairs,Bye) => |
|||
N = X[1].len, |
|||
foreach(Round in 1..NumRounds) |
|||
printf("Round %2d: ", Round), |
|||
if N > 10 then nl end, |
|||
foreach(P in 1..NumPairs) |
|||
P2Val = X[Round,P,2], |
|||
if var(Bye) ; P2Val != Bye then |
|||
printf("(%2w vs %2w) ",X[Round,P,1],P2Val), |
|||
if N > 10 then nl end |
|||
end |
|||
end, |
|||
nl |
|||
end, |
|||
nl.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Round 1: ( 1 vs 11) ( 2 vs 5) ( 3 vs 6) ( 4 vs 12) ( 7 vs 9) ( 8 vs 10) |
|||
Round 2: ( 1 vs 5) ( 2 vs 4) ( 3 vs 10) ( 6 vs 7) ( 8 vs 9) (11 vs 12) |
|||
Round 3: ( 1 vs 6) ( 2 vs 8) ( 3 vs 5) ( 4 vs 11) ( 7 vs 10) ( 9 vs 12) |
|||
Round 4: ( 1 vs 12) ( 2 vs 11) ( 3 vs 7) ( 4 vs 6) ( 5 vs 8) ( 9 vs 10) |
|||
Round 5: ( 1 vs 9) ( 2 vs 6) ( 3 vs 12) ( 4 vs 5) ( 7 vs 8) (10 vs 11) |
|||
Round 6: ( 1 vs 4) ( 2 vs 3) ( 5 vs 7) ( 6 vs 10) ( 8 vs 12) ( 9 vs 11) |
|||
Round 7: ( 1 vs 2) ( 3 vs 4) ( 5 vs 10) ( 6 vs 9) ( 7 vs 12) ( 8 vs 11) |
|||
Round 8: ( 1 vs 3) ( 2 vs 12) ( 4 vs 10) ( 5 vs 9) ( 6 vs 8) ( 7 vs 11) |
|||
Round 9: ( 1 vs 10) ( 2 vs 7) ( 3 vs 8) ( 4 vs 9) ( 5 vs 11) ( 6 vs 12) |
|||
Round 10: ( 1 vs 8) ( 2 vs 10) ( 3 vs 9) ( 4 vs 7) ( 5 vs 12) ( 6 vs 11) |
|||
Round 11: ( 1 vs 7) ( 2 vs 9) ( 3 vs 11) ( 4 vs 8) ( 5 vs 6) (10 vs 12) </pre> |
|||
===Constraint model with extra constraints=== |
|||
The constraint model is slower than the algorithmic approach for larger number of players. The advantage of a constraint model is that it is quite easy to add extra constraint, such that some players must play in a certain round (e.g. for availability reasons etc). |
|||
Here are some extra constraints: |
|||
* 1 vs 2 must be played the third round |
|||
* 5 vs 9 must be played in the 7th round |
|||
* 2 vs 3 must be played in the last round |
|||
* 7 vs 12 must be played in the last round |
|||
<syntaxhighlight lang="picat">main => |
|||
nolog, |
|||
N = 12, |
|||
Extras = [[1,2,3], |
|||
[5,9,7], |
|||
[2,3,N-1], |
|||
[7,12,N-1]], |
|||
tournament_cp(N, NumRounds,NumPairs,Extras,X,Bye), |
|||
print_tournament(X,NumRounds,NumPairs,Bye).</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Round 1: ( 1 vs 11) ( 2 vs 4) ( 3 vs 12) ( 5 vs 8) ( 6 vs 9) ( 7 vs 10) |
|||
Round 2: ( 1 vs 12) ( 2 vs 11) ( 3 vs 9) ( 4 vs 7) ( 5 vs 10) ( 6 vs 8) |
|||
Round 3: ( 1 vs 2) ( 3 vs 10) ( 4 vs 12) ( 5 vs 11) ( 6 vs 7) ( 8 vs 9) |
|||
Round 4: ( 1 vs 4) ( 2 vs 6) ( 3 vs 11) ( 5 vs 12) ( 7 vs 8) ( 9 vs 10) |
|||
Round 5: ( 1 vs 10) ( 2 vs 7) ( 3 vs 5) ( 4 vs 6) ( 8 vs 12) ( 9 vs 11) |
|||
Round 6: ( 1 vs 6) ( 2 vs 5) ( 3 vs 4) ( 7 vs 9) ( 8 vs 11) (10 vs 12) |
|||
Round 7: ( 1 vs 3) ( 2 vs 12) ( 4 vs 8) ( 5 vs 9) ( 6 vs 10) ( 7 vs 11) |
|||
Round 8: ( 1 vs 7) ( 2 vs 8) ( 3 vs 6) ( 4 vs 5) ( 9 vs 12) (10 vs 11) |
|||
Round 9: ( 1 vs 8) ( 2 vs 9) ( 3 vs 7) ( 4 vs 10) ( 5 vs 6) (11 vs 12) |
|||
Round 10: ( 1 vs 9) ( 2 vs 10) ( 3 vs 8) ( 4 vs 11) ( 5 vs 7) ( 6 vs 12) |
|||
Round 11: ( 1 vs 5) ( 2 vs 3) ( 4 vs 9) ( 6 vs 11) ( 7 vs 12) ( 8 vs 10) </pre> |
|||
For this small tournament it took about the same time with and without these extra constraints (0.08s). |
|||
===Number of solutions=== |
|||
Here are the number of different solutions for N = [2,4,6,8] with the symmetry constraints (but without the extra round constraints). The number of odd N players is the same as the number of N-1 players. |
|||
Here the cp solver is used since it's faster than the sat solver for generating all solutions. |
|||
<syntaxhighlight lang="picat">import cp. |
|||
main => |
|||
foreach(N in 2..2..8) |
|||
Count = count_all(tournament_cp(N, _NumRounds,_NumPairs,_Extras,_X,_Bye)), |
|||
println(N=Count) |
|||
end.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>2 = 1 |
|||
4 = 6 |
|||
6 = 720 |
|||
8 = 31449600</pre> |
|||
This seems to be related to the OEIS sequence [https://oeis.org/A036981 "A036981: (2n+1) X (2n+1) symmetric matrices each of whose rows is a permutation of 1..(2n+1)"]. The next term (for N=10) would be 444733651353600 which takes too long to check. |
|||
=={{header|Python}}== |
|||
===Original method by R. Schurig=== |
|||
<syntaxhighlight lang="python"> |
|||
# round_robin.py by Xing216 |
|||
from copy import deepcopy |
|||
def shift_up(myList): |
|||
myLen = len(myList) |
|||
return [myList[i % myLen] for i in range(1, 1 + myLen)] |
|||
def scheduler(competitors): |
|||
"""Uses the original method by Richard Schurig""" |
|||
if competitors % 2 == 1: |
|||
n = competitors + 1 |
|||
horizontal_rows = n - 1 |
|||
else: |
|||
n = competitors |
|||
horizontal_rows = n |
|||
vertical_rows = n // 2 |
|||
table = [[[] for _ in range(vertical_rows)] for _ in range(horizontal_rows)] |
|||
competitor = 1 |
|||
for i, row in enumerate(table): |
|||
for col in table[i]: |
|||
if competitor == competitors: |
|||
col.append(competitor) |
|||
competitor = 1 |
|||
else: |
|||
col.append(competitor) |
|||
competitor += 1 |
|||
table2 = deepcopy(table) |
|||
table2 = shift_up(table2) |
|||
for row in table2: row.reverse() |
|||
for i, row in enumerate(table): |
|||
for j, col in enumerate(table[i]): |
|||
col.append(table2[i][j][0]) |
|||
return table |
|||
def print_table(table): |
|||
for i, round in enumerate(table): |
|||
print(f"Round {(i + 1):2}", end=": ") |
|||
for match in round: |
|||
print(f"{match[0]:2}-{match[1]:<2}", end=" ") |
|||
print() |
|||
print_table(scheduler(12)) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:10em"> |
|||
Round 1: 1-12 2-11 3-10 4-9 5-8 6-7 |
|||
Round 2: 7-6 8-5 9-4 10-3 11-2 12-1 |
|||
Round 3: 1-12 2-11 3-10 4-9 5-8 6-7 |
|||
Round 4: 7-6 8-5 9-4 10-3 11-2 12-1 |
|||
Round 5: 1-12 2-11 3-10 4-9 5-8 6-7 |
|||
Round 6: 7-6 8-5 9-4 10-3 11-2 12-1 |
|||
Round 7: 1-12 2-11 3-10 4-9 5-8 6-7 |
|||
Round 8: 7-6 8-5 9-4 10-3 11-2 12-1 |
|||
Round 9: 1-12 2-11 3-10 4-9 5-8 6-7 |
|||
Round 10: 7-6 8-5 9-4 10-3 11-2 12-1 |
|||
Round 11: 1-12 2-11 3-10 4-9 5-8 6-7 |
|||
Round 12: 7-6 8-5 9-4 10-3 11-2 12-1 |
|||
</pre> |
|||
===Berger Tables=== |
|||
<syntaxhighlight lang="python"> |
|||
# berger_table.py by Xing216 |
|||
def scheduler(competitors): |
|||
if competitors & 1: |
|||
competitors += 1 |
|||
last = competitors |
|||
half = competitors // 2 |
|||
rounds = last - 1 |
|||
tables = [list() for i in range(rounds)] |
|||
for i in range(1, last): |
|||
row = i - 1 |
|||
tables[row] = [list() * half] |
|||
tables[row][0] = [0, 0] |
|||
if i & 1: |
|||
tables[row][0][1] = last |
|||
opponent = (i + 1) // 2 |
|||
tables[row][0][0] = opponent |
|||
else: |
|||
tables[row][0][0] = last |
|||
opponent = half + i // 2 |
|||
tables[row][0][1] = opponent |
|||
for _ in range(1, half): |
|||
next_opponent = opponent + 1 if opponent < last - 1 else 1 |
|||
tables[row].append([next_opponent, 0]) |
|||
opponent = next_opponent |
|||
last_guest = 1 |
|||
for i in reversed(range(1, last)): |
|||
row = i - 1 |
|||
for j in reversed(range(0, half)): |
|||
opponent = last_guest |
|||
if j > 0: |
|||
tables[row][j][1] = opponent |
|||
last_guest = opponent + 1 if opponent < last - 1 else 1 |
|||
return tables |
|||
def print_table(table): |
|||
for i, round in enumerate(table): |
|||
print(f"Round {(i + 1):2}", end=": ") |
|||
for match in round: |
|||
print(f"{match[0]:2}-{match[1]:<2}", end=" ") |
|||
print() |
|||
print_table(scheduler(12)) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:10em"> |
|||
Round 1: 1-12 2-11 3-10 4-9 5-8 6-7 |
|||
Round 2: 12-7 8-6 9-5 10-4 11-3 1-2 |
|||
Round 3: 2-12 3-1 4-11 5-10 6-9 7-8 |
|||
Round 4: 12-8 9-7 10-6 11-5 1-4 2-3 |
|||
Round 5: 3-12 4-2 5-1 6-11 7-10 8-9 |
|||
Round 6: 12-9 10-8 11-7 1-6 2-5 3-4 |
|||
Round 7: 4-12 5-3 6-2 7-1 8-11 9-10 |
|||
Round 8: 12-10 11-9 1-8 2-7 3-6 4-5 |
|||
Round 9: 5-12 6-4 7-3 8-2 9-1 10-11 |
|||
Round 10: 12-11 1-10 2-9 3-8 4-7 5-6 |
|||
Round 11: 6-12 7-5 8-4 9-3 10-2 11-1 |
|||
</pre> |
|||
=={{header|Quackery}}== |
|||
<syntaxhighlight lang="Quackery"> |
|||
[ stack ] is participants ( --> s ) |
|||
[ dup 10 < if sp echo ] is recho ( n --> ) |
|||
[ dup participants share |
|||
> iff |
|||
[ drop say " bye " ] |
|||
done |
|||
say " vs " |
|||
dup echo 10 < if sp ] is lecho ( n --> ) |
|||
[ dup participants put |
|||
dup 1 & + |
|||
[] over 1 - times |
|||
[ i 1+ join ] |
|||
over 1 - times |
|||
[ say "Round " |
|||
i^ 1+ recho |
|||
say ": " |
|||
over dip |
|||
[ 2dup join ] |
|||
times |
|||
[ i i^ < iff |
|||
conclude done |
|||
dup i peek recho |
|||
dup i^ peek lecho |
|||
say " " ] |
|||
drop cr |
|||
over 2 / 1+ |
|||
split swap join ] |
|||
2drop participants release ] is schedule ( n --> ) |
|||
say "12 participants:" cr |
|||
12 schedule |
|||
cr |
|||
say "5 participants:" cr |
|||
5 schedule |
|||
cr |
|||
say "1 participant:" cr |
|||
1 schedule |
|||
cr |
|||
say "0 participants:" cr |
|||
0 schedule</syntaxhighlight> |
|||
{{out}} |
|||
<pre>12 participants: |
|||
Round 1: 1 vs 12 2 vs 11 3 vs 10 4 vs 9 5 vs 8 6 vs 7 |
|||
Round 2: 5 vs 12 6 vs 4 7 vs 3 8 vs 2 9 vs 1 10 vs 11 |
|||
Round 3: 9 vs 12 10 vs 8 11 vs 7 1 vs 6 2 vs 5 3 vs 4 |
|||
Round 4: 2 vs 12 3 vs 1 4 vs 11 5 vs 10 6 vs 9 7 vs 8 |
|||
Round 5: 6 vs 12 7 vs 5 8 vs 4 9 vs 3 10 vs 2 11 vs 1 |
|||
Round 6: 10 vs 12 11 vs 9 1 vs 8 2 vs 7 3 vs 6 4 vs 5 |
|||
Round 7: 3 vs 12 4 vs 2 5 vs 1 6 vs 11 7 vs 10 8 vs 9 |
|||
Round 8: 7 vs 12 8 vs 6 9 vs 5 10 vs 4 11 vs 3 1 vs 2 |
|||
Round 9: 11 vs 12 1 vs 10 2 vs 9 3 vs 8 4 vs 7 5 vs 6 |
|||
Round 10: 4 vs 12 5 vs 3 6 vs 2 7 vs 1 8 vs 11 9 vs 10 |
|||
Round 11: 8 vs 12 9 vs 7 10 vs 6 11 vs 5 1 vs 4 2 vs 3 |
|||
5 participants: |
|||
Round 1: 1 bye 2 vs 5 3 vs 4 |
|||
Round 2: 2 bye 3 vs 1 4 vs 5 |
|||
Round 3: 3 bye 4 vs 2 5 vs 1 |
|||
Round 4: 4 bye 5 vs 3 1 vs 2 |
|||
Round 5: 5 bye 1 vs 4 2 vs 3 |
|||
1 participant: |
|||
Round 1: 1 bye |
|||
0 participants: |
|||
</pre> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
<lang |
<syntaxhighlight lang="raku" line>my @players = (1,0)[$_%2] .. $_ given 12; |
||
my $half = +@players div 2; |
my $half = +@players div 2; |
||
my $round = 0; |
my $round = 0; |
||
Line 281: | Line 1,690: | ||
@players[1..*].=rotate(-1); |
@players[1..*].=rotate(-1); |
||
last if [<] @players; |
last if [<] @players; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Round 1: ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) |
<pre>Round 1: ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) |
||
Line 296: | Line 1,705: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
< |
<syntaxhighlight lang="ruby">def round_robin( n ) |
||
rotating_players = (2..n).map(&:to_s) #player 1 to be added later |
rotating_players = (2..n).map(&:to_s) #player 1 to be added later |
||
rotating_players << "bye" if n.odd? |
rotating_players << "bye" if n.odd? |
||
Line 312: | Line 1,721: | ||
puts |
puts |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre>Round 1 |
<pre>Round 1 |
||
Line 357: | Line 1,766: | ||
1 3 4 5 6 7 |
1 3 4 5 6 7 |
||
2 12 11 10 9 8 |
2 12 11 10 9 8 |
||
</pre> |
|||
=={{header|Rust}}== |
|||
{{Trans|Nim}} |
|||
<syntaxhighlight lang="rust"> |
|||
fn round_robin(n: usize) { |
|||
assert!(n >= 2); |
|||
let mut n = n; |
|||
let mut list1: Vec<usize> = (2..=n).collect(); |
|||
if n % 2 == 1 { |
|||
list1.push(0); // 0 denotes a "bye". |
|||
n += 1; |
|||
} |
|||
for r in 1..n { |
|||
print!("Round {:2}:", r); |
|||
let list2 = vec![1].into_iter().chain(list1.iter().cloned()).collect::<Vec<_>>(); |
|||
for i in 0..(n / 2) { |
|||
print!(" ({:>2} vs {:<2})", list2[i], list2[n - i - 1]); |
|||
} |
|||
println!(); |
|||
list1.rotate_right(1); |
|||
} |
|||
} |
|||
fn main() { |
|||
println!("Round robin for 12 players:\n"); |
|||
round_robin(12); |
|||
println!("\n\nRound robin for 5 players (0 denotes a bye):\n"); |
|||
round_robin(5); |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Round robin for 12 players: |
|||
Round 1: ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) |
|||
Round 2: ( 1 vs 11) (12 vs 10) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) |
|||
Round 3: ( 1 vs 10) (11 vs 9 ) (12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) |
|||
Round 4: ( 1 vs 9 ) (10 vs 8 ) (11 vs 7 ) (12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 5: ( 1 vs 8 ) ( 9 vs 7 ) (10 vs 6 ) (11 vs 5 ) (12 vs 4 ) ( 2 vs 3 ) |
|||
Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) (10 vs 4 ) (11 vs 3 ) (12 vs 2 ) |
|||
Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) (10 vs 2 ) (11 vs 12) |
|||
Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12) (10 vs 11) |
|||
Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12) ( 8 vs 11) ( 9 vs 10) |
|||
Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12) ( 6 vs 11) ( 7 vs 10) ( 8 vs 9 ) |
|||
Round 11: ( 1 vs 2 ) ( 3 vs 12) ( 4 vs 11) ( 5 vs 10) ( 6 vs 9 ) ( 7 vs 8 ) |
|||
Round robin for 5 players (0 denotes a bye): |
|||
Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) |
|||
Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) |
|||
Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) |
|||
Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 ) |
|||
</pre> |
|||
=={{header|Scala}}== |
|||
{{trans|Java}} |
|||
<syntaxhighlight lang="Scala"> |
|||
object RoundRobinTournamentSchedule extends App { |
|||
def roundRobin(teamCount: Int): Unit = { |
|||
require(teamCount >= 2, s"Number of teams must be greater than 2: $teamCount") |
|||
var rotatingList = (2 to teamCount).toList |
|||
var adjustedTeamCount = teamCount |
|||
if (teamCount % 2 == 1) { |
|||
rotatingList :+= 0 |
|||
adjustedTeamCount += 1 |
|||
} |
|||
for (round <- 1 until adjustedTeamCount) { |
|||
print(f"Round $round%2d:") |
|||
val fixedList = 1 :: rotatingList |
|||
for (i <- 0 until adjustedTeamCount / 2) { |
|||
print(f" ( ${fixedList(i)}%2d vs ${fixedList(adjustedTeamCount - 1 - i)}%2d )") |
|||
} |
|||
println() |
|||
rotatingList = rotatingList.last :: rotatingList.init |
|||
} |
|||
} |
|||
println("Round robin for 12 players:") |
|||
roundRobin(12) |
|||
println() |
|||
println("Round robin for 5 players, 0 denotes a bye:") |
|||
roundRobin(5) |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Round robin for 12 players: |
|||
Round 1: ( 1 vs 12 ) ( 2 vs 11 ) ( 3 vs 10 ) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) |
|||
Round 2: ( 1 vs 11 ) ( 12 vs 10 ) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) |
|||
Round 3: ( 1 vs 10 ) ( 11 vs 9 ) ( 12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) |
|||
Round 4: ( 1 vs 9 ) ( 10 vs 8 ) ( 11 vs 7 ) ( 12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 5: ( 1 vs 8 ) ( 9 vs 7 ) ( 10 vs 6 ) ( 11 vs 5 ) ( 12 vs 4 ) ( 2 vs 3 ) |
|||
Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) ( 10 vs 4 ) ( 11 vs 3 ) ( 12 vs 2 ) |
|||
Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) ( 10 vs 2 ) ( 11 vs 12 ) |
|||
Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12 ) ( 10 vs 11 ) |
|||
Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12 ) ( 8 vs 11 ) ( 9 vs 10 ) |
|||
Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12 ) ( 6 vs 11 ) ( 7 vs 10 ) ( 8 vs 9 ) |
|||
Round 11: ( 1 vs 2 ) ( 3 vs 12 ) ( 4 vs 11 ) ( 5 vs 10 ) ( 6 vs 9 ) ( 7 vs 8 ) |
|||
Round robin for 5 players, 0 denotes a bye: |
|||
Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) |
|||
Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) |
|||
Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) |
|||
Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) |
|||
Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 ) |
|||
</pre> |
|||
=={{header|Swift}}== |
|||
{{trans|Java}} |
|||
<syntaxhighlight lang="Swift"> |
|||
import Foundation |
|||
func roundRobin(teamCount: Int) { |
|||
if teamCount < 2 { |
|||
fatalError("Number of teams must be greater than 2: \(teamCount)") |
|||
} |
|||
var rotatingList = Array(2...teamCount) |
|||
var effectiveTeamCount = teamCount |
|||
if teamCount % 2 == 1 { |
|||
rotatingList.append(0) // Adding a 'bye' in case of odd number of teams |
|||
effectiveTeamCount += 1 |
|||
} |
|||
for round in 1..<effectiveTeamCount { |
|||
print("Round \(round):", terminator: "") |
|||
let fixedList = [1] + rotatingList |
|||
for i in 0..<(effectiveTeamCount / 2) { |
|||
print(" (\(fixedList[i]) vs \(fixedList[effectiveTeamCount - 1 - i]))", terminator: "") |
|||
} |
|||
print() |
|||
rotatingList.rotate(shift: 1) |
|||
} |
|||
} |
|||
extension Array { |
|||
mutating func rotate(shift: Int) { |
|||
let index = shift >= 0 ? |
|||
self.index(self.startIndex, offsetBy: self.count - shift, limitedBy: self.endIndex) : |
|||
self.index(self.startIndex, offsetBy: -shift, limitedBy: self.endIndex) |
|||
guard let validIndex = index else { return } |
|||
self = Array(self[validIndex..<self.endIndex] + self[self.startIndex..<validIndex]) |
|||
} |
|||
} |
|||
// Example usage |
|||
print("Round robin for 12 players:") |
|||
roundRobin(teamCount: 12) |
|||
print("\nRound robin for 5 players, 0 denotes a bye:") |
|||
roundRobin(teamCount: 5) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Round robin for 12 players: |
|||
Round 1: (1 vs 12) (2 vs 11) (3 vs 10) (4 vs 9) (5 vs 8) (6 vs 7) |
|||
Round 2: (1 vs 11) (12 vs 10) (2 vs 9) (3 vs 8) (4 vs 7) (5 vs 6) |
|||
Round 3: (1 vs 10) (11 vs 9) (12 vs 8) (2 vs 7) (3 vs 6) (4 vs 5) |
|||
Round 4: (1 vs 9) (10 vs 8) (11 vs 7) (12 vs 6) (2 vs 5) (3 vs 4) |
|||
Round 5: (1 vs 8) (9 vs 7) (10 vs 6) (11 vs 5) (12 vs 4) (2 vs 3) |
|||
Round 6: (1 vs 7) (8 vs 6) (9 vs 5) (10 vs 4) (11 vs 3) (12 vs 2) |
|||
Round 7: (1 vs 6) (7 vs 5) (8 vs 4) (9 vs 3) (10 vs 2) (11 vs 12) |
|||
Round 8: (1 vs 5) (6 vs 4) (7 vs 3) (8 vs 2) (9 vs 12) (10 vs 11) |
|||
Round 9: (1 vs 4) (5 vs 3) (6 vs 2) (7 vs 12) (8 vs 11) (9 vs 10) |
|||
Round 10: (1 vs 3) (4 vs 2) (5 vs 12) (6 vs 11) (7 vs 10) (8 vs 9) |
|||
Round 11: (1 vs 2) (3 vs 12) (4 vs 11) (5 vs 10) (6 vs 9) (7 vs 8) |
|||
Round robin for 5 players, 0 denotes a bye: |
|||
Round 1: (1 vs 0) (2 vs 5) (3 vs 4) |
|||
Round 2: (1 vs 5) (0 vs 4) (2 vs 3) |
|||
Round 3: (1 vs 4) (5 vs 3) (0 vs 2) |
|||
Round 4: (1 vs 3) (4 vs 2) (5 vs 0) |
|||
Round 5: (1 vs 2) (3 vs 0) (4 vs 5) |
|||
</pre> |
</pre> |
||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
{{libheader|Wren-fmt}} |
{{libheader|Wren-fmt}} |
||
< |
<syntaxhighlight lang="wren">import "./fmt" for Fmt |
||
var rotate = Fn.new { |lst| |
var rotate = Fn.new { |lst| |
||
Line 372: | Line 1,974: | ||
var lst = (2..n).toList |
var lst = (2..n).toList |
||
if (n % 2 == 1) { |
if (n % 2 == 1) { |
||
lst |
lst.add(0) // 0 denotes a bye |
||
n = n + 1 |
n = n + 1 |
||
} |
} |
||
var n2 = n / 2 |
|||
for (r in 1...n) { |
for (r in 1...n) { |
||
Fmt.write("Round $2d", r) |
Fmt.write("Round $2d", r) |
||
var lst2 = [1] + lst |
var lst2 = [1] + lst |
||
for (i in 0... |
for (i in 0...n/2) Fmt.write(" ($2d vs $-2d)", lst2[i], lst2[n - 1 - i]) |
||
System.print() |
System.print() |
||
rotate.call(lst) |
rotate.call(lst) |
||
Line 388: | Line 1,989: | ||
roundRobin.call(12) |
roundRobin.call(12) |
||
System.print("\n\nRound robin for 5 players (0 denotes a bye) :\n") |
System.print("\n\nRound robin for 5 players (0 denotes a bye) :\n") |
||
roundRobin.call(5) |
roundRobin.call(5) |
||
</syntaxhighlight> |
|||
{{out}} |
{{out}} |
||
Line 417: | Line 2,019: | ||
=={{header|XPL0}}== |
=={{header|XPL0}}== |
||
< |
<syntaxhighlight lang="xpl0">def N = 12; \number of players (must be even) |
||
int I, Player(N+1), Round, Temp; |
int I, Player(N+1), Round, Temp; |
||
[for I:= 1 to N do Player(I):= I; |
[for I:= 1 to N do Player(I):= I; |
||
Line 433: | Line 2,035: | ||
Player(2):= Temp; |
Player(2):= Temp; |
||
]; |
]; |
||
]</ |
]</syntaxhighlight> |
||
{{out}} |
{{out}} |
Latest revision as of 09:33, 7 March 2024
A round-robin tournament is also known as an all-play-all-tournament; each participant plays every other participant once.
You are encouraged to solve this task according to the task description, using any language you may know.
For N participants the number of rounds is N-1 if N is an even number. When there are an odd number of participants then each round one contestor has no opponent (AKA as a "bye"). The number of rounds is N in that case.
- Task
Write a program that prints out a tournament schedule for 12 participants (represented by numbers 1 to 12).
- See also
Ada
-- Create a round-robin schedule
-- J. Carter 2023 May
-- Circle method
with Ada.Text_IO;
procedure Round_Robin is
type Player_ID is range 1 .. 12;
type Player_List is array (Player_ID) of Player_ID;
Circle : Player_List;
J : Player_ID;
begin -- Round_Robin
Fill : for I in Circle'Range loop
Circle (I) := I;
end loop Fill;
All_Rounds : for Round in 1 .. Player_ID'Last - 1 loop
Ada.Text_IO.Put_Line (Item => "Round" & Round'Image);
J := Player_ID'Last;
Pairs : for I in 1 .. Player_ID'Last / 2 loop
Order : declare
Min : constant Player_ID := Player_ID'Min (Circle (I), Circle (J) );
Max : constant Player_ID := Player_ID'Max (Circle (I), Circle (J) );
begin -- Order
Ada.Text_IO.Put_Line (Item => Min'Image & " v" & Max'Image);
J := J - 1;
end Order;
end loop Pairs;
Ada.Text_IO.New_Line;
Circle := Circle (Circle'First) & Circle (Circle'Last) & Circle (Circle'First + 1 .. Circle'Last - 1);
end loop All_Rounds;
end Round_Robin;
- Output:
Round 1 1 v 12 2 v 11 3 v 10 4 v 9 5 v 8 6 v 7 Round 2 1 v 11 10 v 12 2 v 9 3 v 8 4 v 7 5 v 6 Round 3 1 v 10 9 v 11 8 v 12 2 v 7 3 v 6 4 v 5 Round 4 1 v 9 8 v 10 7 v 11 6 v 12 2 v 5 3 v 4 Round 5 1 v 8 7 v 9 6 v 10 5 v 11 4 v 12 2 v 3 Round 6 1 v 7 6 v 8 5 v 9 4 v 10 3 v 11 2 v 12 Round 7 1 v 6 5 v 7 4 v 8 3 v 9 2 v 10 11 v 12 Round 8 1 v 5 4 v 6 3 v 7 2 v 8 9 v 12 10 v 11 Round 9 1 v 4 3 v 5 2 v 6 7 v 12 8 v 11 9 v 10 Round 10 1 v 3 2 v 4 5 v 12 6 v 11 7 v 10 8 v 9 Round 11 1 v 2 3 v 12 4 v 11 5 v 10 6 v 9 7 v 8
ALGOL 68
BEGIN # round-robin tournament schedule - translation of XPL0 #
INT n = 12; # number of players (must be even) #
[ 1 : n ]INT player;
FOR i TO n DO player[ i ] := i OD;
FOR round TO n - 1 DO
print( ( whole( round, 0 ), ":" ) );
FOR i TO n OVER 2 DO
print( ( REPR 9, whole( player[ i ], 0 ) ) )
OD;
print( ( newline ) );
FOR i FROM n BY -1 TO ( n OVER 2 ) + 1 DO
print( ( REPR 9, whole( player[ i ], 0 ) ) )
OD;
print( ( newline, newline ) );
INT nth player = player[ n ];
player[ 3 : n ] := player[ 2 : n - 1 ];
player[ 2 ] := nth player
OD
END
- Output:
Same as the XPL0 sample.
APL
∇ SCHEDULER N;R;I
R←(⍳N),(2|N)⍴'-'
I←0 ⋄ N←⍴(R)
L:⎕←'ROUND',I←I+1
⎕←((N÷2)↑R),[0.5]⌽(N÷2)↓R
R←(1↑R),1⌽1↓R
→(I<N-1)/L
∇
- Output:
SCHEDULER 4 ROUND 1 1 2 4 3 ROUND 2 1 3 2 4 ROUND 3 1 4 3 2
AWK
# syntax: GAWK -f ROUND-ROBIN_TOURNAMENT_SCHEDULE.AWK
BEGIN {
main(1)
main(2)
main(5,"The Bizzaros")
main(12)
exit(0)
}
function main(n,description, arr,i,j,leng,tmp) {
if (n < 2) {
printf("\n%d is too few participants\n",n)
return
}
printf("\n%d players %s\n",n,description)
for (i=1; i<=n; i++) {
arr[i] = i
}
if (n % 2 == 1) {
arr[++n] = 0 # a "bye"
}
leng = length(n-1)
for (i=1; i<n; i++) {
printf("\nround %*d:",leng,i)
for (j=1; j<=n/2; j++) {
printf("%4s",arr[j]==0?"bye":arr[j])
}
printf("\n%*s",leng+7,"")
for (j=n; j>n/2; j--) {
printf("%4s",arr[j]==0?"bye":arr[j])
}
printf("\n")
tmp = arr[n]
for (j=n; j>2; j--) {
arr[j] = arr[j-1]
}
arr[2] = tmp
}
}
- Output:
1 is too few participants 2 players round 1: 1 2 5 players The Bizzaros round 1: 1 2 3 bye 5 4 round 2: 1 bye 2 5 4 3 round 3: 1 5 bye 4 3 2 round 4: 1 4 5 3 2 bye round 5: 1 3 4 2 bye 5 12 players round 1: 1 2 3 4 5 6 12 11 10 9 8 7 round 2: 1 12 2 3 4 5 11 10 9 8 7 6 round 3: 1 11 12 2 3 4 10 9 8 7 6 5 round 4: 1 10 11 12 2 3 9 8 7 6 5 4 round 5: 1 9 10 11 12 2 8 7 6 5 4 3 round 6: 1 8 9 10 11 12 7 6 5 4 3 2 round 7: 1 7 8 9 10 11 6 5 4 3 2 12 round 8: 1 6 7 8 9 10 5 4 3 2 12 11 round 9: 1 5 6 7 8 9 4 3 2 12 11 10 round 10: 1 4 5 6 7 8 3 2 12 11 10 9 round 11: 1 3 4 5 6 7 2 12 11 10 9 8
BASIC
BASIC256
arraybase 1
print "Twelve teams"
call roundrob(12)
print "Nine teams with byes"
call roundrob(9)
end
function nob(n,i,byes)
#helper function to allow byess to be printed intelligently
if n > 9 then pad = " " else pad = ""
if n = i and byes then
return pad + "B"
else
if i < 10 then return pad + string(i) else return string(i)
end if
end function
subroutine roundrob(n)
byes = 0
if n mod 2 = 1 then #if there is an odd number of competitors
byes = 1 #make note of this fact
n += 1 #and treat the tournament as having one more competitor
end if
dim schd(n)
for i = 1 to n
schd[i] = i #initial population of the array with numbers 1-n
next i
for r = 1 to n-1
print "Round "; rjust(string(r), 2); ": ";
for i = 1 to n/2 #print the pairings according to the scheme
#1 2 3 4
#5 6 7 8
print "("; nob(n,schd[i],byes); " -"; nob(n,schd[i+n/2],byes); " ) ";
next i
print
#now move positions 2-n around clockwise
temp1 = schd[n/2] #need to track two temporary variables
temp2 = schd[n/2+1]
for i = n/2 to 3 step -1 #top row
schd[i] = schd[i-1]
next i
for i = n/2+1 to n-1 #bottom row
schd[i] = schd[i+1]
next i
schd[n] = temp1 #end ifll in the ones that "jumped" between rows
schd[2] = temp2
next r
end subroutine
FreeBASIC
function nob( n as uinteger, i as uinteger, bye as boolean ) as string
'helper function to allow byes to be printed intelligently
dim as string pad
if n > 9 then pad = " " else pad = ""
if n = i and bye then
return pad+"B"
else
if i<10 then return pad + str(i) else return str(i)
end if
end function
sub roundrob( byval n as uinteger )
dim as boolean bye = false
if n mod 2 = 1 then 'if there is an odd number of competitors
bye = 1 'make note of this fact
n += 1 'and treat the tournament as having one more competitor
end if
dim as uinteger schd(1 to n), r, i, temp1, temp2
for i = 1 to n
schd(i) =i 'initial population of the array with numbers 1-n
next i
for r = 1 to n-1
print using "Round ##: ";r;
for i = 1 to n/2 'print the pairings according to the scheme
'1 2 3 4
'5 6 7 8
print using "(& - &) ";nob(n,schd(i),bye);nob(n,schd(i+n\2),bye);
next i
print
'now move positions 2-n around clockwise
temp1 = schd(n/2) 'need to track two temporary variables
temp2 = schd(n/2+1)
for i = n/2 to 3 step -1 'top row
schd(i) = schd(i-1)
next i
for i = n/2+1 to n-1 'bottom row
schd(i) = schd(i+1)
next i
schd(n) = temp1 'fill in the ones that "jumped" between rows
schd(2) = temp2
next r
end sub
print "Twelve teams"
roundrob(12)
print "Nine teams with byes"
roundrob(9)
- Output:
Twelve teams Round 1: ( 1 - 7) ( 2 - 8) ( 3 - 9) ( 4 - 10) ( 5 - 11) ( 6 - 12) Round 2: ( 1 - 8) ( 7 - 9) ( 2 - 10) ( 3 - 11) ( 4 - 12) ( 5 - 6) Round 3: ( 1 - 9) ( 8 - 10) ( 7 - 11) ( 2 - 12) ( 3 - 6) ( 4 - 5) Round 4: ( 1 - 10) ( 9 - 11) ( 8 - 12) ( 7 - 6) ( 2 - 5) ( 3 - 4) Round 5: ( 1 - 11) (10 - 12) ( 9 - 6) ( 8 - 5) ( 7 - 4) ( 2 - 3) Round 6: ( 1 - 12) (11 - 6) (10 - 5) ( 9 - 4) ( 8 - 3) ( 7 - 2) Round 7: ( 1 - 6) (12 - 5) (11 - 4) (10 - 3) ( 9 - 2) ( 8 - 7) Round 8: ( 1 - 5) ( 6 - 4) (12 - 3) (11 - 2) (10 - 7) ( 9 - 8) Round 9: ( 1 - 4) ( 5 - 3) ( 6 - 2) (12 - 7) (11 - 8) (10 - 9) Round 10: ( 1 - 3) ( 4 - 2) ( 5 - 7) ( 6 - 8) (12 - 9) (11 - 10) Round 11: ( 1 - 2) ( 3 - 7) ( 4 - 8) ( 5 - 9) ( 6 - 10) (12 - 11) Nine teams with byes Round 1: ( 1 - 6) ( 2 - 7) ( 3 - 8) ( 4 - 9) ( 5 - B) Round 2: ( 1 - 7) ( 6 - 8) ( 2 - 9) ( 3 - B) ( 4 - 5) Round 3: ( 1 - 8) ( 7 - 9) ( 6 - B) ( 2 - 5) ( 3 - 4) Round 4: ( 1 - 9) ( 8 - B) ( 7 - 5) ( 6 - 4) ( 2 - 3) Round 5: ( 1 - B) ( 9 - 5) ( 8 - 4) ( 7 - 3) ( 6 - 2) Round 6: ( 1 - 5) ( B - 4) ( 9 - 3) ( 8 - 2) ( 7 - 6) Round 7: ( 1 - 4) ( 5 - 3) ( B - 2) ( 9 - 6) ( 8 - 7) Round 8: ( 1 - 3) ( 4 - 2) ( 5 - 6) ( B - 7) ( 9 - 8) Round 9: ( 1 - 2) ( 3 - 6) ( 4 - 7) ( 5 - 8) ( B - 9)
uBasic/4tH
Print "Twelve teams"
Proc _Roundrob(12)
Print
Print "Nine teams with byes"
Proc _Roundrob(9)
End
_Roundrob
Param (1)
Local (5)
b@ = 0
' if there is an odd number of competitors
If a@ % 2 = 1 Then b@ = 1 : a@ = a@ + 1
' make note of this fact and treat the tournament
For d@ = 1 To a@ ' as having one more competitor
@(d@) = d@ ' initial population of the array with numbers 1-n
Next
For c@ = 1 To a@-1 ' print the pairings according to the scheme
Print Using "Round __: ";c@;
' 1 2 3 4
For d@ = 1 To a@/2 ' 5 6 7 8
Print Show(Iif (a@ = @(d@) * b@, " ( B - ", Str(" (_# - ", @(d@))));
Print Show(Iif (a@ = @(d@+a@/2) * b@, " B) ", Str("_#) ", @(d@+a@/2))));
Next
Print ' now move positions 2-n around clockwise
e@ = @(a@/2) ' need to track two temporary variables
f@ = @(a@/2+1)
' top row
For d@ = a@/2 To 3 Step -1
@(d@) = @(d@-1)
Next
' bottom row
For d@ = a@/2+1 To a@-1
@(d@) = @(d@+1)
Next
@(a@) = e@ ' fill in the ones that "jumped" between rows
@(2) = f@
Next
Return
Yabasic
print "Twelve teams"
roundrob(12)
print "Nine teams with byes"
roundrob(9)
end
sub nob$(n,i,byes)
//helper sub to allow byess to be printed intelligently
//dim as string pad
if n > 9 then pad$ = " " else pad$ = "" : fi
if n = i and byes then
return pad$+"B"
else
if i < 10 then return pad$+str$(i) else return str$(i) : fi
fi
end sub
sub roundrob(n)
byes = 0
if mod(n, 2) = 1 then //if there is an odd number of competitors
byes = 1 //make note of this fact
n = n+1 //and treat the tournament as having one more competitor
fi
dim schd(n)
//, r, i, temp1, temp2
for i = 1 to n
schd(i) = i //initial population of the array with numbers 1-n
next i
for r = 1 to n-1
print "Round ", r using "##", ": ";
for i = 1 to n/2 //print the pairings according to the scheme
//1 2 3 4
//5 6 7 8
print "(", nob$(n,schd(i),byes), " -", nob$(n,schd(i+n/2),byes), " ) ";
next i
print
//now move positions 2-n around clockwise
temp1 = schd(n/2)//need to track two temporary variables
temp2 = schd(n/2+1)
for i = n/2 to 3 step -1 //top row
schd(i) = schd(i-1)
next i
for i = n/2+1 to n-1 //bottom row
schd(i) = schd(i+1)
next i
schd(n) = temp1 //fill in the ones that "jumped" between rows
schd(2) = temp2
next r
end sub
C++
#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <stdexcept>
#include <vector>
void round_robin(uint32_t team_count) {
if ( team_count < 2 ) {
throw std::invalid_argument("Number of teams must be greater than 2: " + team_count);
}
std::vector<uint32_t> rotating_list(team_count);
std::iota(rotating_list.begin(), rotating_list.end(), 2);
if ( team_count % 2 == 1 ) {
rotating_list.emplace_back(0);
team_count++;
}
for ( uint32_t round = 1; round < team_count; ++round ) {
std::cout << "Round " << std::setw(2) << round << ":";
std::vector<uint32_t> fixed_list(1, 1);
fixed_list.insert(fixed_list.end(), rotating_list.begin(), rotating_list.end());
for ( uint32_t i = 0; i < team_count / 2; ++i ) {
std::cout << " ( " << std::setw(2) << fixed_list[i]
<< " vs " << std::setw(2) << fixed_list[team_count - 1 - i] << " )";
}
std::cout << std::endl;
std::rotate(rotating_list.rbegin(), rotating_list.rbegin() + 1, rotating_list.rend());
}
}
int main() {
std::cout << "Round robin for 12 players:" << std::endl;
round_robin(12);
std::cout << std::endl << std::endl;
std::cout << "Round robin for 5 players, 0 denotes a bye:" << std::endl;
round_robin(5);
}
- Output:
Round robin for 12 players: Round 1: ( 1 vs 12 ) ( 2 vs 11 ) ( 3 vs 10 ) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) Round 2: ( 1 vs 11 ) ( 13 vs 10 ) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) Round 3: ( 1 vs 10 ) ( 12 vs 9 ) ( 13 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) Round 4: ( 1 vs 9 ) ( 11 vs 8 ) ( 12 vs 7 ) ( 13 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 5: ( 1 vs 8 ) ( 10 vs 7 ) ( 11 vs 6 ) ( 12 vs 5 ) ( 13 vs 4 ) ( 2 vs 3 ) Round 6: ( 1 vs 7 ) ( 9 vs 6 ) ( 10 vs 5 ) ( 11 vs 4 ) ( 12 vs 3 ) ( 13 vs 2 ) Round 7: ( 1 vs 6 ) ( 8 vs 5 ) ( 9 vs 4 ) ( 10 vs 3 ) ( 11 vs 2 ) ( 12 vs 13 ) Round 8: ( 1 vs 5 ) ( 7 vs 4 ) ( 8 vs 3 ) ( 9 vs 2 ) ( 10 vs 13 ) ( 11 vs 12 ) Round 9: ( 1 vs 4 ) ( 6 vs 3 ) ( 7 vs 2 ) ( 8 vs 13 ) ( 9 vs 12 ) ( 10 vs 11 ) Round 10: ( 1 vs 3 ) ( 5 vs 2 ) ( 6 vs 13 ) ( 7 vs 12 ) ( 8 vs 11 ) ( 9 vs 10 ) Round 11: ( 1 vs 2 ) ( 4 vs 13 ) ( 5 vs 12 ) ( 6 vs 11 ) ( 7 vs 10 ) ( 8 vs 9 ) Round robin for 5 players, 0 denotes a bye: Round 1: ( 1 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) Round 3: ( 1 vs 4 ) ( 6 vs 3 ) ( 0 vs 2 ) Round 4: ( 1 vs 3 ) ( 5 vs 2 ) ( 6 vs 0 ) Round 5: ( 1 vs 2 ) ( 4 vs 0 ) ( 5 vs 6 )
C#
using System;
using System.Collections.Generic;
using System.Linq;
public class RoundRobinTournamentSchedule
{
public static void Main(string[] args)
{
Console.WriteLine("Round robin for 12 players:");
RoundRobin(12);
Console.WriteLine("\n");
Console.WriteLine("Round robin for 5 players, 0 denotes a bye:");
RoundRobin(5);
}
private static void RoundRobin(int teamCount)
{
if (teamCount < 2)
{
throw new ArgumentException($"Number of teams must be greater than 2: {teamCount}");
}
List<int> rotatingList = Enumerable.Range(2, teamCount - 1).ToList();
if (teamCount % 2 == 1)
{
rotatingList.Add(0);
teamCount += 1;
}
for (int round = 1; round < teamCount; round++)
{
Console.Write($"Round {round,2}:");
List<int> fixedList = new List<int> { 1 };
fixedList.AddRange(rotatingList);
for (int i = 0; i < teamCount / 2; i++)
{
Console.Write($" ( {fixedList[i],2} vs {fixedList[teamCount - 1 - i],2} )");
}
Console.WriteLine();
Rotate(rotatingList, 1);
}
}
private static void Rotate(List<int> list, int rotationCount)
{
int count = list.Count;
if (count == 0) return;
rotationCount %= count;
if (rotationCount < 0)
{
rotationCount += count;
}
list.Reverse();
list.Reverse(0, rotationCount);
list.Reverse(rotationCount, count - rotationCount);
}
}
- Output:
Round robin for 12 players: Round 1: ( 1 vs 12 ) ( 2 vs 11 ) ( 3 vs 10 ) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) Round 2: ( 1 vs 11 ) ( 12 vs 10 ) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) Round 3: ( 1 vs 10 ) ( 11 vs 9 ) ( 12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) Round 4: ( 1 vs 9 ) ( 10 vs 8 ) ( 11 vs 7 ) ( 12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 5: ( 1 vs 8 ) ( 9 vs 7 ) ( 10 vs 6 ) ( 11 vs 5 ) ( 12 vs 4 ) ( 2 vs 3 ) Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) ( 10 vs 4 ) ( 11 vs 3 ) ( 12 vs 2 ) Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) ( 10 vs 2 ) ( 11 vs 12 ) Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12 ) ( 10 vs 11 ) Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12 ) ( 8 vs 11 ) ( 9 vs 10 ) Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12 ) ( 6 vs 11 ) ( 7 vs 10 ) ( 8 vs 9 ) Round 11: ( 1 vs 2 ) ( 3 vs 12 ) ( 4 vs 11 ) ( 5 vs 10 ) ( 6 vs 9 ) ( 7 vs 8 ) Round robin for 5 players, 0 denotes a bye: Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 )
D
import std.stdio;
import std.range;
import std.array;
import std.conv;
import std.algorithm;
void main() {
12.generatePlayers.generateSchedule.displaySchedule;
}
string[] generatePlayers(int n) {
("\nRound-Robin for "~(n).text~" players:\n").writeln;
//
return (n%2 == 0) ? iota(1, n+1).map!(a => a.text).array : iota(1, n+1).map!(a => a.text).array~"bye";
}
string[] mutate(string[] arr) {
return arr[0]~arr[$-1]~ arr[1..$-1].array;
}
string[][] generateSchedule(string[] players) {
auto nbPlayer = players.length;
string[][]schedule;
schedule ~= players;
for(int i = 1; i <= nbPlayer-2; i++)
{
schedule ~= schedule[$-1].mutate;
}
//
return schedule;
}
void displaySchedule(string[][] schedule) {
auto nbPlayer = schedule[0].length;
foreach(i, row; schedule.array)
{
writef("Round %2s: ", i+1);
for(int k=0; k<nbPlayer/2; k++)
{
writef("(%2s vs %2s)", row[k], row[nbPlayer-(k+1)]);
if (k==(nbPlayer/2)-1) writeln; else " ".write;
}
}
//
writeln;
}
- Output:
Round-Robin for 12 players: Round 1: ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9) ( 5 vs 8) ( 6 vs 7) Round 2: ( 1 vs 11) (12 vs 10) ( 2 vs 9) ( 3 vs 8) ( 4 vs 7) ( 5 vs 6) Round 3: ( 1 vs 10) (11 vs 9) (12 vs 8) ( 2 vs 7) ( 3 vs 6) ( 4 vs 5) Round 4: ( 1 vs 9) (10 vs 8) (11 vs 7) (12 vs 6) ( 2 vs 5) ( 3 vs 4) Round 5: ( 1 vs 8) ( 9 vs 7) (10 vs 6) (11 vs 5) (12 vs 4) ( 2 vs 3) Round 6: ( 1 vs 7) ( 8 vs 6) ( 9 vs 5) (10 vs 4) (11 vs 3) (12 vs 2) Round 7: ( 1 vs 6) ( 7 vs 5) ( 8 vs 4) ( 9 vs 3) (10 vs 2) (11 vs 12) Round 8: ( 1 vs 5) ( 6 vs 4) ( 7 vs 3) ( 8 vs 2) ( 9 vs 12) (10 vs 11) Round 9: ( 1 vs 4) ( 5 vs 3) ( 6 vs 2) ( 7 vs 12) ( 8 vs 11) ( 9 vs 10) Round 10: ( 1 vs 3) ( 4 vs 2) ( 5 vs 12) ( 6 vs 11) ( 7 vs 10) ( 8 vs 9) Round 11: ( 1 vs 2) ( 3 vs 12) ( 4 vs 11) ( 5 vs 10) ( 6 vs 9) ( 7 vs 8)
EasyLang
proc roundrobin n . .
numfmt 0 2
print n & " players"
for i to n
arr[] &= i
.
if n mod 2 = 1
n += 1
arr[] &= 0
.
for i = 1 to n - 1
print ""
write "round " & i & ": "
for j = 1 to n / 2
write arr[j] & " "
.
print ""
write " "
for j = n downto n / 2 + 1
write arr[j] & " "
.
print ""
h = arr[n]
for j = n downto 3
arr[j] = arr[j - 1]
.
arr[2] = h
.
.
roundrobin 12
Go
package main
import "fmt"
func rotate(lst []int) {
len := len(lst)
last := lst[len-1]
for i := len - 1; i >= 1; i-- {
lst[i] = lst[i-1]
}
lst[0] = last
}
func roundRobin(n int) {
lst := make([]int, n-1)
for i := 0; i < len(lst); i++ {
lst[i] = i + 2
}
if n%2 == 1 {
lst = append(lst, 0) // 0 denotes a bye
n++
}
for r := 1; r < n; r++ {
fmt.Printf("Round %2d", r)
lst2 := append([]int{1}, lst...)
for i := 0; i < n/2; i++ {
fmt.Printf(" (%2d vs %-2d)", lst2[i], lst2[n-1-i])
}
fmt.Println()
rotate(lst)
}
}
func main() {
fmt.Println("Round robin for 12 players:\n")
roundRobin(12)
fmt.Println("\n\nRound robin for 5 players (0 denotes a bye) :\n")
roundRobin(5)
}
- Output:
Same as Wren example.
J
Implementation (using the wikipedia circle method):
circ=: {{
if. 1=2|y do.
assert. 1<y
<:(#~ [: */"1 *)"2 circ y+1
else.
ids=. i.y
(-:y) ({.,.|.@}.)"_1] 0,.(}:ids)|."0 1}.ids
end.
}}
Task example:
rplc&'j:'"1":j./"1>:circ 12
1:12 2:11 3:10 4:9 5:8 6:7
1:2 3:12 4:11 5:10 6:9 7:8
1:3 4:2 5:12 6:11 7:10 8:9
1:4 5:3 6:2 7:12 8:11 9:10
1:5 6:4 7:3 8:2 9:12 10:11
1:6 7:5 8:4 9:3 10:2 11:12
1:7 8:6 9:5 10:4 11:3 12:2
1:8 9:7 10:6 11:5 12:4 2:3
1:9 10:8 11:7 12:6 2:5 3:4
1:10 11:9 12:8 2:7 3:6 4:5
1:11 12:10 2:9 3:8 4:7 5:6
(Here, circ
uses index values which start at zero, so we need to add 1 to every index. Then we form the id pairs as complex numbers and replace the 'j' used to separate real from imaginary in their character representation with ':' for a hopefully compact and easy-to-read display.)
((Note that we could have instead centered each id pair on the ':' with only slightly more work. But it's not clear that that results in a more pleasing display.)):
,/"2(' ',_2&{.@[,':',2&{.@])&":/"1>:circ 12
1:12 2:11 3:10 4:9 5:8 6:7
1:2 3:12 4:11 5:10 6:9 7:8
1:3 4:2 5:12 6:11 7:10 8:9
1:4 5:3 6:2 7:12 8:11 9:10
1:5 6:4 7:3 8:2 9:12 10:11
1:6 7:5 8:4 9:3 10:2 11:12
1:7 8:6 9:5 10:4 11:3 12:2
1:8 9:7 10:6 11:5 12:4 2:3
1:9 10:8 11:7 12:6 2:5 3:4
1:10 11:9 12:8 2:7 3:6 4:5
1:11 12:10 2:9 3:8 4:7 5:6
Java
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public final class RoundRobinTournamentSchedule {
public static void main(String[] args) {
System.out.println("Round robin for 12 players:");
roundRobin(12);
System.out.println(System.lineSeparator());
System.out.println("Round robin for 5 players, 0 denotes a bye:");
roundRobin(5);
}
private static void roundRobin(int teamCount) {
if ( teamCount < 2 ) {
throw new IllegalArgumentException("Number of teams must be greater than 2: " + teamCount);
}
List<Integer> rotatingList = IntStream.rangeClosed(2, teamCount).boxed().collect(Collectors.toList());
if ( teamCount % 2 == 1 ) {
rotatingList.add(0);
teamCount += 1;
}
for ( int round = 1; round < teamCount; round++ ) {
System.out.print(String.format("%s%2d%s", "Round ", round, ":"));
List<Integer> fixedList = IntStream.rangeClosed(1, 1).boxed().collect(Collectors.toList());
fixedList.addAll(rotatingList);
for ( int i = 0; i < teamCount / 2; i++ ) {
System.out.print(String.format("%s%2d%s%2d%s",
" ( ", fixedList.get(i), " vs ", fixedList.get(teamCount - 1 - i), " )"));
}
System.out.println();
Collections.rotate(rotatingList, +1);
}
}
}
- Output:
Round robin for 12 players: Round 1: ( 1 vs 12 ) ( 2 vs 11 ) ( 3 vs 10 ) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) Round 2: ( 1 vs 11 ) ( 12 vs 10 ) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) Round 3: ( 1 vs 10 ) ( 11 vs 9 ) ( 12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) Round 4: ( 1 vs 9 ) ( 10 vs 8 ) ( 11 vs 7 ) ( 12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 5: ( 1 vs 8 ) ( 9 vs 7 ) ( 10 vs 6 ) ( 11 vs 5 ) ( 12 vs 4 ) ( 2 vs 3 ) Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) ( 10 vs 4 ) ( 11 vs 3 ) ( 12 vs 2 ) Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) ( 10 vs 2 ) ( 11 vs 12 ) Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12 ) ( 10 vs 11 ) Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12 ) ( 8 vs 11 ) ( 9 vs 10 ) Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12 ) ( 6 vs 11 ) ( 7 vs 10 ) ( 8 vs 9 ) Round 11: ( 1 vs 2 ) ( 3 vs 12 ) ( 4 vs 11 ) ( 5 vs 10 ) ( 6 vs 9 ) ( 7 vs 8 ) Round robin for 5 players, 0 denotes a bye: Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 )
jq
Works with gojq, the Go implementation of jq
Adapted from Wren
def lpad($len): tostring | ($len - length) as $l | (" " * $l) + .;
def rotate: .[-1:] + .[:-1];
def roundRobin($n):
{$n, lst: [range(2; $n+1)]}
| if $n % 2 == 1
then .lst += [0] # 0 denotes a bye
| .n += 1
end
| foreach range(1; .n) as $r (.;
.emit = "Round \($r|lpad(3)): "
| ([1] + .lst) as $lst2
| reduce range(0; .n/2) as $i (.;
.emit += " (\($lst2[$i]|lpad(2)) vs \($lst2[.n - 1 - $i]|lpad(2)))")
| .lst |= rotate )
| .emit ;
"Round robin for 12 players:",
roundRobin(12),
"\n\nRound robin for 5 players (0 denotes a bye):\n",
roundRobin(5)
- Output:
Essentially the same as for Wren.
Julia
""" https://rosettacode.org/mw/index.php?title=Round-robin_tournament_schedule """
function schurig(N, verbose = true)
""" Taken from https://en.wikipedia.org/wiki/Round-robin_tournament
#Original_construction_of_pairing_tables_by_Richard_Schurig_(1886) """
nrows = isodd(N) ? N : N - 1
ncols = (N + 1) ÷ 2
players = mod1.(reshape(collect(1:nrows*ncols), ncols, nrows)', nrows)
opponents = zero(players)
table = [(0, 0) for _ in 1:nrows, _ in 1:ncols]
for i in 1:nrows
oldrow = i == nrows ? 1 : i + 1
verbose && print("\n", rpad("Round $i:", 10))
for j in 1:ncols
oldcol = ncols - j + 1
opponents[i, j] = players[oldrow, oldcol]
j == 1 && (opponents[i, j] = iseven(N) ? N : 0)
table[i, j] = (sort([players[i, j], opponents[i, j]])...,)
if verbose
s1, s2 = string.(table[i, j])
print(rpad("($(s1 == "0" ? "Bye" : s1) - $s2)", 10))
end
end
end
return table
end
print("Schurig table for round robin with 12 players:")
schurig(12)
print("\n\nSchurig table for round robin with 7 players:")
schurig(7)
- Output:
Schurig table for round robin with 12 players: Round 1: (1 - 12) (2 - 11) (3 - 10) (4 - 9) (5 - 8) (6 - 7) Round 2: (7 - 12) (6 - 8) (5 - 9) (4 - 10) (3 - 11) (1 - 2) Round 3: (2 - 12) (1 - 3) (4 - 11) (5 - 10) (6 - 9) (7 - 8) Round 4: (8 - 12) (7 - 9) (6 - 10) (5 - 11) (1 - 4) (2 - 3) Round 5: (3 - 12) (2 - 4) (1 - 5) (6 - 11) (7 - 10) (8 - 9) Round 6: (9 - 12) (8 - 10) (7 - 11) (1 - 6) (2 - 5) (3 - 4) Round 7: (4 - 12) (3 - 5) (2 - 6) (1 - 7) (8 - 11) (9 - 10) Round 8: (10 - 12) (9 - 11) (1 - 8) (2 - 7) (3 - 6) (4 - 5) Round 9: (5 - 12) (4 - 6) (3 - 7) (2 - 8) (1 - 9) (10 - 11) Round 10: (11 - 12) (1 - 10) (2 - 9) (3 - 8) (4 - 7) (5 - 6) Round 11: (6 - 12) (5 - 7) (4 - 8) (3 - 9) (2 - 10) (1 - 11) Schurig table for round robin with 7 players: Round 1: (Bye - 1) (2 - 7) (3 - 6) (4 - 5) Round 2: (Bye - 5) (4 - 6) (3 - 7) (1 - 2) Round 3: (Bye - 2) (1 - 3) (4 - 7) (5 - 6) Round 4: (Bye - 6) (5 - 7) (1 - 4) (2 - 3) Round 5: (Bye - 3) (2 - 4) (1 - 5) (6 - 7) Round 6: (Bye - 7) (1 - 6) (2 - 5) (3 - 4) Round 7: (Bye - 4) (3 - 5) (2 - 6) (1 - 7)
Nim
import std/[algorithm, sequtils, strformat]
proc roundRobin(n: Positive) =
assert n >= 2
var n = n
var list1 = toSeq(2..n)
if n mod 2 == 1:
list1.add 0 # 0 denotes a "bye".
inc n
for r in 1..<n:
stdout.write &"Round {r:2}:"
let list2 = 1 & list1
for i in 0..<(n div 2):
stdout.write &" ({list2[i]:>2} vs {list2[n - i - 1]:<2})"
echo()
list1.rotateLeft(-1)
echo "Round robin for 12 players:\n"
roundRobin(12)
echo "\n\nRound robin for 5 players (0 denotes a bye) :\n"
roundRobin(5)
- Output:
Round robin for 12 players: Round 1: ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) Round 2: ( 1 vs 11) (12 vs 10) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) Round 3: ( 1 vs 10) (11 vs 9 ) (12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) Round 4: ( 1 vs 9 ) (10 vs 8 ) (11 vs 7 ) (12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 5: ( 1 vs 8 ) ( 9 vs 7 ) (10 vs 6 ) (11 vs 5 ) (12 vs 4 ) ( 2 vs 3 ) Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) (10 vs 4 ) (11 vs 3 ) (12 vs 2 ) Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) (10 vs 2 ) (11 vs 12) Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12) (10 vs 11) Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12) ( 8 vs 11) ( 9 vs 10) Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12) ( 6 vs 11) ( 7 vs 10) ( 8 vs 9 ) Round 11: ( 1 vs 2 ) ( 3 vs 12) ( 4 vs 11) ( 5 vs 10) ( 6 vs 9 ) ( 7 vs 8 ) Round robin for 5 players (0 denotes a bye) : Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 )
Pascal
A console program in Free Pascal. Uses the circle method, but not exactly as in Wikipedia: the fixed player is the dummy, if present, otherwise the last; and the rotation is anticlockwise.
program RoundRobin;
(*
Rosetta Code: write list of matches in a round robin tournament.
Command line:
RoundRobin number_of_players
*)
{$mode objfpc}{$H+}
uses SysUtils;
var
nrPlayers, round : integer;
n, m, c, j, k : integer;
a : array of integer;
// Write the matches in a round, formatting nicely
procedure WriteRound();
var
t, u : integer;
begin
Write( 'Round', round:3, ': ');
u := 0;
for t := 0 to m - 2 do begin
Write( '(', a[u]:2); inc(u);
Write( ' v', a[u]:3, ') '); inc(u);
end;
Write( '(', a[u]:2); // u = n - 2
if c > 0 then
WriteLn( ' v', c:3, ')')
else
WriteLn( ' bye)');
end;
begin
if ParamCount < 1 then begin
WriteLn( 'Number of players is required');
exit;
end;
nrPlayers := SysUtils.StrToIntDef( ParamStr(1), -1);
// if string can't be converted, nrPlayers := -1
if (nrPlayers < 2) then begin
WriteLn( 'Invalid number of players');
exit;
end;
WriteLn( 'Round robin with ', nrPlayers, ' players');
m := (nrPlayers + 1) div 2;
n := 2*m;
if Odd( nrPlayers) then c := 0 // dummy player, opponent gets a bye
else c := n; // genuine player
SetLength( a, n);
k := 0;
for j := 0 to m - 2 do begin
a[k] := m - j; inc(k);
a[k] := m + 1 + j; inc(k);
end;
a[k] := 1;
a[n - 1] := c; // a[n - 1] stays = c throughout
round := 1;
WriteRound();
for round := 2 to n - 1 do begin
for j := 0 to n - 2 do begin // increment all entries except a[n - 1]
inc(a[j]);
if a[j] = n then a[j] := 1; // wrap round if necessary
end;
WriteRound();
end;
end.
- Output:
Round robin with 12 players Round 1: ( 6 v 7) ( 5 v 8) ( 4 v 9) ( 3 v 10) ( 2 v 11) ( 1 v 12) Round 2: ( 7 v 8) ( 6 v 9) ( 5 v 10) ( 4 v 11) ( 3 v 1) ( 2 v 12) Round 3: ( 8 v 9) ( 7 v 10) ( 6 v 11) ( 5 v 1) ( 4 v 2) ( 3 v 12) Round 4: ( 9 v 10) ( 8 v 11) ( 7 v 1) ( 6 v 2) ( 5 v 3) ( 4 v 12) Round 5: (10 v 11) ( 9 v 1) ( 8 v 2) ( 7 v 3) ( 6 v 4) ( 5 v 12) Round 6: (11 v 1) (10 v 2) ( 9 v 3) ( 8 v 4) ( 7 v 5) ( 6 v 12) Round 7: ( 1 v 2) (11 v 3) (10 v 4) ( 9 v 5) ( 8 v 6) ( 7 v 12) Round 8: ( 2 v 3) ( 1 v 4) (11 v 5) (10 v 6) ( 9 v 7) ( 8 v 12) Round 9: ( 3 v 4) ( 2 v 5) ( 1 v 6) (11 v 7) (10 v 8) ( 9 v 12) Round 10: ( 4 v 5) ( 3 v 6) ( 2 v 7) ( 1 v 8) (11 v 9) (10 v 12) Round 11: ( 5 v 6) ( 4 v 7) ( 3 v 8) ( 2 v 9) ( 1 v 10) (11 v 12) Round robin with 9 players Round 1: ( 5 v 6) ( 4 v 7) ( 3 v 8) ( 2 v 9) ( 1 bye) Round 2: ( 6 v 7) ( 5 v 8) ( 4 v 9) ( 3 v 1) ( 2 bye) Round 3: ( 7 v 8) ( 6 v 9) ( 5 v 1) ( 4 v 2) ( 3 bye) Round 4: ( 8 v 9) ( 7 v 1) ( 6 v 2) ( 5 v 3) ( 4 bye) Round 5: ( 9 v 1) ( 8 v 2) ( 7 v 3) ( 6 v 4) ( 5 bye) Round 6: ( 1 v 2) ( 9 v 3) ( 8 v 4) ( 7 v 5) ( 6 bye) Round 7: ( 2 v 3) ( 1 v 4) ( 9 v 5) ( 8 v 6) ( 7 bye) Round 8: ( 3 v 4) ( 2 v 5) ( 1 v 6) ( 9 v 7) ( 8 bye) Round 9: ( 4 v 5) ( 3 v 6) ( 2 v 7) ( 1 v 8) ( 9 bye)
Perl
Even
#!/usr/bin/perl
use strict; # https://rosettacode.org/wiki/Round-robin_tournament_schedule
use warnings;
my $n = 12;
my @teams = 1 .. $n;
for (1 .. $n-1)
{
@teams[0,$n-1,1..$n-2] = @teams;
printf 'Round %2d:' . '%4d vs %2d'x($n/2) . "\n", $_, @teams[ map { $_, $n-1-$_} 0..($n/2)-1 ];
}
- Output:
Round 1: 1 vs 2 3 vs 12 4 vs 11 5 vs 10 6 vs 9 7 vs 8 Round 2: 1 vs 3 4 vs 2 5 vs 12 6 vs 11 7 vs 10 8 vs 9 Round 3: 1 vs 4 5 vs 3 6 vs 2 7 vs 12 8 vs 11 9 vs 10 Round 4: 1 vs 5 6 vs 4 7 vs 3 8 vs 2 9 vs 12 10 vs 11 Round 5: 1 vs 6 7 vs 5 8 vs 4 9 vs 3 10 vs 2 11 vs 12 Round 6: 1 vs 7 8 vs 6 9 vs 5 10 vs 4 11 vs 3 12 vs 2 Round 7: 1 vs 8 9 vs 7 10 vs 6 11 vs 5 12 vs 4 2 vs 3 Round 8: 1 vs 9 10 vs 8 11 vs 7 12 vs 6 2 vs 5 3 vs 4 Round 9: 1 vs 10 11 vs 9 12 vs 8 2 vs 7 3 vs 6 4 vs 5 Round 10: 1 vs 11 12 vs 10 2 vs 9 3 vs 8 4 vs 7 5 vs 6 Round 11: 1 vs 12 2 vs 11 3 vs 10 4 vs 9 5 vs 8 6 vs 7
Even and Odd
use strict;
use warnings;
use feature 'say';
use List::AllUtils <pairwise all>;
sub round_robin {
my($n) = @_;
my($round,@pairings);
my @players = (1,0)[$n%2] .. $n;
my $half = +@players / 2;
while () {
my @a = @players[ 0 .. $half-1];
my @b = reverse @players[$half .. $#players];
push @pairings, sprintf "Round %2d: %s\n", ++$round, join ' ', pairwise { sprintf "%3d vs %2d", $a, $b } @a, @b;
push @players, splice @players, 1, @players-2;
last if all { $players[$_-1] < $players[$_] } 1..$#players;
}
@pairings
}
say join '', round_robin 12;
say '';
say join '', map { s/0 vs /Bye: /r } round_robin 7;
- Output:
Round 1: 1 vs 12 2 vs 11 3 vs 10 4 vs 9 5 vs 8 6 vs 7 Round 2: 1 vs 11 12 vs 10 2 vs 9 3 vs 8 4 vs 7 5 vs 6 Round 3: 1 vs 10 11 vs 9 12 vs 8 2 vs 7 3 vs 6 4 vs 5 Round 4: 1 vs 9 10 vs 8 11 vs 7 12 vs 6 2 vs 5 3 vs 4 Round 5: 1 vs 8 9 vs 7 10 vs 6 11 vs 5 12 vs 4 2 vs 3 Round 6: 1 vs 7 8 vs 6 9 vs 5 10 vs 4 11 vs 3 12 vs 2 Round 7: 1 vs 6 7 vs 5 8 vs 4 9 vs 3 10 vs 2 11 vs 12 Round 8: 1 vs 5 6 vs 4 7 vs 3 8 vs 2 9 vs 12 10 vs 11 Round 9: 1 vs 4 5 vs 3 6 vs 2 7 vs 12 8 vs 11 9 vs 10 Round 10: 1 vs 3 4 vs 2 5 vs 12 6 vs 11 7 vs 10 8 vs 9 Round 11: 1 vs 2 3 vs 12 4 vs 11 5 vs 10 6 vs 9 7 vs 8 Round 1: Bye: 7 1 vs 6 2 vs 5 3 vs 4 Round 2: Bye: 6 7 vs 5 1 vs 4 2 vs 3 Round 3: Bye: 5 6 vs 4 7 vs 3 1 vs 2 Round 4: Bye: 4 5 vs 3 6 vs 2 7 vs 1 Round 5: Bye: 3 4 vs 2 5 vs 1 6 vs 7 Round 6: Bye: 2 3 vs 1 4 vs 7 5 vs 6 Round 7: Bye: 1 2 vs 7 3 vs 6 4 vs 5
Phix
Based on the circle with rotor diagrams on the wikipedia page, and implements home/away.
with javascript_semantics function round_robin(integer n) -- -- As per the wikipedia page, we do something like this: -- -- even(n), say 6: in round 1 we have 6 & 1,2,3,4,5 -> {{6,1},{2,5},{3,4}}, -- 2 2,3,4,5,1 -> {{6,2},{3,1},{4,5}}, -- 3 3,4,5,1,2 -> {{6,3},{4,2},{5,1}}, -- 4 4,5,1,2,3 -> {{6,4},{5,3},{1,2}}, -- 5 5,1,2,3,4 -> {{6,5},{1,4},{2,3}} -- -- for an odd(n), say 5, simply replace all the 6 above with 0 (a bye). -- -- As per the wikipedia diagram, we pick a rotor (6/0) and arrange the rest -- in a circle, and as it rotates around the circle we play it against that -- one then pick off second/last, third/last-but-one, and so forth from the -- perspective of the rotor. There must obviously be an odd number of teams -- in the circle itself, otherwise pairing-offs won't meet in the middle. -- -- However, rather than physically rotate the {1,2,3,4,5}, we'll just say -- that anything past 5 starts from 1 again (the -= n below), and use the -- shorthand of l [===length(result)] as our starting position/offset. -- -- Not shown above, but we'll also use even/odd rules for home/away matches. -- integer rotor = iff(even(n)?n:0), l = 0 -- length(result), shorthand n -= even(n) -- (circle must be odd) sequence result = {} for rownd=1 to n do -- (since "round" is a builtin) sequence games = {iff(even(rownd) or rotor=0?{rownd,rotor}:{rotor,rownd})} integer opponent = n -- pair rest off from last inwards, for m=2 to (n+1)/2 do -- such that m plays current opponent integer rom = m+l, -- all shifted by rop = opponent+l -- l as an offset if rom>n then rom -= n end if if rop>n then rop -= n end if games &= iff(odd(m)?{{rom,rop}}:{{rop,rom}}) opponent -= 1 end for result = append(result,games) l += 1 -- (obviously "l = length(result)" works fine here too) end for return result end function function vs(sequence pair) -- (display helper) return sprintf(iff(pair[2]=0?"%2d bye ":"%2d vs %-2d"),pair) end function for test=12 to 3 by -9 do sequence res = round_robin(test) printf(1,"\nFor %d teams:\n",test) for r=1 to length(res) do printf(1,"Round %2d: %s\n",{r,join(apply(res[r],vs))}) end for end for
- Output:
For 12 teams: Round 1: 12 vs 1 11 vs 2 3 vs 10 9 vs 4 5 vs 8 7 vs 6 Round 2: 2 vs 12 1 vs 3 4 vs 11 10 vs 5 6 vs 9 8 vs 7 Round 3: 12 vs 3 2 vs 4 5 vs 1 11 vs 6 7 vs 10 9 vs 8 Round 4: 4 vs 12 3 vs 5 6 vs 2 1 vs 7 8 vs 11 10 vs 9 Round 5: 12 vs 5 4 vs 6 7 vs 3 2 vs 8 9 vs 1 11 vs 10 Round 6: 6 vs 12 5 vs 7 8 vs 4 3 vs 9 10 vs 2 1 vs 11 Round 7: 12 vs 7 6 vs 8 9 vs 5 4 vs 10 11 vs 3 2 vs 1 Round 8: 8 vs 12 7 vs 9 10 vs 6 5 vs 11 1 vs 4 3 vs 2 Round 9: 12 vs 9 8 vs 10 11 vs 7 6 vs 1 2 vs 5 4 vs 3 Round 10: 10 vs 12 9 vs 11 1 vs 8 7 vs 2 3 vs 6 5 vs 4 Round 11: 12 vs 11 10 vs 1 2 vs 9 8 vs 3 4 vs 7 6 vs 5 For 3 teams: Round 1: 1 bye 3 vs 2 Round 2: 2 bye 1 vs 3 Round 3: 3 bye 2 vs 1
While I "optimised away" the need for a physical rotate, obviously not because I was concerned with performance but more in the hope of creating shorter and more elegant code, in the end it made little difference. Should it be more to your taste, you can remove "l" and replace the inner loop above with:
sequence circle = tagset(n) for rownd=1 to n do -- (since "round" is a bultin) integer r = circle[1] sequence games = {iff(even(rownd) or rotor=0?{r,rotor}:{rotor,r})} integer ldx = 2, rdx = n while ldx<rdx do integer teama = circle[ldx], teamb = circle[rdx] games &= {iff(odd(ldx)?{teama,teamb},{teamb,teama})} ldx += 1 rdx -= 1 end while result = append(result,games) circle = circle[2..$]&circle[1] -- (physically rotate it) end for
Picat
Constraint modelling
import sat.
main =>
nolog,
N = 12,
tournament_cp(N, NumRounds,NumPairs,_,X,Bye),
print_tournament(X,NumRounds,NumPairs,Bye),
nl.
tournament_cp(N, NumRounds,NumPairs,Extras, X,Bye) =>
% Adjust for odd number of players.
% The bye (Dummy) player is N+1.
if N mod 2 == 1 then
N := N + 1,
Bye = N
end,
NumRounds = N-1,
NumPairs = N div 2,
X = new_array(NumRounds,NumPairs,2),
X :: 1..N,
% ensure that all players play each other
foreach(P1 in 1..N, P2 in P1+1..N)
sum([X[Round,P,1] #= P1 #/\ X[Round,P,2] #= P2 : Round in 1..NumRounds, P in 1..NumPairs]) #= 1
end,
foreach(Round in 1..NumRounds)
all_different([X[Round,I,J] : I in 1..NumPairs, J in 1..2]),
% symmetry breaking
% - all first players in increasing order
increasing_strict([X[Round,I,1] : I in 1..NumPairs]),
% - player 1 < player 2
foreach(P in 1..NumPairs)
X[Round,P,1] #< X[Round,P,2]
end
end,
if Extras != [] then
foreach([P1,P2,Round] in Extras)
sum([X[Round,P,1] #= P1 #/\ X[Round,P,2] #= P2 : P in 1..NumPairs]) #= 1
end
end,
solve($[ff,split],X).
print_tournament(X,NumRounds,NumPairs,Bye) =>
N = X[1].len,
foreach(Round in 1..NumRounds)
printf("Round %2d: ", Round),
if N > 10 then nl end,
foreach(P in 1..NumPairs)
P2Val = X[Round,P,2],
if var(Bye) ; P2Val != Bye then
printf("(%2w vs %2w) ",X[Round,P,1],P2Val),
if N > 10 then nl end
end
end,
nl
end,
nl.
- Output:
Round 1: ( 1 vs 11) ( 2 vs 5) ( 3 vs 6) ( 4 vs 12) ( 7 vs 9) ( 8 vs 10) Round 2: ( 1 vs 5) ( 2 vs 4) ( 3 vs 10) ( 6 vs 7) ( 8 vs 9) (11 vs 12) Round 3: ( 1 vs 6) ( 2 vs 8) ( 3 vs 5) ( 4 vs 11) ( 7 vs 10) ( 9 vs 12) Round 4: ( 1 vs 12) ( 2 vs 11) ( 3 vs 7) ( 4 vs 6) ( 5 vs 8) ( 9 vs 10) Round 5: ( 1 vs 9) ( 2 vs 6) ( 3 vs 12) ( 4 vs 5) ( 7 vs 8) (10 vs 11) Round 6: ( 1 vs 4) ( 2 vs 3) ( 5 vs 7) ( 6 vs 10) ( 8 vs 12) ( 9 vs 11) Round 7: ( 1 vs 2) ( 3 vs 4) ( 5 vs 10) ( 6 vs 9) ( 7 vs 12) ( 8 vs 11) Round 8: ( 1 vs 3) ( 2 vs 12) ( 4 vs 10) ( 5 vs 9) ( 6 vs 8) ( 7 vs 11) Round 9: ( 1 vs 10) ( 2 vs 7) ( 3 vs 8) ( 4 vs 9) ( 5 vs 11) ( 6 vs 12) Round 10: ( 1 vs 8) ( 2 vs 10) ( 3 vs 9) ( 4 vs 7) ( 5 vs 12) ( 6 vs 11) Round 11: ( 1 vs 7) ( 2 vs 9) ( 3 vs 11) ( 4 vs 8) ( 5 vs 6) (10 vs 12)
Constraint model with extra constraints
The constraint model is slower than the algorithmic approach for larger number of players. The advantage of a constraint model is that it is quite easy to add extra constraint, such that some players must play in a certain round (e.g. for availability reasons etc).
Here are some extra constraints:
- 1 vs 2 must be played the third round
- 5 vs 9 must be played in the 7th round
- 2 vs 3 must be played in the last round
- 7 vs 12 must be played in the last round
main =>
nolog,
N = 12,
Extras = [[1,2,3],
[5,9,7],
[2,3,N-1],
[7,12,N-1]],
tournament_cp(N, NumRounds,NumPairs,Extras,X,Bye),
print_tournament(X,NumRounds,NumPairs,Bye).
- Output:
Round 1: ( 1 vs 11) ( 2 vs 4) ( 3 vs 12) ( 5 vs 8) ( 6 vs 9) ( 7 vs 10) Round 2: ( 1 vs 12) ( 2 vs 11) ( 3 vs 9) ( 4 vs 7) ( 5 vs 10) ( 6 vs 8) Round 3: ( 1 vs 2) ( 3 vs 10) ( 4 vs 12) ( 5 vs 11) ( 6 vs 7) ( 8 vs 9) Round 4: ( 1 vs 4) ( 2 vs 6) ( 3 vs 11) ( 5 vs 12) ( 7 vs 8) ( 9 vs 10) Round 5: ( 1 vs 10) ( 2 vs 7) ( 3 vs 5) ( 4 vs 6) ( 8 vs 12) ( 9 vs 11) Round 6: ( 1 vs 6) ( 2 vs 5) ( 3 vs 4) ( 7 vs 9) ( 8 vs 11) (10 vs 12) Round 7: ( 1 vs 3) ( 2 vs 12) ( 4 vs 8) ( 5 vs 9) ( 6 vs 10) ( 7 vs 11) Round 8: ( 1 vs 7) ( 2 vs 8) ( 3 vs 6) ( 4 vs 5) ( 9 vs 12) (10 vs 11) Round 9: ( 1 vs 8) ( 2 vs 9) ( 3 vs 7) ( 4 vs 10) ( 5 vs 6) (11 vs 12) Round 10: ( 1 vs 9) ( 2 vs 10) ( 3 vs 8) ( 4 vs 11) ( 5 vs 7) ( 6 vs 12) Round 11: ( 1 vs 5) ( 2 vs 3) ( 4 vs 9) ( 6 vs 11) ( 7 vs 12) ( 8 vs 10)
For this small tournament it took about the same time with and without these extra constraints (0.08s).
Number of solutions
Here are the number of different solutions for N = [2,4,6,8] with the symmetry constraints (but without the extra round constraints). The number of odd N players is the same as the number of N-1 players.
Here the cp solver is used since it's faster than the sat solver for generating all solutions.
import cp.
main =>
foreach(N in 2..2..8)
Count = count_all(tournament_cp(N, _NumRounds,_NumPairs,_Extras,_X,_Bye)),
println(N=Count)
end.
- Output:
2 = 1 4 = 6 6 = 720 8 = 31449600
This seems to be related to the OEIS sequence "A036981: (2n+1) X (2n+1) symmetric matrices each of whose rows is a permutation of 1..(2n+1)". The next term (for N=10) would be 444733651353600 which takes too long to check.
Python
Original method by R. Schurig
# round_robin.py by Xing216
from copy import deepcopy
def shift_up(myList):
myLen = len(myList)
return [myList[i % myLen] for i in range(1, 1 + myLen)]
def scheduler(competitors):
"""Uses the original method by Richard Schurig"""
if competitors % 2 == 1:
n = competitors + 1
horizontal_rows = n - 1
else:
n = competitors
horizontal_rows = n
vertical_rows = n // 2
table = [[[] for _ in range(vertical_rows)] for _ in range(horizontal_rows)]
competitor = 1
for i, row in enumerate(table):
for col in table[i]:
if competitor == competitors:
col.append(competitor)
competitor = 1
else:
col.append(competitor)
competitor += 1
table2 = deepcopy(table)
table2 = shift_up(table2)
for row in table2: row.reverse()
for i, row in enumerate(table):
for j, col in enumerate(table[i]):
col.append(table2[i][j][0])
return table
def print_table(table):
for i, round in enumerate(table):
print(f"Round {(i + 1):2}", end=": ")
for match in round:
print(f"{match[0]:2}-{match[1]:<2}", end=" ")
print()
print_table(scheduler(12))
- Output:
Round 1: 1-12 2-11 3-10 4-9 5-8 6-7 Round 2: 7-6 8-5 9-4 10-3 11-2 12-1 Round 3: 1-12 2-11 3-10 4-9 5-8 6-7 Round 4: 7-6 8-5 9-4 10-3 11-2 12-1 Round 5: 1-12 2-11 3-10 4-9 5-8 6-7 Round 6: 7-6 8-5 9-4 10-3 11-2 12-1 Round 7: 1-12 2-11 3-10 4-9 5-8 6-7 Round 8: 7-6 8-5 9-4 10-3 11-2 12-1 Round 9: 1-12 2-11 3-10 4-9 5-8 6-7 Round 10: 7-6 8-5 9-4 10-3 11-2 12-1 Round 11: 1-12 2-11 3-10 4-9 5-8 6-7 Round 12: 7-6 8-5 9-4 10-3 11-2 12-1
Berger Tables
# berger_table.py by Xing216
def scheduler(competitors):
if competitors & 1:
competitors += 1
last = competitors
half = competitors // 2
rounds = last - 1
tables = [list() for i in range(rounds)]
for i in range(1, last):
row = i - 1
tables[row] = [list() * half]
tables[row][0] = [0, 0]
if i & 1:
tables[row][0][1] = last
opponent = (i + 1) // 2
tables[row][0][0] = opponent
else:
tables[row][0][0] = last
opponent = half + i // 2
tables[row][0][1] = opponent
for _ in range(1, half):
next_opponent = opponent + 1 if opponent < last - 1 else 1
tables[row].append([next_opponent, 0])
opponent = next_opponent
last_guest = 1
for i in reversed(range(1, last)):
row = i - 1
for j in reversed(range(0, half)):
opponent = last_guest
if j > 0:
tables[row][j][1] = opponent
last_guest = opponent + 1 if opponent < last - 1 else 1
return tables
def print_table(table):
for i, round in enumerate(table):
print(f"Round {(i + 1):2}", end=": ")
for match in round:
print(f"{match[0]:2}-{match[1]:<2}", end=" ")
print()
print_table(scheduler(12))
- Output:
Round 1: 1-12 2-11 3-10 4-9 5-8 6-7 Round 2: 12-7 8-6 9-5 10-4 11-3 1-2 Round 3: 2-12 3-1 4-11 5-10 6-9 7-8 Round 4: 12-8 9-7 10-6 11-5 1-4 2-3 Round 5: 3-12 4-2 5-1 6-11 7-10 8-9 Round 6: 12-9 10-8 11-7 1-6 2-5 3-4 Round 7: 4-12 5-3 6-2 7-1 8-11 9-10 Round 8: 12-10 11-9 1-8 2-7 3-6 4-5 Round 9: 5-12 6-4 7-3 8-2 9-1 10-11 Round 10: 12-11 1-10 2-9 3-8 4-7 5-6 Round 11: 6-12 7-5 8-4 9-3 10-2 11-1
Quackery
[ stack ] is participants ( --> s )
[ dup 10 < if sp echo ] is recho ( n --> )
[ dup participants share
> iff
[ drop say " bye " ]
done
say " vs "
dup echo 10 < if sp ] is lecho ( n --> )
[ dup participants put
dup 1 & +
[] over 1 - times
[ i 1+ join ]
over 1 - times
[ say "Round "
i^ 1+ recho
say ": "
over dip
[ 2dup join ]
times
[ i i^ < iff
conclude done
dup i peek recho
dup i^ peek lecho
say " " ]
drop cr
over 2 / 1+
split swap join ]
2drop participants release ] is schedule ( n --> )
say "12 participants:" cr
12 schedule
cr
say "5 participants:" cr
5 schedule
cr
say "1 participant:" cr
1 schedule
cr
say "0 participants:" cr
0 schedule
- Output:
12 participants: Round 1: 1 vs 12 2 vs 11 3 vs 10 4 vs 9 5 vs 8 6 vs 7 Round 2: 5 vs 12 6 vs 4 7 vs 3 8 vs 2 9 vs 1 10 vs 11 Round 3: 9 vs 12 10 vs 8 11 vs 7 1 vs 6 2 vs 5 3 vs 4 Round 4: 2 vs 12 3 vs 1 4 vs 11 5 vs 10 6 vs 9 7 vs 8 Round 5: 6 vs 12 7 vs 5 8 vs 4 9 vs 3 10 vs 2 11 vs 1 Round 6: 10 vs 12 11 vs 9 1 vs 8 2 vs 7 3 vs 6 4 vs 5 Round 7: 3 vs 12 4 vs 2 5 vs 1 6 vs 11 7 vs 10 8 vs 9 Round 8: 7 vs 12 8 vs 6 9 vs 5 10 vs 4 11 vs 3 1 vs 2 Round 9: 11 vs 12 1 vs 10 2 vs 9 3 vs 8 4 vs 7 5 vs 6 Round 10: 4 vs 12 5 vs 3 6 vs 2 7 vs 1 8 vs 11 9 vs 10 Round 11: 8 vs 12 9 vs 7 10 vs 6 11 vs 5 1 vs 4 2 vs 3 5 participants: Round 1: 1 bye 2 vs 5 3 vs 4 Round 2: 2 bye 3 vs 1 4 vs 5 Round 3: 3 bye 4 vs 2 5 vs 1 Round 4: 4 bye 5 vs 3 1 vs 2 Round 5: 5 bye 1 vs 4 2 vs 3 1 participant: Round 1: 1 bye 0 participants:
Raku
my @players = (1,0)[$_%2] .. $_ given 12;
my $half = +@players div 2;
my $round = 0;
loop {
printf "Round %2d: %s\n", ++$round, "{ zip( @players[^$half], @players[$half..*].reverse ).map: { sprintf "(%2d vs %-2d)", |$_ } }";
@players[1..*].=rotate(-1);
last if [<] @players;
}
- Output:
Round 1: ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) Round 2: ( 1 vs 11) (12 vs 10) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) Round 3: ( 1 vs 10) (11 vs 9 ) (12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) Round 4: ( 1 vs 9 ) (10 vs 8 ) (11 vs 7 ) (12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 5: ( 1 vs 8 ) ( 9 vs 7 ) (10 vs 6 ) (11 vs 5 ) (12 vs 4 ) ( 2 vs 3 ) Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) (10 vs 4 ) (11 vs 3 ) (12 vs 2 ) Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) (10 vs 2 ) (11 vs 12) Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12) (10 vs 11) Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12) ( 8 vs 11) ( 9 vs 10) Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12) ( 6 vs 11) ( 7 vs 10) ( 8 vs 9 ) Round 11: ( 1 vs 2 ) ( 3 vs 12) ( 4 vs 11) ( 5 vs 10) ( 6 vs 9 ) ( 7 vs 8 )
Ruby
def round_robin( n )
rotating_players = (2..n).map(&:to_s) #player 1 to be added later
rotating_players << "bye" if n.odd?
Array.new(rotating_players.size) do |r|
all = ["1"] + rotating_players.rotate(-r)
[all[0, all.size/2], all[all.size/2..].reverse]
end
end
round_robin(12).each.with_index(1) do |round, i|
puts "Round #{i}"
round.each do |players|
puts players.map{|player| player.ljust(4)}.join
end
puts
end
- Output:
Round 1 1 2 3 4 5 6 12 11 10 9 8 7 Round 2 1 12 2 3 4 5 11 10 9 8 7 6 Round 3 1 11 12 2 3 4 10 9 8 7 6 5 Round 4 1 10 11 12 2 3 9 8 7 6 5 4 Round 5 1 9 10 11 12 2 8 7 6 5 4 3 Round 6 1 8 9 10 11 12 7 6 5 4 3 2 Round 7 1 7 8 9 10 11 6 5 4 3 2 12 Round 8 1 6 7 8 9 10 5 4 3 2 12 11 Round 9 1 5 6 7 8 9 4 3 2 12 11 10 Round 10 1 4 5 6 7 8 3 2 12 11 10 9 Round 11 1 3 4 5 6 7 2 12 11 10 9 8
Rust
fn round_robin(n: usize) {
assert!(n >= 2);
let mut n = n;
let mut list1: Vec<usize> = (2..=n).collect();
if n % 2 == 1 {
list1.push(0); // 0 denotes a "bye".
n += 1;
}
for r in 1..n {
print!("Round {:2}:", r);
let list2 = vec![1].into_iter().chain(list1.iter().cloned()).collect::<Vec<_>>();
for i in 0..(n / 2) {
print!(" ({:>2} vs {:<2})", list2[i], list2[n - i - 1]);
}
println!();
list1.rotate_right(1);
}
}
fn main() {
println!("Round robin for 12 players:\n");
round_robin(12);
println!("\n\nRound robin for 5 players (0 denotes a bye):\n");
round_robin(5);
}
- Output:
Round robin for 12 players: Round 1: ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) Round 2: ( 1 vs 11) (12 vs 10) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) Round 3: ( 1 vs 10) (11 vs 9 ) (12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) Round 4: ( 1 vs 9 ) (10 vs 8 ) (11 vs 7 ) (12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 5: ( 1 vs 8 ) ( 9 vs 7 ) (10 vs 6 ) (11 vs 5 ) (12 vs 4 ) ( 2 vs 3 ) Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) (10 vs 4 ) (11 vs 3 ) (12 vs 2 ) Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) (10 vs 2 ) (11 vs 12) Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12) (10 vs 11) Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12) ( 8 vs 11) ( 9 vs 10) Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12) ( 6 vs 11) ( 7 vs 10) ( 8 vs 9 ) Round 11: ( 1 vs 2 ) ( 3 vs 12) ( 4 vs 11) ( 5 vs 10) ( 6 vs 9 ) ( 7 vs 8 ) Round robin for 5 players (0 denotes a bye): Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 )
Scala
object RoundRobinTournamentSchedule extends App {
def roundRobin(teamCount: Int): Unit = {
require(teamCount >= 2, s"Number of teams must be greater than 2: $teamCount")
var rotatingList = (2 to teamCount).toList
var adjustedTeamCount = teamCount
if (teamCount % 2 == 1) {
rotatingList :+= 0
adjustedTeamCount += 1
}
for (round <- 1 until adjustedTeamCount) {
print(f"Round $round%2d:")
val fixedList = 1 :: rotatingList
for (i <- 0 until adjustedTeamCount / 2) {
print(f" ( ${fixedList(i)}%2d vs ${fixedList(adjustedTeamCount - 1 - i)}%2d )")
}
println()
rotatingList = rotatingList.last :: rotatingList.init
}
}
println("Round robin for 12 players:")
roundRobin(12)
println()
println("Round robin for 5 players, 0 denotes a bye:")
roundRobin(5)
}
- Output:
Round robin for 12 players: Round 1: ( 1 vs 12 ) ( 2 vs 11 ) ( 3 vs 10 ) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) Round 2: ( 1 vs 11 ) ( 12 vs 10 ) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) Round 3: ( 1 vs 10 ) ( 11 vs 9 ) ( 12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) Round 4: ( 1 vs 9 ) ( 10 vs 8 ) ( 11 vs 7 ) ( 12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 5: ( 1 vs 8 ) ( 9 vs 7 ) ( 10 vs 6 ) ( 11 vs 5 ) ( 12 vs 4 ) ( 2 vs 3 ) Round 6: ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) ( 10 vs 4 ) ( 11 vs 3 ) ( 12 vs 2 ) Round 7: ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) ( 10 vs 2 ) ( 11 vs 12 ) Round 8: ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12 ) ( 10 vs 11 ) Round 9: ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12 ) ( 8 vs 11 ) ( 9 vs 10 ) Round 10: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12 ) ( 6 vs 11 ) ( 7 vs 10 ) ( 8 vs 9 ) Round 11: ( 1 vs 2 ) ( 3 vs 12 ) ( 4 vs 11 ) ( 5 vs 10 ) ( 6 vs 9 ) ( 7 vs 8 ) Round robin for 5 players, 0 denotes a bye: Round 1: ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 2: ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) Round 3: ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) Round 4: ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) Round 5: ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 )
Swift
import Foundation
func roundRobin(teamCount: Int) {
if teamCount < 2 {
fatalError("Number of teams must be greater than 2: \(teamCount)")
}
var rotatingList = Array(2...teamCount)
var effectiveTeamCount = teamCount
if teamCount % 2 == 1 {
rotatingList.append(0) // Adding a 'bye' in case of odd number of teams
effectiveTeamCount += 1
}
for round in 1..<effectiveTeamCount {
print("Round \(round):", terminator: "")
let fixedList = [1] + rotatingList
for i in 0..<(effectiveTeamCount / 2) {
print(" (\(fixedList[i]) vs \(fixedList[effectiveTeamCount - 1 - i]))", terminator: "")
}
print()
rotatingList.rotate(shift: 1)
}
}
extension Array {
mutating func rotate(shift: Int) {
let index = shift >= 0 ?
self.index(self.startIndex, offsetBy: self.count - shift, limitedBy: self.endIndex) :
self.index(self.startIndex, offsetBy: -shift, limitedBy: self.endIndex)
guard let validIndex = index else { return }
self = Array(self[validIndex..<self.endIndex] + self[self.startIndex..<validIndex])
}
}
// Example usage
print("Round robin for 12 players:")
roundRobin(teamCount: 12)
print("\nRound robin for 5 players, 0 denotes a bye:")
roundRobin(teamCount: 5)
- Output:
Round robin for 12 players: Round 1: (1 vs 12) (2 vs 11) (3 vs 10) (4 vs 9) (5 vs 8) (6 vs 7) Round 2: (1 vs 11) (12 vs 10) (2 vs 9) (3 vs 8) (4 vs 7) (5 vs 6) Round 3: (1 vs 10) (11 vs 9) (12 vs 8) (2 vs 7) (3 vs 6) (4 vs 5) Round 4: (1 vs 9) (10 vs 8) (11 vs 7) (12 vs 6) (2 vs 5) (3 vs 4) Round 5: (1 vs 8) (9 vs 7) (10 vs 6) (11 vs 5) (12 vs 4) (2 vs 3) Round 6: (1 vs 7) (8 vs 6) (9 vs 5) (10 vs 4) (11 vs 3) (12 vs 2) Round 7: (1 vs 6) (7 vs 5) (8 vs 4) (9 vs 3) (10 vs 2) (11 vs 12) Round 8: (1 vs 5) (6 vs 4) (7 vs 3) (8 vs 2) (9 vs 12) (10 vs 11) Round 9: (1 vs 4) (5 vs 3) (6 vs 2) (7 vs 12) (8 vs 11) (9 vs 10) Round 10: (1 vs 3) (4 vs 2) (5 vs 12) (6 vs 11) (7 vs 10) (8 vs 9) Round 11: (1 vs 2) (3 vs 12) (4 vs 11) (5 vs 10) (6 vs 9) (7 vs 8) Round robin for 5 players, 0 denotes a bye: Round 1: (1 vs 0) (2 vs 5) (3 vs 4) Round 2: (1 vs 5) (0 vs 4) (2 vs 3) Round 3: (1 vs 4) (5 vs 3) (0 vs 2) Round 4: (1 vs 3) (4 vs 2) (5 vs 0) Round 5: (1 vs 2) (3 vs 0) (4 vs 5)
Wren
import "./fmt" for Fmt
var rotate = Fn.new { |lst|
var last = lst[-1]
for (i in lst.count-1..1) lst[i] = lst[i-1]
lst[0] = last
}
var roundRobin = Fn.new { |n|
var lst = (2..n).toList
if (n % 2 == 1) {
lst.add(0) // 0 denotes a bye
n = n + 1
}
for (r in 1...n) {
Fmt.write("Round $2d", r)
var lst2 = [1] + lst
for (i in 0...n/2) Fmt.write(" ($2d vs $-2d)", lst2[i], lst2[n - 1 - i])
System.print()
rotate.call(lst)
}
}
System.print("Round robin for 12 players:\n")
roundRobin.call(12)
System.print("\n\nRound robin for 5 players (0 denotes a bye) :\n")
roundRobin.call(5)
- Output:
Round robin for 12 players: Round 1 ( 1 vs 12) ( 2 vs 11) ( 3 vs 10) ( 4 vs 9 ) ( 5 vs 8 ) ( 6 vs 7 ) Round 2 ( 1 vs 11) (12 vs 10) ( 2 vs 9 ) ( 3 vs 8 ) ( 4 vs 7 ) ( 5 vs 6 ) Round 3 ( 1 vs 10) (11 vs 9 ) (12 vs 8 ) ( 2 vs 7 ) ( 3 vs 6 ) ( 4 vs 5 ) Round 4 ( 1 vs 9 ) (10 vs 8 ) (11 vs 7 ) (12 vs 6 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 5 ( 1 vs 8 ) ( 9 vs 7 ) (10 vs 6 ) (11 vs 5 ) (12 vs 4 ) ( 2 vs 3 ) Round 6 ( 1 vs 7 ) ( 8 vs 6 ) ( 9 vs 5 ) (10 vs 4 ) (11 vs 3 ) (12 vs 2 ) Round 7 ( 1 vs 6 ) ( 7 vs 5 ) ( 8 vs 4 ) ( 9 vs 3 ) (10 vs 2 ) (11 vs 12) Round 8 ( 1 vs 5 ) ( 6 vs 4 ) ( 7 vs 3 ) ( 8 vs 2 ) ( 9 vs 12) (10 vs 11) Round 9 ( 1 vs 4 ) ( 5 vs 3 ) ( 6 vs 2 ) ( 7 vs 12) ( 8 vs 11) ( 9 vs 10) Round 10 ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 12) ( 6 vs 11) ( 7 vs 10) ( 8 vs 9 ) Round 11 ( 1 vs 2 ) ( 3 vs 12) ( 4 vs 11) ( 5 vs 10) ( 6 vs 9 ) ( 7 vs 8 ) Round robin for 5 players (0 denotes a bye) : Round 1 ( 1 vs 0 ) ( 2 vs 5 ) ( 3 vs 4 ) Round 2 ( 1 vs 5 ) ( 0 vs 4 ) ( 2 vs 3 ) Round 3 ( 1 vs 4 ) ( 5 vs 3 ) ( 0 vs 2 ) Round 4 ( 1 vs 3 ) ( 4 vs 2 ) ( 5 vs 0 ) Round 5 ( 1 vs 2 ) ( 3 vs 0 ) ( 4 vs 5 )
XPL0
def N = 12; \number of players (must be even)
int I, Player(N+1), Round, Temp;
[for I:= 1 to N do Player(I):= I;
for Round:= 1 to N-1 do
[IntOut(0, Round); ChOut(0, ^:);
for I:= 1 to N/2 do
[ChOut(0, 9\tab\); IntOut(0, Player(I))];
CrLf(0);
for I:= N downto N/2+1 do
[ChOut(0, 9\tab\); IntOut(0, Player(I))];
CrLf(0); CrLf(0);
Temp:= Player(N); \rotate
for I:= N-1 downto 2 do
Player(I+1):= Player(I);
Player(2):= Temp;
];
]
- Output:
1: 1 2 3 4 5 6 12 11 10 9 8 7 2: 1 12 2 3 4 5 11 10 9 8 7 6 3: 1 11 12 2 3 4 10 9 8 7 6 5 4: 1 10 11 12 2 3 9 8 7 6 5 4 5: 1 9 10 11 12 2 8 7 6 5 4 3 6: 1 8 9 10 11 12 7 6 5 4 3 2 7: 1 7 8 9 10 11 6 5 4 3 2 12 8: 1 6 7 8 9 10 5 4 3 2 12 11 9: 1 5 6 7 8 9 4 3 2 12 11 10 10: 1 4 5 6 7 8 3 2 12 11 10 9 11: 1 3 4 5 6 7 2 12 11 10 9 8