On Thu, 17 Feb 2005 00:52:48 +1000, Alfred Vahau <[EMAIL PROTECTED]> wrote:
> Hi,
> I've been struggling with what should be a trivial problem. Perl is such
> a rich language that in formulating the logic, I've actually
> became confused. Partly because I took a C approach when I know that a
> veteran Perl programmer would write only a few lines to achive the same
> result. (The challenge coming from 'The Camel' 3rd ed. pp.119, 120).
> 

Alfred,

I'm a little confused by your weighting here...it seems to me that GPA
= SUM(G * CC)/SUM(CC), where

G = Cource Grade
CC = Course Credit.

In the US, we often call (G*CC) Honor Points.

So let's take student 386.  Assuming a 4-point scale:

Grade   Credits   Points
F        3.00          0
C        3.00          6
C        3.00          6
D        2.00          4
D        3.00          3
D        3.00          3
B        3.00          9
C        3.00          6
F        2.00          0
-----------------------
         36.00         37
37/36 = 1.027..

In other words, our formula is good, so we don't need the elaborate
lookup table.

Other places to simplfy:  the idea behind the match operator is that
it will match what you're looking for; you don't need to match all
cases and then discard the ones you don't want.  Just look for the
ones you want, and get rid of the rest.  "unless" is your friend here,
as are character classes.  Also, if the string you're matching against
doesn't have embedded \s, \b is redundant--as are ^ and $.  Where else
could you possibly match?

Given that, here's one quick way to do it.  It's easier for me to
type, using <>; you can go back and hard code the data file later if
you want:

__CODE__
#!/usr/bin/perl

use warnings ;
use strict ;

my %grades = ( A => 4, B => 3, C=> 2, D=> 1, F => 0 ) ;
# lookup hash for the grades

my %studcredit ;
# we'll store the credits attempted here

my %studpoints ;
# we'll store the honor points here

while (<>) {
    chomp;
    my ($id, $grade, $cred) = split /\s/, $_ ; # or just split
    next unless $grade =~ /[ABCDF]/;
    my $numgrade = $grades{$grade};
    $studcredit{$id} += $cred;
    $studpoints{$id} += ($numgrade * $cred);
}

# using the hashes let us save the division to the end.
# I did it because it's easier than nesting loops, but it
# has the side benefit of handling improperly sorted data.

# so now we'll get the results:

foreach my $sid (keys %studcredit) {
    my $gpa = ($studpoints{$sid} / $studcredit{$sid});
    # do something useful with $gpa here,
    # like apply rules for turning it into a letter grade.
    # for now, we'll just print it
    print "$sid\t$gpa\n";
}
__END__

HTH,

--jay

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to