-3

Suppose a set of numbers is given in a file number_list.txt. Find the sum of the numbers from the file in the following categories:

 Sum of all 1 digits numbers
 Sum of all 2 digits numbers
 Sum of all 3 digits numbers
 Sum of all numbers starting with a digit 7
 Sum of all number ending with a digit 8

write code in perl to find the above sums

example: If we have "number_list.txt"

           23 
           258 
           1 
           24 
           57 
           76 
           85 
           72 
           4  
           654 
           958 
           6 
           46 
           358 

Then we need to get answer like this

             Sum of all 1 digits numbers
                   1 + 4 + 6 = 11

             Sum of all 2 digits numbers
                   23 + 24 + 57 + 76 + 85 + 72 + 46 = 383

             Sum of all 3 digits numbers
                   258 + 654 + 958 + 358 = 2228

             Sum of all numbers starting with a digit 7
                   76 + 72 = 148

             Sum of all number ending with a digit 8
                   258 + 358 + 958 = 1574

And I have done so far.

   #!/usr/bin/perl
   use strict;
   use warnings;

   my $filename = "numbers.txt";
   open( my $fh, '<', $filename ) or die "Can't open $filename: $!";
   my @array1;
   my @array2;
   my @array3;
   my @array4;

   print "\n \n";
   while ( my $line = <$fh> ) {
    #if ( length($line) == 1)  
    #{

    #   push (@array1, $line);
    #}
    if ( length($line) == 2)
    {
        push (@array2, $line);
    }
    if ( length($line) == 3)
    {
        push (@array3, $line); 
    }
    if ( length($line) == 4)
    {
        push (@array4, $line); 
    }
} 
#print "\n Sum of all  digits numbers\n \n";
#for each (@array1) {
#           print "$_";
#   }
my $sum1 = 0;
my $sum2 = 0;
my $sum3 = 0;

print "\n \n Sum of all 1 digits numbers of:\n \n"; 
for each my $num2 (@array2) {
        print "$num2";
        $sum1 = $sum1 + $num2; 
    }
    print "\n Sum = $sum1";

print "\n \n Sum of all 2 digits numbers of:\n \n"; 
for each my $num3 (@array3) {
        print "$num3";
        $sum2 = $sum2 + $num3;
    }
    print "\n Sum = $sum2";

print "\n \n Sum of all 3 digits numbers of:\n \n"; 
foreach my $num4(@array4) {
        print "$num4";
        $sum3 = $sum3 +$num4;
    }
    print "\n Sum = $sum3";

So I have trouble with to make this program in simple way. Is there any simple method have to do this program ?

And also I have trouble with getting

   Sum of all numbers starting with a digit 7
   Sum of all number ending with a digit 8

3 Answers3

0

Firstly, import sum from List::Util to make summing arrays of numbers easier.

If it's a relatively small file (which it probably is), things are a lot easier if you pull them all into an array first and grep them as you need them

so after you have opened you file...

use List::Util 'sum';

my @nums = <$fh>;
chomp @nums;    # Remove trailing newlines;

my @values;

print "Sum of all 3 digits numbers\n";
@values = grep { length == 3 } @nums;
print join( ' + ', @values ), ' = ', sum( @values ), "\n";

print "Sum of all numbers starting with a digit 7\n";
@values = grep { index( $_, 7 ) == 0 } @nums;
print join(' + ', @values), ' = ', sum( @values ), "\n";

print "Sum of all numbers ending with a digit 8\n";
@values = grep { index( reverse($_), 8 ) == 0 } @nums;
print join(' + ', @values), ' = ', sum( @values ), "\n";

Ideally you'd put any duplicate code (like that printing of the sums) inside a sub. Every time you retype the same code, you increase your chances of making an error.

If you want to do it by streaming through the file, then you will have to keep track of multiple arrays as you go

my (@len_3, @len_4, @len_5, @start_7, @end_8); 

while (my $n  = <$fh>) {
    if ( length $n == 3 ) { 
        push @len_3, $n; 
    }   
    # ...
    if ( index($n, 7) == 0 ) { 
        push @start_7, $nl=;
    }   
}

print "Sum of all 3 digits numbers\n";
print join(' + ', @len_3), ' = ', sum( @len_3 ), "\n";
# ...

The more 'cases' you have, the more arrays you have to keep track of. There are better ways to do this - such as storing array references as hash values - but if your just learning, that may be a little confusing right now.

elcaro
  • 2,227
  • 13
  • 15
0

I'd tackle it like this:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use List::Util qw ( sum );

my %numbers;
my %startswith;

open( my $fh, '<', "numbers.txt") or die $!;

while (<$fh>) {
    my ( $num, $start_num ) = m|((\d)\d*)|;
    push( @{ $numbers{length($num)} }, $num );
    push( @{ $startswith{$start_num} },  $num );
}
close ( $fh );
print Dumper \%numbers;
print Dumper \%startswith;

foreach my $len ( sort keys %numbers ) {
    print "Sum of all $len digits numbers:\n";
    print join( "+", @{ $numbers{$len} } ), "\n";
    print sum ( @{$numbers{$len}}),"\n";
}
foreach my $first ( sort keys %startswith ) {
    print "Sum of all numbers starting with $first:\n";
    print join( "+", @{ $startswith{$first} } ), "\n";
    print sum ( @{ $startswith{$first} } ), "\n";
}

This gives output of:

Sum of all 1 digits numbers:
1+4+6
11
Sum of all 2 digits numbers:
23+24+57+76+85+72+46
383
Sum of all 3 digits numbers:
258+654+958+358
2228
Sum of all numbers starting with 1:
1
1
Sum of all numbers starting with 2:
23+258+24
305
Sum of all numbers starting with 3:
358
358
Sum of all numbers starting with 4:
4+46
50
Sum of all numbers starting with 5:
57
57
Sum of all numbers starting with 6:
654+6
660
Sum of all numbers starting with 7:
76+72
148
Sum of all numbers starting with 8:
85
85
Sum of all numbers starting with 9:
958
958

And will implicitly support arbitrary length numbers. (You could use List::Util for the sum, but I thought I'd offer a non-module.

Sobrique
  • 52,974
  • 7
  • 60
  • 101
-1

You can done all with regex.

while( <$fh> ) {
   $sum1+= $_   if /^\d$/;
   $sum2+= $_   if /^\d{2}$/;
   $sum3+= $_   if /^\d{3}$/;
   $sum7+= $_   if /^7\d*$/;
   $sum8+= $_   if /^\d*8$/;
}

if you put number to list, you can print them as:

local $" =  ' + ';
print "@sum1 = $sum1";
Eugen Konkov
  • 22,193
  • 17
  • 108
  • 158