For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > February 2005 > Idiomatic Perl for GPA Calculation









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Idiomatic Perl for GPA Calculation
Alfred Vahau

2005-02-16, 3:57 pm

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 . 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).

I have a fairly large file with the records in the format:

ID1 Grade Credit
ID1 Grade Credit
ID1 Grade Credit
..
..
ID2 Grade Credit
ID2 Grade Credit
ID2 Grade Credit
..
..
ID3 Grade Credit
ID3 Grade Credit
ID3 Grade Credit
..
etc,

The IDs are the student identication numbers. The Grades stand for
letter grades A, B, C, D, F, NG, YL, Y, W, T, DF.
Credit are the credit points for the courses and take on the values 2,
3, 4, 6.

To calculate the grade point average, I use the formula:

$gpa = $wcp / $cp_total

where $gpa = Grade Point Average, $wcp = weighted credit points,
$cp_total = sum of credit points for the courses.

The weighted credit points is given by the formula:

$wcp = ($a6*4.0*6.0 + $a4*4.0*4.0 + $a3*4.0*3.0 + $a2*4.0*2.0) +
($b6*3.0*6.0 + $b4*3.0*4.0 + $b3*3.0*3.0 + $b2*3.0*2.0) +
($c6*2.0*6.0 + $c4*2.0*4.0 + $c3*2.0*3.0 + $c2*2.0*2.0) +
($d6*1.0*6.0 + $d4*1.0*4.0 + $d3*1.0*3.0 + $d2*1.0*2.0);

One of the conditions is that only A, B, C, D, F grades are to be used
in the calcuation of the GPAs.
To do that I need to know how many As, a student has for a course, say
worth, 6 points. This is shown by the variable
$a6. For a 4-point course, $a4, etc, Each letter is weighted with A=4,
B=3, C=2, D=1, F=0.

Below is one of just of several coding that I have developed so far.
Somewhere the while, unless, do or until will do the job but I haven't
quite figure out their positions in the program.

What is the Perl idiom for doing such a calculation?

For the sample data:

id 386, $gpa = 35/25 = 1.40

id 216, $gpa = 92/53 = 1.73


Thanks in advance for the help.

Alfred Vahau



------------- One of my codes which does not produce correct results
-----------

----
#!/usr/bin/perl

# This is the GPA calculation routine for the
# Eduadmin system again.
#

$ifile = 'gpa.dat';

open (INF, "<$ifile") || die "Can't open file $ifile:$!\n";

$cp_total = 0;

$id = 0;

$temp = 0;

LINE: while (<INF> ) {

($id, $grade, $cp) = split;

if ($grade =~ /NG/i ||
$grade =~ /YL/i ||
$grade =~ /DF/i ||
$grade =~ /\bY\b/i ||
$grade =~ /W/i ||
$grade =~ /T/i) {next LINE;}

$cp_total +=
$cp;

if ($grade =~ /\bA\b/i) {
$a6++ if $cp == 6;
$a4++ if $cp == 4;
$a3++ if $cp == 3;
$a2++ if $cp == 2;

}

if ($grade =~ /\bB\b/i) {
$b6++ if $cp == 6;
$b4++ if $cp == 4;
$b3++ if $cp == 3;
$b2++ if $cp == 2;

}

if ($grade =~ /\bC\b/i) {
$c6++ if $cp == 6;
$c4++ if $cp == 4;
$c3++ if $cp == 3;
$c2++ if $cp == 2;

}

if ($grade =~ /\bD\b/i) {
$d6++ if $cp == 6;
$d4++ if $cp == 4;
$d3++ if $cp == 3;
$d2++ if $cp == 2;

}

if ($temp == $id) {
next LINE;
}
else {

$wcp = ($a6*4.0*6.0 + $a4*4.0*4.0 + $a3*4.0*3.0 + $a2*4.0*2.0) +
($b6*3.0*6.0 + $b4*3.0*4.0 + $b3*3.0*3.0 + $b2*3.0*2.0) +
($c6*2.0*6.0 + $c4*2.0*4.0 + $c3*2.0*3.0 + $c2*2.0*2.0) +
($d6*1.0*6.0 + $d4*1.0*4.0 + $d3*1.0*3.0 + $d2*1.0*2.0);

$gpa = $wcp / $cp_total;

$temp = $id;
$cp_total = 0;
next LINE;
}

} # end of while

The sample data is:

386 F 3.00
386 C 3.00
386 C 3.00
386 D 2.00
386 D 3.00
386 D 3.00
386 B 3.00
386 C 3.00
386 F 2.00
216 C 2.00
216 C 2.00
216 C 2.00
216 YL 4.00
216 YL 2.00
216 C 2.00
216 D 2.00
216 C 2.00
216 YL 4.00
216 YL 2.00
216 C 2.00
216 C 2.00
216 D 2.00
216 C 4.00
216 C 2.00
216 C 3.00
216 C 3.00
216 C 3.00
216 C 3.00
216 C 2.00
216 C 3.00
216 F 3.00
216 D 3.00
216 F 3.00
216 C 3.00

--
Perl -
"... making the easy jobs easy,
without making the hard jobs impossible."
'The Camel', 3ed

Ankur Gupta

2005-02-16, 3:57 pm

>
> ----
> #!/usr/bin/perl
>
> # This is the GPA calculation routine for the
> # Eduadmin system again.
> #
>
> $ifile = 'gpa.dat';
>
> open (INF, "<$ifile") || die "Can't open file $ifile:$!\n";
>
> $cp_total = 0;
>
> $id = 0;
>
> $temp = 0;
>
> LINE: while (<INF> ) { ($id, $grade, $cp) =
> split;
> if ($grade =~ /NG/i ||
> $grade =~ /YL/i ||
> $grade =~ /DF/i ||
> $grade =~ /\bY\b/i ||
> $grade =~ /W/i ||
> $grade =~ /T/i) {next LINE;}
>
> $cp_total +=
> $cp;
> if ($grade =~ /\bA\b/i) { $a6++ if $cp ==
> 6; $a4++ if $cp ==
> 4; $a3++ if $cp ==
> 3; $a2++ if $cp ==
> 2; }
> if ($grade =~ /\bB\b/i) { $b6++ if
> $cp == 6; $b4++ if $cp ==
> 4; $b3++ if $cp ==
> 3; $b2++ if $cp ==
> 2; }
>
> if ($grade =~ /\bC\b/i) { $c6++ if $cp ==
> 6; $c4++ if $cp ==
> 4; $c3++ if $cp ==
> 3; $c2++ if $cp ==
> 2; }
>
> if ($grade =~ /\bD\b/i) { $d6++ if $cp ==
> 6; $d4++ if $cp ==
> 4; $d3++ if $cp ==
> 3; $d2++ if $cp ==
> 2; }
>
> if ($temp == $id) {
> next LINE;
> }
> else {
>
> $wcp = ($a6*4.0*6.0 + $a4*4.0*4.0 + $a3*4.0*3.0 + $a2*4.0*2.0) +
> ($b6*3.0*6.0 + $b4*3.0*4.0 + $b3*3.0*3.0 + $b2*3.0*2.0) +
> ($c6*2.0*6.0 + $c4*2.0*4.0 + $c3*2.0*3.0 + $c2*2.0*2.0) +
> ($d6*1.0*6.0 + $d4*1.0*4.0 + $d3*1.0*3.0 + $d2*1.0*2.0);
> $gpa = $wcp / $cp_total;
>
> $temp = $id;
> $cp_total = 0;
> next LINE;
> }
>
> } # end of while
>

use hashes of hashes.........

#Lets first store the hashes
while(<INF> ){
($id, $grade, $cp) = split(/\s+/);
#I am removing the .00 for convenience. You can preserve it and make
changes accordingly
$cp =~ s/(\d)\.00/$1/;
#No need for label.. lets put everything in one search
next if $grade =~ /(NG|YL|DF|\bY\b|W|T)/ ;
#This is the best part.. I am creating hashes of hashes of hashes.
The hashes takes care of uniqueness.
$student{$id}->{$grade}->{$cp}++;
#Simple hash for sum of credit points
$cp_total{$id} += $cp;
}

#Now calculate the weighted credit points for each student..
foreach $id ( keys %student ){
#Even this can be improved by using more foreaches. But lets keep it
like this for easy readability
$wcp = ($student{$id}->{A}->{6}*24 + $student{$id}->{A}->{4}*16 +
$student{$id}->{A}->{3}*12 + $student{$id}->{A}->{2}*8)+
($student{$id}->{B}->{6}*18 +
$student{$id}->{B}->{4}*12 + $student{$id}->{B}->{3}*9 +
$student{$id}->{B}->{2}*6)+
($student{$id}->{C}->{6}*12 + $student{$id}->{C}->{4}*8
+ $student{$id}->{C}->{3}*6 + $student{$id}->{C}->{2}*6)+
($student{$id}->{D}->{6}*6 + $student{$id}->{D}->{4}*4
+ $student{$id}->{D}->{3}*3 + $student{$id}->{D}->{2}*2);
#Calculate the gpa and store it for each student
$gpa{$id} = $wcp/$cp_total{$id};
}

#Lets print it now. We could have done it in the above foreach also ..
foreach $id (keys %student){
print "GPA for $id : $gpa{$id}\n";
}

BTW, I got these values
GPA for 216 : 1.98
GPA for 386 : 1.40

Although it is correct for 386.. it does not matches for id 216. Are you
sure gpa for 216 is correct.

Hope you got the idea of how you can use hashes to make the program
short and simple.

--
Ankur


Jay

2005-02-16, 3:57 pm

On Thu, 17 Feb 2005 00:52:48 +1000, Alfred Vahau <Alf.Vahau@upng.ac.pg> 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 . 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 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
Jay

2005-02-16, 3:57 pm

On Wed, 16 Feb 2005 11:10:24 -0500, Jay <daggerquill@gmail.com> wrote:
> On Thu, 17 Feb 2005 00:52:48 +1000, Alfred Vahau <Alf.Vahau@upng.ac.pg> wrote:
>
> Alfred,
>
> I'm a little 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.
>


Yeah, ignore the match I did by hand. The progam is sound, though.

--jay
Alfred Vahau

2005-02-16, 8:57 pm

Thank you for the pointer. I will check the calculation again for GPA of
1.98 against id 216.
Clearly there is no problem for allowed grades so 1.40 has been
confirmed for 386.

Alfred,


Ankur Gupta wrote:

> use hashes of hashes.........
>
> #Lets first store the hashes
> while(<INF> ){
> ($id, $grade, $cp) = split(/\s+/);
> #I am removing the .00 for convenience. You can preserve it and
> make changes accordingly
> $cp =~ s/(\d)\.00/$1/;
> #No need for label.. lets put everything in one search
> next if $grade =~ /(NG|YL|DF|\bY\b|W|T)/ ;
> #This is the best part.. I am creating hashes of hashes of hashes.
> The hashes takes care of uniqueness.
> $student{$id}->{$grade}->{$cp}++;
> #Simple hash for sum of credit points
> $cp_total{$id} += $cp;
> }
>
> #Now calculate the weighted credit points for each student..
> foreach $id ( keys %student ){
> #Even this can be improved by using more foreaches. But lets keep
> it like this for easy readability
> $wcp = ($student{$id}->{A}->{6}*24 + $student{$id}->{A}->{4}*16 +
> $student{$id}->{A}->{3}*12 + $student{$id}->{A}->{2}*8)+
> ($student{$id}->{B}->{6}*18 +
> $student{$id}->{B}->{4}*12 + $student{$id}->{B}->{3}*9 +
> $student{$id}->{B}->{2}*6)+
> ($student{$id}->{C}->{6}*12 +
> $student{$id}->{C}->{4}*8 + $student{$id}->{C}->{3}*6 +
> $student{$id}->{C}->{2}*6)+
> ($student{$id}->{D}->{6}*6 + $student{$id}->{D}->{4}*4
> + $student{$id}->{D}->{3}*3 + $student{$id}->{D}->{2}*2);
> #Calculate the gpa and store it for each student
> $gpa{$id} = $wcp/$cp_total{$id};
> }
>
> #Lets print it now. We could have done it in the above foreach also ..
> foreach $id (keys %student){
> print "GPA for $id : $gpa{$id}\n";
> }
>
> BTW, I got these values
> GPA for 216 : 1.98
> GPA for 386 : 1.40
>
> Although it is correct for 386.. it does not matches for id 216. Are
> you sure gpa for 216 is correct.
>
> Hope you got the idea of how you can use hashes to make the program
> short and simple.
>
> --
> Ankur
>
>
>


--
Perl -
"... making the easy jobs easy,
without making the hard jobs impossible."
'The Camel', 3ed

Alfred Vahau

2005-02-16, 8:57 pm

Jay wrote:

>On Thu, 17 Feb 2005 00:52:48 +1000, Alfred Vahau <Alf.Vahau@upng.ac.pg> wrote:
>
>
>
>Alfred,
>
>I'm a little by your weighting here...it seems to me that GPA
>= SUM(G * CC)/SUM(CC), where
>
>G = Cource Grade
>CC = Course Credit.
>
>

The observation is correct. The sums are involved here.

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

Thanks. I couldn't recall the term for the numerator. Been a while since
my days at Blacksburg, VA.

>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 ;
>
>

When I turn warnings and strict off, the program executes smoothly. When
they are on, the following compilation
error results:

*****
Global symbol "$inputfile" requires explicit package name at gpa3.pl
line 15.
Global symbol "$inputfile" requires explicit package name at gpa3.pl
line 17.
Global symbol "$inputfile" requires explicit package name at gpa3.pl
line 17.
Execution of gpa3.pl aborted due to compilation errors.
******

This is a result of declaring the file name prior to opening.

$inputfile = 'gpa.dat';
open (INF, "<$inputfile") || die "can't open file $inputfile $!:\n";

But this is another problem that I can address later.
*********

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

Thank you. Keeps tracking easier.

>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
>
>

I'll use /\s+/ just in case of additional white spaces in the real data

> next unless $grade =~ /[ABCDF]/;
>
>

The use of character classes clearly skipped my mind. Just to be sure of
cases, I'll use /[a-fA-F]/

> 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
>
>

Yes. There's a bit of repetive processing involved.

> print "$sid\t$gpa\n";
>
>

Id 316 gpa = 1.40 is confirmed.
Id 216 = 1.64 is different from one I quoted (1.73).

Ankur Gupta in an earlier posting quoted 1.98 for id 216 so I will have
to check the calculations again
for non-allowed grades.

>}
>__END__
>
>HTH,
>
>
>

Thank you. It sure is a big help.

>--jay
>
>
>

Alfred,

--
Perl -
"... making the easy jobs easy,
without making the hard jobs impossible."
'The Camel', 3ed

Jay

2005-02-16, 8:57 pm

On Thu, 17 Feb 2005 06:06:30 +1000, Alfred Vahau <Alf.Vahau@upng.ac.pg> wrote:
>
> $inputfile = 'gpa.dat';
> open (INF, "<$inputfile") || die "can't open file $inputfile $!:\n";
>
> But this is another problem that I can address later.
> *********
>


my $inputfile = 'gpa.dat' ;

strict wants you to declare the scope of the variable. It's just a
good thing to do.


> Thank you. Keeps tracking easier.
>
> I'll use /\s+/ just in case of additional white spaces in the real data
>
> The use of character classes clearly skipped my mind. Just to be sure of
> cases, I'll use /[a-fA-F]/



\s+ isn't a bad idea.

Be careful with you classes here, though. [a-fA-F] matches both 'e'
and 'E'. Try '/[ABCDF]/i'.



> Id 316 gpa = 1.40 is confirmed.
> Id 216 = 1.64 is different from one I quoted (1.73).
>
> Ankur Gupta in an earlier posting quoted 1.98 for id 216 so I will have
> to check the calculations again
> for non-allowed grades.


Some of the data may not have cut and pasted correctly.


HTH,

--jay
Alfred Vahau

2005-02-16, 8:57 pm



Jay wrote:

>On Thu, 17 Feb 2005 06:06:30 +1000, Alfred Vahau <Alf.Vahau@upng.ac.pg> wrote:
>
>
>
>my $inputfile = 'gpa.dat' ;
>
>strict wants you to declare the scope of the variable. It's just a
>good thing to do.
>
>
>

Thanks for pointing this out.

>
>
>
>
>\s+ isn't a bad idea.
>
>Be careful with you classes here, though. [a-fA-F] matches both 'e'
>and 'E'. Try '/[ABCDF]/i'.
>
>
>
>

Of course! There's no E grade in our current system.

>
>
>
>Some of the data may not have cut and pasted correctly.
>
>
>
>

Again will check.

>HTH,
>
>--jay
>
>


Thanks,

Alfred,

--
Perl -
"... making the easy jobs easy,
without making the hard jobs impossible."
'The Camel', 3ed

Randal L. Schwartz

2005-02-17, 4:00 pm

>>>>> "Alfred" == Alfred Vahau <Alf.Vahau@upng.ac.pg> writes:

Alfred> $wcp = ($a6*4.0*6.0 + $a4*4.0*4.0 + $a3*4.0*3.0 + $a2*4.0*2.0) +
Alfred> ($b6*3.0*6.0 + $b4*3.0*4.0 + $b3*3.0*3.0 + $b2*3.0*2.0) +
Alfred> ($c6*2.0*6.0 + $c4*2.0*4.0 + $c3*2.0*3.0 + $c2*2.0*2.0) +
Alfred> ($d6*1.0*6.0 + $d4*1.0*4.0 + $d3*1.0*3.0 + $d2*1.0*2.0);

I know this may only be a prototype for your later code, but it's a
red flag to me when a variable name has a sequential letter or a
number. Almost always, you're going to want to do something to "all
the variables that look like $a_something_", and that means they
should have been an array or hash to start with.

Important clue: DO NOT NAME A VARIABLE WITH A NUMBER OR SEQUENTIAL LETTER.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
Alfred Vahau

2005-02-17, 8:56 pm

Thank you Randal. Yes, the formula looked ugly and the challenge from
'The Camel' on p.119, 120
prompted me to post for the Perl idiom to do the job. Jay's posting
weaved the magic after some modifications.
Hard to believe that such a terse coding using only hashes can do the job
for the 30,000 records that had to be processed.

I'm satisfied that 'The Camel' challenge had been met.

Thanks to all Perl folks who follow the Sun.

Alfred,

Randal L. Schwartz wrote:

>
>Alfred> $wcp = ($a6*4.0*6.0 + $a4*4.0*4.0 + $a3*4.0*3.0 + $a2*4.0*2.0) +
>Alfred> ($b6*3.0*6.0 + $b4*3.0*4.0 + $b3*3.0*3.0 + $b2*3.0*2.0) +
>Alfred> ($c6*2.0*6.0 + $c4*2.0*4.0 + $c3*2.0*3.0 + $c2*2.0*2.0) +
>Alfred> ($d6*1.0*6.0 + $d4*1.0*4.0 + $d3*1.0*3.0 + $d2*1.0*2.0);
>
>I know this may only be a prototype for your later code, but it's a
>red flag to me when a variable name has a sequential letter or a
>number. Almost always, you're going to want to do something to "all
>the variables that look like $a_something_", and that means they
>should have been an array or hash to start with.
>
>Important clue: DO NOT NAME A VARIABLE WITH A NUMBER OR SEQUENTIAL LETTER.
>
>
>


--
Perl -
"... making the easy jobs easy,
without making the hard jobs impossible."
'The Camel', 3ed

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com