[Solution] Perl 'Medium' QOTW
Rod Adams <[email protected]> Mon, 17 Jan 2005 20:19:35 -0600
| Newsgroups | gmane.comp.lang.perl.qotw.discuss |
|---|---|
| Message-ID | <[email protected]> |
No pretty tricks from tourney or game theory, but it's not super ugly or
expensive.
Starts by making a list of all the games that ultimately must be played
in the entire tourney. It then attempts to create a schedule, one day at
a time. It scans all the matches left to be played, and add each one if
possible (neither team already scheduled for that day). If it gets the
required number of matches, it returns the match. Otherwise, it
backtracks to find a different solution.
Once a day is set, those matches are removed from the pool, and a new
day begins, if there are any matches left to be played.
Recursion is used to make the backtracking simple.
-- Rod Adams
#!/usr/bin/perl
for (1..5) {
print $_*2, ":\n";
$x = allocate_schedule($_*2);
pprint ($x);
}
sub allocate_schedule {
my $n = $_[0];
$n & 1 and die "Can't schedule odd number of teams\n";
# Create list of all matches
my @Matches;
for my $n1 (0 .. $n-2) {
for my $n2 ($n1+1 .. $n-1) {
push @Matches, [$n1, $n2];
}
}
my @result = ();
my $match_per_day = $n / 2;
while (@Matches) {
my $result = create_day($match_per_day, [], \@Matches,0);
if (defined($result)) {
push @result, $result;
} else {
die "Impossible to Schedule.\n";
}
}
return \@result;
}
sub create_day {
my ($left, $today, $remaining, $tail) = @_;
return $today if $left <= 0;
# look for a match to add
for my $m ($tail .. $#$remaining) {
my ($t1, $t2) = @{$$remaining[$m]};
next if defined($$today[$t1]);
next if defined($$today[$t2]);
$$today[$t1] = $t2;
$$today[$t2] = $t1;
my $result = create_day($left-1, $today, $remaining, $m+1);
if (defined($result)) {
splice(@$remaining, $m, 1, );
return $result;
} else {
$$today[$t1] = $$today[$t2] = undef;
}
}
# no matches worked... abort
return undef;
}
sub pprint {
my @out;
for my $x (@{$_[0]}) {
push @out, '[' . join(',', @$x) . ']';
}
print "[", join(",\n ", @out), "]\n";
}
__END__