Math::Base36 and Amateur Radio
Amateur radio stations worldwide are identified by a callsign. Callsigns have a prefix and suffix. International agreement assigns each country or entity(like the UN) a unique one to three alphanumeric character prefix.
Why do I care? I have a Tk script that looks up callsign information on QRZ.COM(via an XML interface). QRZ requires complete callsigns to make a match. You don't always catch a complete callsign. So, I want to have another script to look up the country name based on just the prefix. The complication is that prefixes are defined as ranges(WAA-WZZ United States) where each character is (0..9)(A..Z). There are many thousands of prefixes.
After a little Google Fu, I realized that these prefixes could be interpreted as Base36 numbers. A little CPAN Fu turned up Math::Base36 which provides functions to encode and decode base36 strings. With this I could convert the text based prefixes into numeric ranges.
The prefix data was downloaded from ARRL.ORG(300+ rows) and edited to move the (0..9)XX rows ahead of the (A..Z)XX rows and to clean up a few descriptions. This list is in sort order.
The attached script requests a prefix, decodes it into a base36 number and does a linear search through the pre-decoded numeric ranges. It's plenty fast for my needs. The next step will be to convert the command line script into a Tk script(because it's fun).
#! /usr/bin/perl # base36test.pl - Test of looking-up Amateur Radio DXCC entities via c +allsign prefixes # lu6.pl requires a complete callsign to query QRZ +.com, # but also returns more details. This script w +as developed # to be used when only a partial callsign was +heard # Callsigns are composed of the characters [0..9] +[A..Z] # Prefixes can be 1,2, or 3 characters # Each country or entity has been assigned a uniqu +e prefix # It was noticed that combinations of these ranges + may be # interpreted as Base36 numbers. This provided + for a # simplified numerical search # A table of DXCC entities(dxcc.txt) was downloade +d from ARRL.COM # and was cleaned up a little and arranged in +alphabetical order. # builddxcctable() creates a Base36 encoded versio +n of this table # where beginning and ending prefix strings ar +e converted # to Base36 numbers for comparison against a B +ase36 encoded prefix # finddxcc() searches the Base36 table and returns + the entity name # linear search through the table ranges(300 + +/- rows) # # James M. Lynes Jr. - KE4MIQ # Created: February 22, 2023 # Last Modified: 02/22/2023 - First version created # - command line version # # Environment: Ubuntu 22.04LTS # Notes: Install Perl Tk and Non-Core Modules # sudo apt update # sudo apt install perl-tk # cpanm Math::Base36 # # DXCC - DX(long distance) Century Club # A certificate earned by contacting 100 countri +es/entities # Outside of your home country # use Math::Base36 ':all'; use Text::Tabs; my @dxcc; # DXCC table builddxcctable(); # Build table of + DXCC entities while(1) { # Loop for entit +y entry print "\nEnter a DXCC Prefix(ke): "; my $prefix = <STDIN>; chomp($prefix); if(length($prefix) == 1) { # Entries may be + 1,2, or 3 characters $prefix = uc($prefix) . 'AA'; # Pad with A' +s TO 3 characters } elsif(length($prefix) == 2) { $prefix = uc($prefix) . 'A'; } my $base36num = decode_base36($prefix); # Encode entry i +nto Base36 my $entity = finddxcc($base36num); # Search for ent +ry print "$entity\n"; } # # Read dxcc.txt file and build the DXCC lookup table in Base36 # sub builddxcctable { open(my $fh, '<', 'dxcc.txt'); while(defined(my $line = <$fh>)) { chomp($line); $line = expand($line); my $len = length($line) -1; my $bcall = substr($line, 0, 3); my $ecall = substr($line, 4, 3); my $desc = substr($line ,16, $len); # Entity name my $dbcall = decode_base36($bcall); # Base36 prefix + range beginning my $decall = decode_base36($ecall); # Base36 prefix + range end push(@dxcc, [$dbcall, $decall, $desc]); } close($fh); } # # Linear search the DXCC table for a match with entered Base36 encoded + prefix # sub finddxcc { my($base) = @_; my $dx; for my $i(0 .. $#dxcc) { next if($dxcc[$i][1] < $base); $dx = $dxcc[$i][2]; last; } return $dx; }
James
There's never enough time to do it right, but always enough time to do it over...
|
|---|