Reputation: 351
My question in Perl is like this:
Read a series of employee numbers and daily working hours from standard input, one set perl line.The employee number and the hours worked should be separated by a space. Use hashes and calculate the total number of hours worked and the average number of hours per work period. Print out a report by sorted employee number, the number of work periods, the total hours worked, and the average number of hours per work period. Assume that some of the employees are on a part-time schedule and do not work the same number of days or hours as regular employees.
My script is:
#!/usr/bin/perl
use strict;
use warnings;
my @series = qw(41234 9 67845 8 32543 10 84395 7 57543 9 23545 11);
my $workper = 3;
my %empwork;
while (my $series = shift @series) {
my $nums = shift @series;
$empwork{$series} += $nums;
}
my $tot;
foreach (sort keys %empwork) {
$tot += $empwork{$_};
}
my $avg = $tot/$workper;
print "Sorted Employee Numbers:\n";
foreach my $empnum(sort keys %empwork) {
print "$empnum\n";
}
print "The number of work periods is $workper\n";
print "Total number of hours is $tot\n";
print "Average number of hours per work period is $avg\n";
My Output is:
Sorted Employee Numbers:
23545
32543
41234
57543
67845
84395
The number of work periods is 3
Total number of hours is 54
Average number of hours per work period is 18
Can anyone please tell me whether I have done anything wrong in the script. If yes, please help. Thanks in advance.
If I use loop through %empwork once like this:
foreach my $empnum(sort keys %empwork) {
$tot += $empwork{$_};
print "$empnum\n";
}
Then I will get the output as:
Sorted Employee Numbers:
23545
32543
41234
57543
67845
84395
The number of work periods is 3
Total number of hours is 0
Average number of hours per work period is 0
Use of uninitialized value in hash element at /tmp/135043087931085.pl line 16.
Use of uninitialized value in addition (+) at /tmp/135043087931085.pl line 16.
Use of uninitialized value in hash element at /tmp/135043087931085.pl line 16.
Use of uninitialized value in addition (+) at /tmp/135043087931085.pl line 16.
Use of uninitialized value in hash element at /tmp/135043087931085.pl line 16.
Use of uninitialized value in addition (+) at /tmp/135043087931085.pl line 16.
Use of uninitialized value in hash element at /tmp/135043087931085.pl line 16.
Use of uninitialized value in addition (+) at /tmp/135043087931085.pl line 16.
Use of uninitialized value in hash element at /tmp/135043087931085.pl line 16.
Use of uninitialized value in addition (+) at /tmp/135043087931085.pl line 16.
Use of uninitialized value in hash element at /tmp/135043087931085.pl line 16.
Use of uninitialized value in addition (+) at /tmp/135043087931085.pl line 16.
I tried the program as below. But its not working.
#!/usr/bin/perl
use strict;
use warnings;
my @series = qw(41234 9 67845 8 32543 10 84395 7 57543 9 23545 11 23545 1 23545 2 23545 6);
my $total_periods = 0;
my $total_hours = 0;
my %empwork;
while (my $series = shift @series)
{
my $nums = shift @series;
$empwork{$series} += $nums;
}
print "Sorted Employee Numbers:\n";
foreach my $empnum(sort keys %empwork)
{
my $periods=0;
$periods++;
my $hours = 0;
$hours += $empwork{$empnum};
my $avg = $hours/$periods;
$total_periods += $periods;
$total_hours += $hours;
print "$empnum\n$periods periods\n$hours hours\n$avg average\n\n";
}
my $grand_avg = $total_hours/$total_periods;
print "The number of work periods is $total_periods\n";
print "Total number of hours is $total_hours\n";
print "Average number of hours per work period is $grand_avg\n";
Where am I going wrong?
Upvotes: 0
Views: 664
Reputation: 6566
This snippet of code has a problem:
foreach my $empnum(sort keys %empwork) {
$tot += $empwork{$_};
print "$empnum\n";
}
You are using $empnum
as the loop iterator variable, but then referencing $empwork{$_}
. That is why you get the errors. Simply replace that with $empwork{$empnum}
and you will be fine.
The rest of the code that you show above works fine. However, a few suggestions:
Will there be duplicate employee numbers in your source array? The sample data doesn't show any. If there are no duplicates, you can simply do this to populate the hash, and do away with your while
loop:
%empwork = @series;
Also, in this portion:
foreach (sort keys %empwork) {
$tot += $empwork{$_};
}
There is no reason to sort the keys when you are not doing something order dependent. It just makes the interpreter do unnecessary work. In this case, you don't even need the keys; you are only interested in adding up the values. So, you could do this, which is more efficient:
foreach (values %empwork)
{
$tot += $_;
}
(Of course, you could combine the two loops instead).
Update: here is the complete corrected code that I believe will meet all of your requirements.
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw/sum/;
my @series = qw(41234 9 67845 8 32543 10 84395 7 57543 9 23545 11 23545 1 23545 2 23545 7);
my $total_periods = 0;
my $total_hours = 0;
my %empwork;
while (my $series = shift @series) {
#For each employee, save a list of the number of times they worked
push @{$empwork{$series}}, shift @series;
}
print "Sorted Employee Numbers:\n";
foreach my $empnum(sort keys %empwork) {
my $periods = @{ $empwork{$empnum} };
my $hours = sum(@{ $empwork{$empnum} });
my $avg = $hours/$periods;
$total_periods += $periods;
$total_hours += $hours;
print "$empnum\n$periods periods\n$hours hours\n$avg average\n\n";
}
my $grand_avg = $total_hours/$total_periods;
print "The number of work periods is $total_periods\n";
print "Total number of hours is $total_hours\n";
print "Average number of hours per work period is $grand_avg\n";
Upvotes: 2