Geohash: Difference between revisions

2,686 bytes added ,  3 years ago
→‎{{header|Raku}}: Add alternate version
m (Changed to say floating point as some languags might want to use other than doubles, or may not IEEE doubles as a type.)
(→‎{{header|Raku}}: Add alternate version)
Line 275:
ud99
tv1y
</pre>
 
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.
 
<lang perl6>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.pairs.invert;
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";
}</lang>
<pre>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
</pre>
 
10,327

edits