The format of the code is almost unreadable because HTML doesn't support tabs easily, but it should still run as is in an Unix environment (Mac OSX is Unix so it will run in the terminal application). There is a Perl interpreter for MS Windows, but I think the first line if this code will then have to be modified or eliminated. Note that the variable $huPrint determines what is printed.
The style of this code is certainly not professional, but I don't expect to get a job writing Pearl anyway. At least it gives you an idea of what a program is and how much work it takes to read "human readible" text and convert it into a form that allows calculations to be made.
#!/usr/bin/perl -w
# Perl program aTides v.5 1-Mar-05 M. Konrad
# reads NOAA tide level file
# gets best fit line: X = time (yearDay) Y = tide number (jTide)
# $hr, $min, $AMPM unpacked from "human" time
$iMonth = -1; # month index (0 - 11)
@moName = '0'x12; # month names from NOAA file
@moLen = '0'x12; # month lengths also from file (thus works on leap years)
$firstDS = 93; # first yearDay of Day Light savings time
$lastDS = 302; # last yearDay of Day Light savings time
$moDay = -1; # day of month
$moOffSet = 0; # days to start of current month
$PmoDay = 0; # previous $moDay
@dayTime = '0'x3;
$yearDay = -1; # X day of year; will actually start at 0
$jTide = -1; # Y (global tide index); will actually start at 0
$NjTides = 0; # number of tides
@tideType = 0x1500; # L or H
@tideTime = 0x1500; # X (time in year-days (0 based))
@tideDif = 0x1500; # actual - avg time (min)
$StimeDay = 0; # sum of times
$SjTide = 0; # sum of tide indexes
$AtimeDay = 0; # avg timeDay
$DtimeDay = 0; # tideTime - AtimeDay
$SDtimeDay2 = 0; # sum (DtimeDay squared)
$slope = 0; # slope of the fitted line (tides / day)
$zTide = 0; # intercept of fitted line with Y axis (jTide)
$rTime = 0; # regression time (from iTide and fitted line)
$huPrint = 1;
$inFileName = $ARGV[0]; # get NOAA tide file from input line
print "Reading tide data from file: $inFileName\n\n";
# ========= conversion from the NOAA file to YearDay.time is more complicated and sufficently
# different from than reverse conversion needed here that they are embedded in the main
# body of the code. The subroutine huTime just converts from YearDay. to YearDay/hr/min
#
# ============================================== read tide data from NOAA file
while (<>) { # read file until no more lines
@Line = split; # words separated by white spaces -> array
$nWords = scalar(@Line); # number of words in this line
if(($nWords == 1) && ($Line[0] =~ /\w/)) { # new month
$moName[++$iMonth] = $Line[0];
}
if($nWords > 5) { # can be tide data
if($Line[0] =~ /(\d\d)\/(\d\d)\/(\d\d\d\d)/){ # valid date
if( ($nWords - 2)%4 != 0 ) { # must be sets of 4
print "ilegal line at: ",$Line[0],"\n";
exit 0;
}
$yearDay++; # process this day-line
$moLen[$iMonth]++;
$nTides = ($nWords - 2)/4;
for($iTide=0; $iTide<$nTides; $iTide++) { # process this tide
$jTide++;
$iWord = 2 + 4*$iTide;
($hr, $colon, $min, $AMPM) = unpack ("A2 A A2 A2", $Line[$iWord]);
if(($AMPM eq "PM") && ($hr != 12)) {$hr = $hr + 12;}
if(($AMPM eq "AM") && ($hr == 12)) {$hr = 0;}
$timeDay = $yearDay + ($hr/24) + ($min/1440);
# if daylight savings, convert to standard (standard is less by one hour)
if(($yearDay >= $firstDS) && ($yearDay <= $lastDS)) {$timeDay -= 0.041667;}
$tideTime[$jTide] = $timeDay;
$iWord = $iWord+3;
$tideType[$jTide] = $Line[$iWord];
$StimeDay += $timeDay; # sums used to get avg tides
$SjTide += $jTide;
} # end of tide
} # end of day-line
} # end of non-empty line
} # end of tide file
$NjTides = $jTide + 1;
if($NjTides == 0) { # no tide data: exit
print "can not read tide data from file\n";
exit 0;
}
# ============================================= calc origin and slope of avg tide times
$AtimeDay = $StimeDay / $NjTides; # see "Numerical Recipes in C, 2nd ed" p664
for($iTide=0; $iTide<$NjTides; $iTide++){
$DtimeDay = $tideTime[$iTide] - $AtimeDay;
$SDtimeDay2 += $DtimeDay * $DtimeDay;
$slope += $DtimeDay * $iTide;
}
$slope /= $SDtimeDay2;
$zTide = ($SjTide - $StimeDay * $slope) / $NjTides;
# ================================================= write out tides in "human" format
$iMonth = 0;
print $moName[0],"\n"; # first month
for($iTide=0; $iTide<$NjTides; $iTide++) { # loop through all tides
$rTime = ($iTide - $zTide) / $slope; # get avg and real-avg times
$tideDif[$iTide] = 1440 * ($rTime - $tideTime[$iTide]);
# -------------- thus $tideDif is to be added to the real time to get the avg tide time
if($huPrint == 1)
{
@dayTime = huTime ($tideTime[$iTide]); # decode year-day time number
$moDay = $dayTime[0] - $moOffSet; # find month-day
if($moDay > $moLen[$iMonth]) { # new month
$iMonth++;
print "\n\n",$moName[$iMonth],"\n";
if($iMonth > 0) {
$moOffSet += $moLen[$iMonth-1];
}
$moDay = $dayTime[0] - $moOffSet;
$PmoDay = $moDay -1;
}
if($moDay > $PmoDay) { # new day means new line
print "\n";
printf ("%02d ",$moDay);
$PmoDay = $moDay;
}
printf (".....%s",$tideType[$iTide]); # print "H" or "L"
printf (" %02d%02d ",$dayTime[1],$dayTime[2]); # print hr min
printf ("%04d",$tideDif[$iTide]);
}
else
{
printf ("%8.3f%6d\n",$tideTime[$iTide],$tideDif[$iTide]);
}
}
print "\n";
close ARGV;
sub huTime { # given fractional daytime return day & 24 hr time
$day = int $_[0];
$Fhour = 24 * ($_[0] - $day);
$day++;
$hour = int $Fhour;
$Fmin = 60 * ($Fhour - $hour);
$min = int $Fmin;
return ($day,$hour,$min);
}