in reply to Locator to Lat/Long code: works, but is inelegant

I understand your sense of something suboptimal in that first sub, because there is some repetition of code. Of course, a little repetition in a small script is not really a problem, provided that the script ends up doing the right thing.

(Repetition is nasty when you get into 100's or 1000's of lines of code, with some things being repeated multiple times -- no programmer good enough to deserve a living wage would ever do that.)

The only difference between the "alpha" and "numeric" blocks is the value that gets multiplied with your "div" value, so work that out just once, then handle the lat vs. long decision:

sub maidenhead2latlong { # convert a Maidenhead Grid location (eg FN03ir) # to decimal degrees # this code could be cleaner/shorter/clearer my @locator = split( //, uc(shift) ); # convert arg to upper case array my $lat = my $long = 0; my ( $latdiv, $longdiv ); my @divisors = ( 72000, 36000, 7200, 3600, 300, 150 ); # long,lat field size in seconds my $max = ( @locator > @divisors ) ? $#divisors : $#locator; for my $i ( 0 .. $max ) { my $val = ( int( $i/2 ) % 2 ) ? $locator[$i] : ord($locator[$i +]) - ord('A'); if ( $i % 2 ) { # lat $latdiv = $divisors[$i]; # save latdiv for later $lat += $val * $latdiv; } else { # long $longdiv = $divisors[$i]; # save longdiv for later $long += $val * $longdiv; } } $lat += ( $latdiv / 2 ); # location of centre of square $long += ( $longdiv / 2 ); return ( ( $lat / 3600 ) - 90, ( $long / 3600 ) - 180 ); }
The "for" loop there is about half as many lines as the one in the OP, and seems to produce the same output.