This is more an algorithm question than Perl per se, but I consider it to be an interesting problem, so...

The basic form of Round Robin tournament schedule with all two-way matches is a reasonably well understood problem, so I won't go into a lot of detail here, but in general the constraints are that each team should quiz each other team at most (ideally, exactly) once, that every team plays the same total number of matches, that no team may play more than one match in any given round, that no team may play against itself, and that when team A plays team B, team B also plays team A at the same time. This is a solved problem.

The following is based on Florence's Algorithm. There may also be other solutions, but here is one.

sub roundrobin { my ($n, $rounds, $bye) = @_; if ($n % 2) { $rounds = $n; $bye = 1; # There will be $rounds rounds with exactly one bye for each team. } else { $rounds = $n - 1; $bye = 0; # There will be $rounds rounds, and every team will quiz every rou +nd. } my $m = $n; ++$m if $n % 2; # $m is the lowest even number greater t +han or equal to $n my %s = (teams => $n, rounds => $rounds, bye => $bye); # The working + schedule. # Fill in the working schedule with a nice diagonal pattern: for my $round (0 .. ($rounds - 1)) { for my $i (0 .. ($round-1)) { $s{table}->[$round]->[$i] = (($rounds + $round - $i + 1) + $m) % + $m; } for my $i ($round .. ($n-1)) { $s{table}->[$round]->[$i] = (($rounds + $round - $i) + $m) % $m; } } use Data::Dumper; print Dumper(+{tentative => \%s}); # Now, do knight-like moves with the 0 (bye) in the first row. # Every time the 0 lands on a number, put that number in the first c +olumn: my $byeround = 0; for my $i (reverse (1 .. ($m - 2))) { $byeround = (($byeround - 2) + $rounds) % $rounds; $s{table}->[$byeround]->[0] = $s{table}->[$byeround]->[$i] || 'Oop +sie'; $s{table}->[$byeround]->[$i] = 0; } # If m != n, then remove team n from all the games, and replace with + -1 (which means a bye, i.e., the team sits out that round): if (not $m == $n) { for my $i (0 .. $rounds-1) { $s{table}->[$i]->[$i] = -1; } } return \%s; }

That's a little too clever for easy maintenance, but it works (I'll spare you the code that checks the results). Well, it works as long as you only have two-way matches, and on modern hardware it's near-instant for any number of teams you're likely to have in this type of tournament. (Once you go past about fifty teams, it's impractical for them all to play eachother anyway, because it would be too many matches for each team, so instead you break into divisions and do double-elimination or somesuch. This algorithm can handle fifty teams in a matter of seconds.)

However, the quizzing program that I'm involved in doesn't just have two-way matches. There are also three-way quizzes. There are several reasons why the three-way quizzes are necessary:

So when constructing schedules for this type of quizzing, the constraints are a bit different...

I've been looking at this problem off and on for a couple of years, but I've never gotten anywhere very useful. Some numbers of teams (e.g., 9) are very easy to do by hand, but others are not, so I'd really like to have an algorithm for doing this. Ideas? What approach should I take? Should I predetermine how many two-way and three-way quizzes there should be, based on the number of teams, or should I approach it from a different direction?


Sanity? Oh, yeah, I've got all kinds of sanity. In fact, I've developed whole new kinds of sanity. Why, I've got so much sanity it's driving me crazy.

In reply to Round-Robin with Three-way Matches by jonadab

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.