dirtyboy has asked for the wisdom of the Perl Monks concerning the following question:

The perl program should accept a file name as a command line argument of the form:
Karpov Shirov 3.5-1.5 Shirov Anand 2.0-3.0 Anand Kasparov 1.0-4.0 Kasparov karpov 2.0-2.0 BlueJunior Kasparov 3.0-3.0
The first two strings are names of chess players, followed by the score of the match between them. For example, in the first match Karpov beat Shirov by a score of 3.5 to 1.5.

Your program should read these data and create an associative array, record, indexed by player names. In record{'name'}, you should store the number of wins, losses and draws of player name.

Your program should then produce output for each player, in the form:

player_name, # of wins, # of losses, # of draws and the output should be sorted in descending order of total points.

Note : A player gets 1 point for each win, 0 points for a loss, and 0. +5 points for a draw. *********************************************** THIS FOLLOWING IS THE CODE THAT I HAVE WRITTEN. UW PICO(tm) 4.0 File: $in_file = shift@ARGV; open(PLAYERS, "<$in_file") || die "Cannot open the input file!"; $p1wins = 0; $p1loss = 0; $p2wins = 0; $p2loss = 0; $p1draw = 0; $p2draw = 0; $wins = 0; $loss = 0; $draw = 0; while(<PLAYERS>) { if (/(\w+)\s+(\w+)\s+(\d\.\d)\-(\d\.\d)/) { if($3 > $4) { $p1wins = $p1wins + 1; $p2loss = $p2loss + 1; $player{$1} = [$1, $p1wins, $p1loss, $p1draw]; $player{$2} = [$2, $p2wins, $p2loss, $p2draw]; } } elsif($3 < $4) { $p1loss = $p1loss + 1; $p2wins = $p2wins + 1; $player{$1} = [$1, $p1wins, $p1loss, $p1draw]; $player{$2} = [$2, $p2wins, $p2loss, $p2draw]; } else { $p1draw = $p1draw + 1; $p2draw = $p2draw + 1; $player{$1} = [$1, $p1wins, $p1loss, $p1draw]; $player{$2} = [$2, $p2wins, $p2loss, $p2draw]; } } } print $player{Kasparov}[0], " ",$player{Kasparov}[1], " ",$player{Kasp +arov}[2]," ",$player{Kasparov}[3],"\n"; print $player{Anand}[0]," ",$player{Anand}[1]," ",$player{Anand}[2]," +",$player{Anand}[]3,"\n"; print $player{Karpov}[0], " ",$player{Karpov}[1], " ",$player{Karpov}[ +2]," ",$player{Karpov}[3],"\n"; print $player{Shirov}[0], " ",$player{Shirov}[1], " ",$player{Shirov}[ +2]," ",$player{Shirov}[3],"\n"; print $player{BlueJunior}[0], " ",$player{BlueJunior}[1], " ",$player{ +BlueJunior}[2]," ",$player{BlueJunior}[3],"\n"
I am really stuck with this, I am not able to get past this. Your help is greatly appreciated.


+ 2loss, $p2draw]; } )

Edit by tye, add formatting

Replies are listed 'Best First'.
Re: Stuck with hw
by glivings (Scribe) on Apr 02, 2003 at 20:33 UTC
    I'm assuming that the part youre having a problem with is printing out the reverse-sorted output, in which case the following is probably what you want, instead of your 5 print statements at the end:

    foreach (sort { $player{$b}[1]*1 + $player{$b}[3]*.5 <=> $player{$a}[1 +]*1 + $player{$a}[3]*.5 } keys %player) { print $_ . " " . join(" ", @{$player{$_}}[1..3]) . "\n"; }

    this substitution results in the following output:
    this results in Kasparov 2 1 2 karpov 2 1 1 BlueJunior 1 2 2 Anand 1 2 0 Shirov 1 1 0 Karpov 1 0 0

    Also something you should look out for is unnecessary duplication, specifically in lines like this:
    $player{$1} = [ $1, $p1wins, $p1loss, $p1draw ];

    Is there a reason you need to duplicate the player's name? That information is already stored as the key, you don't need it in the array.

    These are just some quick pointers to help you on your way... it's 4:30, and I'm going home.

    Also: use <CODE></CODE> tags - you'll find that people are more willing to help if they can actually look at your unmangled code - Writeup Formatting Tips

Re: Stuck with hw
by dga (Hermit) on Apr 02, 2003 at 21:43 UTC

    An accurate solution is not possible from the input data unless it is known how the individual games from each match turned out.

    For example in the Kasparov Karpov match the score 2.0-2.0 could be a result of.

    win 2 lose 2win 2 lose 2
    win 1 draw 2 lose 1win 1 draw 2 lose 1
    win 0 draw 4 lose 0win 0 draw 4 lose 0

    Each of these will produce the 2.0-2.0 score from the excersize. Of course, pointing this out to your teacher may not improve your grade. I guess you could code the excersize to print out all the possible variations for each score but this will cause the summary scores at the end to vary over a wide range indeed since for this one match they could each have 0,1, or 2 wins, 0,1 or 2 losses, or 0, 2, or 4 draws with a couple these combined in the middle...

    One consolation, is that the .5 scores have to have an odd number of draws and the .0 scores have to have an even number of draws.

Re: Stuck with hw
by DrManhattan (Chaplain) on Apr 02, 2003 at 20:21 UTC

    Haha, well at least you admit it's homework, and you've included some code of your own. We get a lot of homework questions here from people trying to get us to do their whole assignment for them.

    We can probably give you some advice, but first you'll have to make your post readable.


Re: Stuck with hw
by blaze (Friar) on Apr 03, 2003 at 01:38 UTC
    hmm..well i cant say you're really clear on what exactly you need, but since you did put some code that shows some kind of effort, ill tell you what i make of your question...even though its homework :)

    From what i can tell you have a flat file in the format of "player_one player_two player_one_score-player_two_score", and you just need to get all the players stats, how many they've won, lost and how many draws...i'd try something like this::
    #!/usr/bin/perl -w use strict; chomp(my $file = <STDIN>); my (@names,@winners,@losers,@draws); open FILE, "$file" or die "Couldnt open: $!\n"; while(<FILE>){ my($name1,$name2,$scores) = split(/ /,$_); push(@names,$name1,$name2); my($score1,$score2) = split(/\-/,$scores); if($score1 > $score2){ push(@winners, $name1); push(@losers, $name2); } elsif($score1 < $score2){ push(@winners, $name2); push(@losers, $name1); } else { push(@draws,$name1,$name2); } } close FILE; my %nams; for(@names){ $nams{$_}++; } my %wins; for(@winners){ $wins{$_}++; } my %los; for(@losers){ $los{$_}++; } my %dra; for(@draws){ $dra{$_}++; } foreach my $in(keys %nams){ $wins{$in} = 0 unless defined $wins{$in}; $los{$in} = 0 unless defined $los{$in}; $dra{$in} = 0 unless defined $dra{$in}; print "Player: $in - Wins: $wins{$in} - Losses: $los{$in} - Draws +: $dra{$in}\n"; }
    This is very untested, so you might have to modify it a bit, if im misunderstanding what you need let me know


    Update: gave script ability to print a zero