I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Round-robin tournament schedule

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.

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.

Write a program that prints out a tournament schedule for 12 participants (represented by numbers 1 to 12).

## AWK

` # syntax: GAWK -f ROUND-ROBIN_TOURNAMENT_SCHEDULE.AWKBEGIN {    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
```

## 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 ifend 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 rend 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)

```

## Go

Translation of: Wren
`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.
```

## 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 tableend 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)
```

## Perl

### Even

`#!/usr/bin/perl use strict; # https://rosettacode.org/wiki/Round-robin_tournament_scheduleuse 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)
--
--
-- 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.

## 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]  endend 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  putsend `
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
`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
```