Round-robin tournament schedule

Revision as of 10:18, 20 May 2022 by PureFox (talk | contribs) (Added Go)

A round-robin tournament is also known as an all-play-all-tournament; each participant plays every other participant once.

Round-robin tournament schedule is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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


AWK

<lang AWK>

  1. 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
   }

} </lang>

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

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)

Go

Translation of: Wren

<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)

}</lang>

Output:
Same as Wren example.

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

Even

<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 

Even and Odd

<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;</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

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

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

Library: Wren-fmt

<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.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)</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