Round-robin tournament schedule
A round-robin tournament is also known as an all-play-all-tournament; each participant plays every other participant once.
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
FreeBASIC
<lang 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) </lang>
- 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)
Julia
<lang 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)
</lang>
- 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)
Perl
<lang perl>#!/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 ]; }</lang>
- 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
Raku
<lang perl6>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;
}</lang>
- 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
<lang 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 </lang>
- 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
Wren
<lang ecmascript>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 = lst + [0] // 0 denotes a bye n = n + 1 } var n2 = n / 2 for (r in 1...n) { Fmt.write("Round $2d", r) var lst2 = [1] + lst for (i in 0...n2) 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)</lang>
- 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
<lang 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; ];
]</lang>
- 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