Reference: Used this for verification.
#20200615 Raku programming solution
use Geo::Hash;
# task example 1 : Ireland, most of England and Wales, small part of Scotland
say geo-encode(51.433718e0, -0.214126e0, 2);
# task example 2 : the umpire's chair on Center Court at Wimbledon
say geo-encode(51.433718e0, -0.214126e0, 9);
# Lake Raku is an artificial lake in Tallinn, Estonia
# https://goo.gl/maps/MEBXXhiFbN8WMo5z8
say geo-encode(59.358639e0, 24.744778e0, 4);
# Village Raku is a development committee in north-western Nepal
# https://goo.gl/maps/33s7k2h3UrHCg8Tb6
say geo-encode(29.2021188e0, 81.5324561e0, 4);
gc
gcpue5hp4
ud99
tv1y
Alternately, a roll-your-own version that will work with any Real coordinate, not just floating point values, and thus can return ridiculous precision. The geo-decode routine returns the range in which the actual value will be found; converted here to the mid-point with the interval size. Probably better to specify an odd precision so the error interval ends up the same for both latitude and longitude.
my @Geo32 = <0 1 2 3 4 5 6 7 8 9 b c d e f g h j k m n p q r s t u v w x y z>;
sub geo-encode ( Rat(Real) $latitude, Rat(Real) $longitude, Int $precision = 9 ) {
my @coord = $latitude, $longitude;
my @range = [-90, 90], [-180, 180];
my $which = 1;
my $value = '';
while $value.chars < $precision * 5 {
my $mid = @range[$which].sum / 2;
$value ~= my $upper = +(@coord[$which] > $mid);
@range[$which][not $upper] = $mid;
$which = not $which;
}
@Geo32[$value.comb(5)».parse-base(2)].join;
}
sub geo-decode ( Str $geo ) {
my @range = [-90, 90], [-180, 180];
my $which = 1;
my %Geo32 = @Geo32.antipairs;
for %Geo32{$geo.comb}».fmt('%05b').join.comb {
@range[$which][$_] = @range[$which].sum / 2;
$which = not $which;
}
@range
}
# TESTING
for 51.433718, -0.214126, 2, # Ireland, most of England and Wales, small part of Scotland
51.433718, -0.214126, 9, # the umpire's chair on Center Court at Wimbledon
51.433718, -0.214126, 17, # likely an individual molecule of the chair
57.649110, 10.407440, 11, # Wikipedia test value - Råbjerg Mile in Denmark
59.358639, 24.744778, 7, # Lake Raku in Estonia
29.2021188, 81.5324561, 7 # Village Raku in Nepal
-> $lat, $long, $precision {
say "$lat, $long, $precision:\ngeo-encoded: ",
my $enc = geo-encode $lat, $long, $precision;
say 'geo-decoded: ', geo-decode($enc).map( {-.sum/2 ~ ' ± ' ~
(abs(.[0]-.[1])/2).Num.fmt('%.3e')} ).join(', ') ~ "\n";
}
51.433718, -0.214126, 2:
geo-encoded: gc
geo-decoded: 53.4375 ± 2.813e+00, -5.625 ± 5.625e+00
51.433718, -0.214126, 9:
geo-encoded: gcpue5hp4
geo-decoded: 51.4337182 ± 2.146e-05, -0.21412611 ± 2.146e-05
51.433718, -0.214126, 17:
geo-encoded: gcpue5hp4ebnf8unc
geo-decoded: 51.43371800000523 ± 2.046e-11, -0.21412600000303 ± 2.046e-11
57.64911, 10.40744, 11:
geo-encoded: u4pruydqqvj
geo-decoded: 57.64911063 ± 6.706e-07, 10.407439694 ± 6.706e-07
59.358639, 24.744778, 7:
geo-encoded: ud99ejf
geo-decoded: 59.358444 ± 6.866e-04, 24.744644 ± 6.866e-04
29.2021188, 81.5324561, 7:
geo-encoded: tv1ypk4
geo-decoded: 29.202347 ± 6.866e-04, 81.532974 ± 6.866e-04