Search code examples
perlhashmatchsubroutine

Cannot get the correct calculation when using a Smart Match Operator


I've just been completing an assignment - I asked a question about this last week and was advised not to use a Smart Match Operator, but I have a greater grasp of it over Hashes.

Basically this subroutine is one of 4 subroutines. It Opens a file containing 125,000 mammals, loads it into a list, loops over the list and splits it into scalars. Loads parts of the split list into a calculator which returns a value ($Calcdist).

What I want this to do it basically count the number of species in the area which is does do. somewhat. The data I'm using at the moment is:

$File =("Mammal.txt");
$Distance = 5.0;
$Lat = 51.75;
$Long = -1.25;

With this information it tells me there are 95 animals in that area (using another subroutine) This subroutine should tell me that there are 30 unique species but instead it prints the number 9.

Where abouts am I going wrong? Is my 'if' and 'else' incorrect? I know there are much better ways of coding perl but this is just the way I have been taught.

sub BiodiversityCount ($$$$)
     {
          my ($Filename, $Distance, $Lat1, $Lon1) = @_;
          my ($Line, $Index, $CalcDist, $Counter, $Counter2, $Index2);
          my (@List, @Part, @Species);
          open (INF, "<", $Filename) or die ("Cannot open Mammal.txt\n");
          @List = <INF>;
          close (INF);
          for ($Index=0;$Index<@List;$Index++)
               {
                   @Part = split ("\t", $List[$Index]);
                   $CalcDist = CalculateDistance ($Lat1, $Lon1, $Part[1], $Part[2]);
                   if ($CalcDist<$Distance)
                       {                    
                           if ($Part[0] ~~ @Species)
                               {
                               $Counter++
                               }
                           else
                               {
                               @Species = $Part[0]; 
                               }                                    
                       }
              }
          #printf @Species;
          print("The number of unique species found upto $Distance km from $Lat1, $Lon1 is: $Counter\n");
          #Number of Unique species found in an area
          #Smart match operator
          #Hashes - declared using my %___
      }
BiodiversityCount ($File, $Distance, $Lat, $Long);

Test data:

Muntiacus reevesi
Muntiacus reevesi
Apodemus flavicollis
Mustela erminea
Lepus europaeus
Apodemus sylvaticus
Sciurus carolinensis
Talpa europaea
Arvicola amphibius
Rhinolophus ferrumequinum
Arvicola amphibius
Muntiacus reevesi
Apodemus sylvaticus
Sciurus carolinensis
Sciurus carolinensis
Sorex araneus
Erinaceus europaeus
Sciurus vulgaris
Vulpes vulpes
Clethrionomys glareolus
Sorex araneus
Meles meles
Arvicola amphibius
Microtus agrestis
Vulpes vulpes
Nyctalus noctula
Erinaceus europaeus
Neomys fodiens
Meles meles
Erinaceus europaeus
Capreolus capreolus
Pipistrellus pipistrellus sensu lato
Micromys minutus
Rattus norvegicus
Sorex minutus
Plecotus
Erinaceus europaeus
Muntiacus reevesi
Vulpes vulpes
Mustela erminea
Oryctolagus cuniculus
Dama dama
Erinaceus europaeus
Talpa europaea
Muntiacus reevesi
Muntiacus reevesi
Sciurus carolinensis
Vulpes vulpes
Sorex minutus
Talpa europaea
Talpa europaea
Muntiacus reevesi
Muntiacus reevesi
Muntiacus reevesi
Mustela vison
lethrionomys glareolus
Microtus agrestis
Sciurus vulgaris
Mustela nivalis
Apodemus sylvaticus
Meles meles
Meles meles
Vulpes vulpes
Capreolus capreolus
Mustela nivalis
Mustela putorius
Microtus agrestis
Sorex araneus
Sorex minutus
Muscardinus avellanarius
Muntiacus reevesi
Sciurus carolinensis
Dama dama
Muntiacus reevesi
Talpa europaea
Muntiacus reevesi
Microtus agrestis
Dama dama
Microtus agrestis
Talpa europaea
Arvicola amphibius
Muntiacus reevesi
Muntiacus reevesi
Muntiacus reevesi
Sorex minutus
Vulpes vulpes
Dama dama
Talpa europaea
Apodemus sylvaticus
Sorex araneus
Microtus agrestis
Lepus europaeus
Sorex minutus
Neomys fodiens
Vulpes vulpes

Solution

  • You might want a hash to count unique species. I made an adjustment to your code which uses a hash, %species_count. There are other changes you might make, but for now, I think this hash will get you what you want. (I also fudged $CalcDist = 1;#CalculateDistance ($Lat1, $Lon1, $Part[1], $Part[2]); to run the script, just change it back to what it was originally)

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my $File =("Mammal.txt");
    my $Distance = 5.0;
    my $Lat = 51.75;
    my $Long = -1.25;
    
    sub BiodiversityCount ($$$$)
         {
              my ($Filename, $Distance, $Lat1, $Lon1) = @_;
              my ($Line, $Index, $CalcDist, $Counter, $Counter2, $Index2);
              my (@List, @Part, %species_count);
              #open (INF, "<", $Filename) or die ("Cannot open Mammal.txt\n");
              chomp(@List = <DATA>);
              #close (INF);
              for ($Index=0;$Index<@List;$Index++)
                   {
                       @Part = split ("\t", $List[$Index]);
                       $CalcDist = 1;#CalculateDistance ($Lat1, $Lon1, $Part[1], $Part[2]);
                       if ($CalcDist<$Distance)
                           {
                               $species_count{$Part[0]}++;
                           }
                  }
              #printf @Species;
              #print("The number of unique species found upto $Distance km from $Lat1, $Lon1 is: $Counter\n");
              print("The number of unique species found upto $Distance km from $Lat1, $Lon1 is: ",  scalar keys %species_count, "\n");
              #Number of Unique species found in an area
              #Smart match operator
              #Hashes - declared using my %___
          }
    BiodiversityCount ($File, $Distance, $Lat, $Long);
    
    __DATA__
    Muntiacus reevesi
    Muntiacus reevesi
    Apodemus flavicollis
    Mustela erminea
    Lepus europaeus
    Apodemus sylvaticus
    Sciurus carolinensis
    Talpa europaea
    Arvicola amphibius
    Rhinolophus ferrumequinum
    Arvicola amphibius
    Muntiacus reevesi
    Apodemus sylvaticus
    Sciurus carolinensis
    Sciurus carolinensis
    Sorex araneus
    Erinaceus europaeus
    Sciurus vulgaris
    Vulpes vulpes
    Clethrionomys glareolus
    Sorex araneus
    Meles meles
    Arvicola amphibius
    Microtus agrestis
    Vulpes vulpes
    Nyctalus noctula
    Erinaceus europaeus
    Neomys fodiens
    Meles meles
    Erinaceus europaeus
    Capreolus capreolus
    Pipistrellus pipistrellus sensu lato
    Micromys minutus
    Rattus norvegicus
    Sorex minutus
    Plecotus
    Erinaceus europaeus
    Muntiacus reevesi
    Vulpes vulpes
    Mustela erminea
    Oryctolagus cuniculus
    Dama dama
    Erinaceus europaeus
    Talpa europaea
    Muntiacus reevesi
    Muntiacus reevesi
    Sciurus carolinensis
    Vulpes vulpes
    Sorex minutus
    Talpa europaea
    Talpa europaea
    Muntiacus reevesi
    Muntiacus reevesi
    Muntiacus reevesi
    Mustela vison
    lethrionomys glareolus
    Microtus agrestis
    Sciurus vulgaris
    Mustela nivalis
    Apodemus sylvaticus
    Meles meles
    Meles meles
    Vulpes vulpes
    Capreolus capreolus
    Mustela nivalis
    Mustela putorius
    Microtus agrestis
    Sorex araneus
    Sorex minutus
    Muscardinus avellanarius
    Muntiacus reevesi
    Sciurus carolinensis
    Dama dama
    Muntiacus reevesi
    Talpa europaea
    Muntiacus reevesi
    Microtus agrestis
    Dama dama
    Microtus agrestis
    Talpa europaea
    Arvicola amphibius
    Muntiacus reevesi
    Muntiacus reevesi
    Muntiacus reevesi
    Sorex minutus
    Vulpes vulpes
    Dama dama
    Talpa europaea
    Apodemus sylvaticus
    Sorex araneus
    Microtus agrestis
    Lepus europaeus
    Sorex minutus
    Neomys fodiens
    Vulpes vulpes