Reference Demo. Grep/Map Demo, Too!
#!/usr/bin/perl -w

#####################  Elementary  Reference Review  #######################
#####################  Map/Grep Review, Too!!        #######################

@L1 = qw(2 4 6 8 10);
@L2 = qw(5 7 4 9 3);

@L3 =  dot_product(\@L1, \@L2);   #  Pass refs. to sub to preserve identity!
print "@L3\n";

sub dot_product
{
     my ($r1, $r2) = @_;  # Get two list references.
     my @result;

     return () if @$r1 != @$r2;  # Can't do dot product if sizes different!
     @result = map { $r1->[$_] * $r2->[$_] } 0..(@$r1 - 1);
     return @result;
}
#

%H1 = qw(Bob 4  Mary 8  Carol 10  Willie 2);
%H2 = qw(Joanne 12  Mary 13  Sue 9  Sofie 14 Bob 20);
%H3 = qw(Bill 17 Marge 6 Mary 9 Bob 2);

print join(" ", @{hash_intersections(\%H1, \%H2, \%H3)}),"\n";

sub hash_intersections
{
     my (@hrefs) = @_;
     my ($key, %keycount);

     foreach $key (map {keys %$_} @hrefs)
     {
          $keycount{$key}++;
     }

     ##  Return reference to list of keys whose count == # of hashes.
     return  [grep {$keycount{$_} == @hrefs} keys %keycount];
} 
###########################  Output Below  ##############################

10 28 24 72 30   #  Dot product
Bob Mary         #  Hash keys which all hashes have in common.
########################  Two-Dimensional Arrays  ########################

open(TWO_D, "scores") or die "Cannot open scores file!\n";
push(@scores, [split]) while <TWO_D>;  #  Push list REFERENCE into @scores.
close TWO_D;

foreach $row (@scores)   #  Print out the values row by row!!
{
     foreach $score (@$row)  #  Each element of @scores is a list REF!!
     {
          print "$score ";   #  Question:  Can I do this in ONE loop?
     }
     print "\n";
}
$colavg = avg_col1(1, @scores);  #  Average of scores in column 1.
                                 #  Zero is the first column.
print "\nAverage of column 1: $colavg\n";
$colavg = avg_col2(1, \@scores);
print "Average of column 1: $colavg\n";


sub avg_col1
{
   my ($col, @scores) = @_;
   my $sum;

   $sum = $num = 0;
   foreach $rowref (@scores)
   {
       $num++;
       $sum += $rowref->[$col];
   }
   return $sum/$num;
}


sub avg_col2
{
   my ($col, $scoreref) = @_;
   my $sum;

   $sum = $num = 0;
   foreach $rowref (@$scoreref)
   {
       $num++;
       $sum += $rowref->[$col];
   }
   return $sum/$num;
}
#############################  Program Output  ############################

67 87 89 55 76 
78 99 87 
55 66 77 88 77 66 55 

Average of column 1: 84
Average of column 1: 84

#!/usr/bin/perl -w
#######################  More Fun With References  ##########################

$ref = [];   #  Reference to an anonymous list.
             #  Question: How do I use push to add to this list?

push(@$ref, qw(a b c d));     #  Did it work?
print "@$ref\n\n";    #  Print 1.

@L1 = (1,2,3);
@L2 = qw(Hi Bye Go);
@L3 = qw(Cat Dog);
@LoL = (\@L1, \@L2, \@L3);   #  List of list references.
foreach $ref (@LoL)  #  How do I get the element at index 1 of each list?
{
      print "$ref->[1] ";  #  Same as $$ref[1] but -> notation is superior!
}                          #  Print 2.
print "\n";

#  Prints 3 and 4.
print "$LoL[0]->[1] $LoL[1]->[1] $LoL[2]->[1]\n"; #  Same as loop above!!
print "$LoL[0][1] $LoL[1][1] $LoL[2][1]\n";   #  Same as previous statement.
                                              #  Adjacent indices need not
                                              #  be separated by -> 

$ref_of_ref = [\@L1, \@L2, \@L3];  #  Reference to list of references!!
#  Prints 5 and 6
print "$ref_of_ref->[1]->[1]\n";   #  Should be "Bye".
print "$ref_of_ref->[1][1]\n\n";     #  The same.  Adjacent indices imply
                                     #  a -> so it need not be given!
@L4 = qw(foo bar snafu);  #  How do I push a reference to @L4 onto
                          #  $ref_of_ref??
push(@$ref_of_ref, \@L4); #  Did it work?
foreach $ref (@$ref_of_ref)  
{
     print "@$ref\n";     #  Print 7
}
print "\n";
#  How about a slice of a list in a 2-D list such as @LoL above?
#  Print 8.
print "@{$LoL[1]}[2,1]\n";  #  Go Bye is the result.  Why?  Because
                            #  $LoL[1] is a reference to @L2.  We must
                            #  use @ to dereference to get a list because
                            #  a slice of a list is still a list!!
#########################  Program Output Below!  ##########################
a b c d       #  Print 1

2 Bye Dog     #  Print 2
2 Bye Dog     #  Print 3
2 Bye Dog     #  Print 4
Bye           #  Print 5
Bye           #  Print 6

1 2 3         #  Print 7
Hi Bye Go
Cat Dog
foo bar snafu

Go Bye        #  Print 8