Three word location: Difference between revisions

Content added Content deleted
(Added Perl example)
Line 449: Line 449:
latitude = -81.5638 longitude = 28.3852
latitude = -81.5638 longitude = 28.3852
</pre>
</pre>

=={{header|Perl}}==
{{trans|Raku}}
<lang perl>use strict;
use warnings;
use feature 'say';
use bignum; # without this, round-trip results not exact

use Math::AnyNum 'polymod';

# SYNTHETICS HANDLING

my @synth;
push @synth, join '', @$_ for map { [split /:/] } glob '{b,d,f,h,j,k,l,m,n,p,r,s,t,w,y,z}:{a,e,i,o,u}';
my(%htnys,$c); $htnys{$_} = $c++ for @synth;
my $exp = @synth;
my $prec = 10_000;

sub bin2dec { unpack('N', pack('B32', substr('0' x 32 . shift, -32))) }

sub synth { join '', reverse @synth[polymod(shift() + int(rand 18) * 28126, $exp, $exp) ] }

sub thnys {
my @n = @htnys{ ${shift() } =~ /(..)(..)(..)/ }; # NB notation on hash slice: % -> @
($n[2] + $n[1]*$exp + $n[0]*$exp**2) % 28126
}

# ENCODE / DECODE

sub w_encode {
my($lat, $lon, $f) = @_;
$f = \&synth unless $f;
my @words;
my $bits = sprintf '%021b%022b', int(($lat+90)*$prec), int(($lon+180)*$prec);
push @words, &$f(bin2dec($_)) for $bits =~ / (.{15}) (.{14}) (.{14}) /x;
join ' ', @words
}

sub w_decode {
my($triplet, $f) = @_;
my @t = split ' ', $triplet->[0];
$f = \&thnys unless $f;
my $s = '%015b';
my $bin = sprintf($s, &$f(\$t[0])) . substr(sprintf($s, &$f(\$t[1])), 1) . substr(sprintf($s, &$f(\$t[2])), 1);
(bin2dec(substr($bin,0,21))/$prec - 90), (bin2dec(substr($bin,21))/$prec - 180)
}

# TESTING

for ([ 51.4337, -0.2141, 'Wimbledon'],
[ 21.2596, -157.8117, 'Diamond Head crater'],
[-55.9652, -67.2256, 'Monumento Cabo De Hornos'],
[ 71.170924, 25.782998, 'Nordkapp'],
[ 45.762983, 4.834520, 'Café Perl, Lyon'],
[ 48.391541, -124.736731, 'Cape Flattery Lighthouse, Tatoosh Island'],
) {
my($lat, $lon, $description) = @$_;
my @words = w_encode $lat, $lon;
my @index = w_encode $lat, $lon, sub { shift };
printf "Coordinates: %s, %s (%s)\n To Index: %s\n To 3-word: %s\nFrom 3-word: %s, %s\n From Index: %s, %s\n\n",
$lat, $lon, $description, join(' ',@index), join(' ',@words), w_decode(\@words), w_decode(\@index, sub { ${shift()} });
}</lang>
{{out}}
<pre>Coordinates: 51.4337, -0.2141 (Wimbledon)
To Index: 22099 365 12003
To 3-word: yotema ritomi rahiku
From 3-word: 51.4337, -0.2141
From Index: 51.4337, -0.2141

Coordinates: 21.2596, -157.8117 (Diamond Head crater)
To Index: 17384 5133 8891
To 3-word: hayibi batufo jokube
From 3-word: 21.2596, -157.8117
From Index: 21.2596, -157.8117

Coordinates: -55.9652, -67.2256 (Monumento Cabo De Hornos)
To Index: 5317 15428 13632
To 3-word: fubeha zidura nerupe
From 3-word: -55.9652, -67.2256
From Index: -55.9652, -67.2256

Coordinates: 71.170924, 25.782998 (Nordkapp)
To Index: 25182 15741 9829
To 3-word: zorenu jaboda kiyika
From 3-word: 71.1709, 25.7829
From Index: 71.1709, 25.7829

Coordinates: 45.762983, 4.83452 (Café Perl, Lyon)
To Index: 21212 15728 13337
To 3-word: ludefu bimepo demojo
From 3-word: 45.7629, 4.8345
From Index: 45.7629, 4.8345

Coordinates: 48.391541, -124.736731 (Cape Flattery Lighthouse, Tatoosh Island)
To Index: 21623 11041 11960
To 3-word: kakofo radaki habuho
From 3-word: 48.3915, -124.7368
From Index: 48.3915, -124.7368</pre>


=={{header|Phix}}==
=={{header|Phix}}==