title: How to parse a file, create records and perform manipulations on records including frequency of terms and distance calculations
body: <p>I'm a student in an intro Perl class, looking for suggestions and feedback on my approach to writing a small (but tricky) program that analyzes data about atoms. My professor encourages forums. I am not advanced with Perl subs or modules (including Bioperl) so please limit responses to an appropriate 'beginner level' so that I can understand and learn from your suggestions and/or code (also limit "Magic" please).  </p>
  
  <p>The requirements of the program are as follows:  </p>
  
  <blockquote>
    <ol>
    <li><p>Read a file (containing data about Atoms) from the command line &amp; create an array of atom records (one record/atom per newline). For each record the program will need to store:  </p>
    
    <blockquote>
      <p>• The atom's serial number (cols 7 - 11)<br>
      • The three-letter name of the amino acid to which it belongs (cols 18 - 20)<br>
      • The atom's three coordinates (x,y,z) (cols 31 - 54 )<br>
      • The atom's one- or two-letter element name (e.g. C, O, N, Na) (cols 77-78 )</p>
    </blockquote></li>
    <li><p>Prompt for one of three commands: freq, length, density d (d is some number):  </p>
    
    <blockquote>
      <p>• freq - how many of each type of atom is in the file (example Nitrogen, Sodium, etc would be displayed like this:  N: 918  S: 23<br>
      • length - The distances among coordinates<br>
      • density d (where d is a number) - program will prompt for the name of a file to save computations to and will containing the distance between that atom and every other atom. If that distance is less than or equal to the number d, it increments the count of the number of atoms that are within that distance, unless that count is zero into the file. The output will look something like:<br>
      1:  5<br>
      2:  3<br>
      3:  6<br>
      ... (very big file) and will close when it finishes.</p>
    </blockquote></li>
    </ol>
  </blockquote>
  
  <p>I'm looking for feedback on what I have written (and need to write) in the code below. I especially appreciate any feedback in how to approach writing my subs. I've included sample input data at the bottom.</p>
  
  <p>The program structure and function descriptions as I see it:</p>
  
  <pre><code>$^W = 1; # turn on warnings
  use strict; # behave!
  
  my @fields;
  my @recs;
  
  while ( &lt;DATA&gt; ) {
   chomp;
   @fields = split(/\s+/);
   push @recs, makeRecord(@fields);
  }
  
  for (my $i = 0; $i &lt; @recs; $i++) {
   printRec( $recs[$i] );
  }
      my %command_table = (
   freq =&gt; \&amp;freq,
   length =&gt; \&amp;length,
   density =&gt; \&amp;density,
   help =&gt; \&amp;help, 
   quit =&gt; \&amp;quit
   );
  
  print "Enter a command: ";
  while ( &lt;STDIN&gt; ) {
   chomp; 
   my @line = split( /\s+/);
   my $command = shift @line;
   if ($command !~ /^freq$|^density$|length|^help$|^quit$/ ) {
      print "Command must be: freq, length, density or quit\n";
      }
    else {
      $command_table{$command}-&gt;();
      }
   print "Enter a command: ";
   }
  
  sub makeRecord 
      # Read the entire line and make records from the lines that contain the 
      # word ATOM or HETATM in the first column. Not sure how to do this:
  {
   my %record = 
   (
   serialnumber =&gt; shift,
   aminoacid =&gt; shift,
   coordinates =&gt; shift,
   element  =&gt; [ @_ ]
   );
   return\%record;
  }
  
  sub freq
      # take an array of atom records, return a hash whose keys are 
      # distinct atom names and whose values are the frequences of
      # these atoms in the array.  
  
  sub length
      # take an array of atom records and return the max distance 
      # between all pairs of atoms in that array. My instructor
      # advised this would be constructed as a for loop inside a for loop. 
  
  sub density
      # take an array of atom records and a number d and will return a
      # hash whose keys are atom serial numbers and whose values are 
      # the number of atoms within that distance from the atom with that
      # serial number. 
  
  sub help
  {
      print "To use this program, type either\n",
            "freq\n",
            "length\n",
            "density followed by a number, d,\n",
            "help\n",
            "quit\n";
  }
  
  sub quit
  {
   exit 0;
  }
  
  # truncating for testing purposes. Actual data is aprox. 100 columns 
  # and starts with ATOM or HETATM.
  __DATA__
  ATOM   4743  CG  GLN A 704      19.896  32.017  54.717  1.00 66.44           C  
  ATOM   4744  CD  GLN A 704      19.589  30.757  55.525  1.00 73.28           C  
  ATOM   4745  OE1 GLN A 704      18.801  29.892  55.098  1.00 75.91           O 
  </code></pre>