Question 5: A Perl solution
#!/usr/bin/perl
use 5.014;
use strict;
use warnings;
use autodie;
system "rm -rf work; mkdir work";
chdir("work");
system("tar xvfz 05-rock-paper-scissors");
my @players = map { Player->new_from_file($_) }
glob('contestants/contestant??');
my $round = 1;
while(@players > 1) {
say "\nRound $round\n";
my @next_players;
while(@players) {
my $player1 = shift(@players);
my $player2 = shift(@players);
my $winner = $player1->engage($player2);
push @next_players, $winner;
}
$round++;
@players = @next_players;
}
say "\nToken: ", uc($players[0]->token);
exit;
package Player;
our %winner;
BEGIN {
%winner = (
'rock:rock' => 0,
'rock:paper' => 2,
'rock:scissors' => 1,
'paper:rock' => 1,
'paper:paper' => 0,
'paper:scissors' => 2,
'scissors:rock' => 2,
'scissors:paper' => 1,
'scissors:scissors' => 0,
);
}
sub new_from_file {
my($class, $filename) = @_;
my @choices;
my $self = bless {
choices => \@choices,
}, $class;
open my $fh, '<', $filename;
while(<$fh>) {
chomp;
if(/Name=(\w\w\w\w)/) {
$self->{name} = $1;
}
else {
push @choices, $_;
}
}
return $self;
}
sub name { shift->{name}; }
sub token { shift->{token}; }
sub choice {
my $self = shift;
my $choices = $self->{choices};
die "Player '$self->{name}': all choices exhausted" unless @$choices;
return shift @$choices;
}
sub set_token {
my($self, $loser) = @_;
$self->{token} = $self->name . $loser->name;
return $self;
}
sub engage {
my($player1, $player2) = @_;
say $player1->name, ' vs ', $player2->name;
while(1) {
my $choice1 = $player1->choice;
my $choice2 = $player2->choice;
my $pair = "$choice1:$choice2";
my $result = $winner{$pair} // die "can't find winner for $pair";
if($result == 1) {
say " $pair - ", $player1->name, " wins!";
return $player1->set_token($player2);
}
elsif($result == 2) {
say " $pair - ", $player2->name, " wins!";
return $player2->set_token($player1);
}
else {
say " $pair - draw";
}
}
}