Three word location: Difference between revisions

added RPL
(→‎{{header|Raku}}: Add some randomness, use much more of the synthetics range)
(added RPL)
 
(30 intermediate revisions by 17 users not shown)
Line 1:
{{draft task}}
If one were to enter the words: 'softly affiliate activation' at the what3words.com site, the response would be a location in Walt Disney World. The latitude and longitude for that spot is 28.3852 -81.5638. Using that service enables anyone to specify any place on the Earth with three words.
Three Word Location.
Display a location on the Earth with three words derived from a
latitude longitude pair.
For:
latitude = 28.3852
longitude = -81.5638
Display: W18497 W11324 W01322
Implementation:
Build a synthetic word array of 28126, 6 character words
in the form W00000 thru W28125.
Convert latitude and longitude into positive integers.
Build a 43 bit integer containing latitude (21 bits) and longitude (22 bits).
Isolate most significant 15 bits for word 1 index.
Isolate next 14 bits for word 2 index.
Isolate next 14 bits for word 3 index.
Fetch each word from the word array.
Display the words.
Reverse the procedure and display the original latitude and longitude.
 
Task: Provide a similar solution - Display a location on the Earth with three words derived from a latitude longitude pair.
 
For: latitude = 28.3852 longitude = -81.5638 Display: W18497 W11324 W01322
 
Implementation:
 
Build an array of 28126, 6 character words in the form W00000 thru W28125.
 
Convert latitude and longitude into positive integers.
 
Build a 43 bit integer containing latitude (21 bits) and longitude (22 bits).
 
Isolate most significant 15 bits for word 1 index.
 
Isolate next 14 bits for word 2 index.
 
Isolate next 14 bits for word 3 index.
 
Fetch each word from the word array.
 
Display the words.
 
Reverse the procedure and display the original latitude and longitude.
 
Extra credit: Find a way to populate the word array with actual words.
 
 
=={{header|Ada}}==
<syntaxhighlight lang="ada">
-- Three-word location
-- J. Carter 2023 May
-- Uses the PragmAda Reusable Components (https://github.com/jrcarter/PragmARC)
 
with Ada.Text_IO;
with PragmARC.Images;
 
procedure Three_Word is
type U43 is mod 2 ** 43;
subtype Word is String (1 .. 6);
function Image is new PragmARC.Images.Modular_Image (Number => U43);
function Image is new PragmARC.Images.Float_Image (Number => Float);
Lat : constant String := "28.3852";
Long : constant String := "-81.5638";
LL_Mix : U43 := U43 ( (Float'Value (Lat) + 90.0) * 10_000.0) * 2 ** 22 + U43 ( (Float'Value (Long) + 180.0) * 10_000.0);
W3n : U43 := LL_Mix rem 2 ** 14; -- Number for 3rd word
W2n : U43 := (LL_Mix / 2 ** 14) rem 2 ** 14; -- " " 2nd "
W1n : U43 := LL_Mix / 2 ** 28; -- " " 1st "
W1 : constant Word := 'W' & Image (W1n, Width => 5, Zero_Filled => True); -- 1st word
W2 : constant Word := 'W' & Image (W2n, Width => 5, Zero_Filled => True); -- 2nd "
W3 : constant Word := 'W' & Image (W3n, Width => 5, Zero_Filled => True); -- 3rd "
begin -- Three_Word
Ada.Text_IO.Put (Item => Lat & ", " & Long & " => " & W1 & ' ' & W2 & ' ' & W3 & " => ");
-- Reverse the process
W1n := U43'Value (W1 (2 .. 6) );
W2n := U43'Value (W2 (2 .. 6) );
W3n := U43'Value (W3 (2 .. 6) );
LL_Mix := W1n * 2 ** 28 + W2n * 2 ** 14 + W3n;
Ada.Text_IO.Put_Line (Item => Image (Float (LL_Mix / 2 ** 22) / 10_000.0 - 90.0, Fore => 0, Aft => 4, Exp => 0) & ", " &
Image (Float (LL_Mix rem 2 ** 22) / 10_000.0 - 180.0, Fore => 0, Aft => 4, Exp => 0) );
end Three_Word;
</syntaxhighlight>
 
{{out}}
<pre>
28.3852, -81.5638 => W18497 W11324 W01322 => 28.3852, -81.5638
</pre>
 
=={{header|AppleScript}}==
===Index words===
When the words are index-based as in the task description, it's not necessary to generate all 28126.
<syntaxhighlight lang="applescript">on locationToWords({latitude, longitude})
-- "Convert" the coordinates to positive integers by adding enough degrees to ensure positive results,
-- multiplying by enough to left shift by four decimal places, and rounding.
set intLat to ((latitude + 90) * 10000) as integer
set intLong to ((longitude + 180) * 10000) as integer
-- Derive a 15-bit and two 14-bit values from the two results' 43 bits.
set output to {intLat div 64, intLat mod 64 * 256 + intLong div 16384, intLong mod 16384}
-- Coerce the three values to text "words" beginning with "W" and any necessary leading zeros.
repeat with thisIndex in output
set thisIndex's contents to "W" & text 2 thru 6 of ((100000 + thisIndex) as text)
end repeat
return output
end locationToWords
 
on wordsToLocation(threeWords)
set indices to {}
repeat with thisWord in threeWords
set end of indices to (text 2 thru -1 of thisWord) as integer
end repeat
set intLat to (beginning of indices) * 64 + (item 2 of indices) div 256 mod 64
set intLong to (item 2 of indices) mod 256 * 16384 + (end of indices)
return {intLat / 10000 - 90, intLong / 10000 - 180}
end wordsToLocation
 
-- Task code:
local location, threeWords, checkLocation
set location to {28.3852, -81.5638}
set threeWords to locationToWords(location)
set checkLocation to wordsToLocation(threeWords)
return {location, threeWords, checkLocation}</syntaxhighlight>
 
{{output}}
<syntaxhighlight lang="applescript">{{28.3852, -81.5638}, {"W18497", "W11324", "W01322"}, {28.3852, -81.5638}}</syntaxhighlight>
 
===Actual words===
<syntaxhighlight lang="applescript">on locationToWords({latitude, longitude}, listOfWords)
script o
property wordList : listOfWords
end script
set intLat to ((latitude + 90) * 10000) as integer
set intLong to ((longitude + 180) * 10000) as integer
set output to {intLat div 64, intLat mod 64 * 256 + intLong div 16384, intLong mod 16384}
repeat with thisIndex in output
set thisIndex's contents to item (thisIndex + 1) of o's wordList -- AppleScript indices are 1-based.
end repeat
return output
end locationToWords
 
on wordsToLocation(threeWords, listOfWords)
script o
property wordList : listOfWords
end script
set indices to {}
repeat with thisWord in threeWords
set thisWord to thisWord's contents
set i to 1
repeat until (item i of o's wordList is thisWord)
set i to i + 1
if (i > 28126) then error "wordsToLocation() handler: The word “" & thisWord & "” isn't in the word list."
end repeat
set end of indices to i - 1 -- Converted to 0-based index.
end repeat
set intLat to (beginning of indices) * 64 + (item 2 of indices) div 256 mod 64
set intLong to (item 2 of indices) mod 256 * 16384 + (end of indices)
return {intLat / 10000 - 90, intLong / 10000 - 180}
end wordsToLocation
 
-- Task code:
local o, location, threeWords, checkLocation
-- Use the words in unixdict.txt. It only has 25110 of them by AppleScript's count,
-- so make up the shortfall with invented plurals and third-persons-singular.
script
property wordList : words of (read file ((path to desktop as text) & "unixdict.txt") as «class utf8»)
property additionalWords : {}
end script
set o to result
repeat with i from 1 to (28126 - (count o's wordList))
tell item i of o's wordList
if (it ends with "s") then
set end of o's additionalWords to it & "es"
else
set end of o's additionalWords to it & "s"
end if
end tell
end repeat
set o's wordList to o's wordList & o's additionalWords
 
set location to {28.3852, -81.5638}
set threeWords to locationToWords(location, o's wordList)
set checkLocation to wordsToLocation(threeWords, o's wordList)
return {location, threeWords, checkLocation}</syntaxhighlight>
 
{{output}}
<syntaxhighlight lang="applescript">{{28.3852, -81.5638}, {"quote", "hygiene", "aristotelean"}, {28.3852, -81.5638}}</syntaxhighlight>
 
=={{header|AutoHotkey}}==
Conversion based on Wren<br>
WordList From link suggested by Symsyn
<syntaxhighlight lang="autohotkey">URLDownloadToFile, http://www-personal.umich.edu/~jlawler/wordlist, % A_Temp "\wordlist.txt"
FileRead, wordList, % A_Temp "\wordlist.txt"
 
LL := [28.3852, -81.5638]
num := LL2num(LL)
words := LL2words(wordList, LL)
LL2 := words2LL(wordList, words)
 
MsgBox, 262144, , % result := "
(
LL = " LL.1 ", " LL.2 "
LL2num = " num.1 ", " num.2 ", " num.3 "
LL2words = " words.1 ", " words.2 ", " words.3 "
words2LL = " LL2.1 ", " LL2.2 "
)"
return
;-----------------------------------------------
LL2words(wordList, LL){ ; Latitude/Longitude to 3 words
num := LL2num(LL)
wli := wordList(wordList).1
return [wli[num.1], wli[num.2], wli[num.3]]
}
;-----------------------------------------------
words2LL(wordList, w){ ; 3 words to Latitude/Longitude
iow := wordList(wordList).2
LL := num2LL([iow[w.1], iow[w.2], iow[w.3]])
return [ll.1, ll.2]
}
;-----------------------------------------------
wordList(wordList){ ; word list to two arrays
wli:=[], iow:=[] ; word list index, index of word
for i, word in StrSplit(wordList, "`n", "`r")
if (word ~= "^[a-z]+$") && (StrLen(word) <= 8) && (StrLen(word) > 3)
wli.Push(word), iow[word] := wli.MaxIndex()
return [wli, iow]
}
;-----------------------------------------------
LL2num(LL){ ; Latitude/Longitude to 3 numbers
ilat := LL.1*10000 + 900000
ilon := LL.2*10000 + 1800000
latlon := (ilat << 22) + ilon
return [(latlon >> 28) & 0x7fff, (latlon >> 14) & 0x3fff, latlon & 0x3fff]
}
;-----------------------------------------------
num2LL(w){ ; 3 numbers to Latitude/Longitude
latlon := (w.1 << 28) | (w.2 << 14) | w.3
ilat := latlon >> 22
ilon := latlon & 0x3fffff
return [(ilat-900000)/10000, (ilon-1800000)/10000]
}
;-----------------------------------------------</syntaxhighlight>
{{out}}
<pre>LL = 28.3852, -81.5638
LL2num = 18497, 11324, 1322
LL2words = malleus, fasten, analytic
words2LL = 28.385200, -81.563800</pre>
 
=={{header|C}}==
{{trans|Go}}
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
 
Line 53 ⟶ 270:
 
// isolate relevant bits
w1 = (latlon >> 28) & 0xefff0x7fff;
w2 = (latlon >> 14) & 0x7fff0x3fff;
w3 = latlon & 0x7fff0x3fff;
 
// convert to word format
Line 73 ⟶ 290:
latlon = (w1 << 28) | (w2 << 14) | w3;
ilat = latlon >> 22;
ilon = latlon & 0xfffff0x3fffff;
lat = (double)(ilat-900000) / 10000;
lon = (double)(ilon-1800000) / 10000;
Line 81 ⟶ 298:
printf(" latitude = %0.4f, longitude = %0.4f\n", lat, lon);
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 89 ⟶ 306:
 
Three word location is:
W18497 W27708W11324 W01322
 
After reversing the procedure:
latitude = 28.3852, longitude = -81.5638
</pre>
 
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
program Three_word_location;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
System.SysUtils;
 
type
TThreeWordLocation = array of string;
 
TGlobalPosition = record
private
FLatitude: Double;
FLongitude: Double;
FWs: TThreeWordLocation;
class function toWord(w: int64): string; static;
class function fromWord(ws: string): int64; static;
procedure SetLatitude(const Value: Double);
procedure SetLongitude(const Value: Double);
procedure Recalculate;
function GetTWLocationAsStr: string;
public
constructor Create(_lat, _lon: Double); overload;
constructor Create(Ws: TThreeWordLocation); overload;
procedure Assign(Ws: TThreeWordLocation);
property Latitude: Double read FLatitude write SetLatitude;
property Longitude: Double read FLongitude write SetLongitude;
property TWLocation: TThreeWordLocation read FWs;
property TWLocationAsStr: string read GetTWLocationAsStr;
end;
 
{ TGlobalPosition }
 
constructor TGlobalPosition.Create(_lat, _lon: Double);
begin
FLatitude := _lat;
FLongitude := _lon;
Recalculate;
end;
 
constructor TGlobalPosition.Create(ws: TThreeWordLocation);
begin
Assign(ws);
end;
 
class function TGlobalPosition.fromWord(ws: string): int64;
begin
Result := StrToInt(ws.Substring(1));
end;
 
function TGlobalPosition.GetTWLocationAsStr: string;
var
i: Integer;
begin
Result := '';
for i := 0 to 2 do
Result := Result + ' ' + FWs[i];
Result := Result.Trim;
end;
 
procedure TGlobalPosition.Recalculate;
var
i: Integer;
w: array[0..2] of int64;
ilat, ilon, latlon: Int64;
begin
SetLength(FWs, 3);
 
// convert lat and lon to positive integers
ilat := Round(FLatitude * 10000 + 900000);
ilon := Round(FLongitude * 10000 + 1800000);
 
// build 43 bit BigInt comprising 21 bits (lat) and 22 bits (lon)
latlon := (ilat shl 22) + ilon;
 
// isolate relevant bits
w[0] := (latlon shr 28) and $7fff;
w[1] := (latlon shr 14) and $3fff;
w[2] := latlon and $3fff;
 
// convert to word format
for i := 0 to 2 do
FWs[i] := toWord(w[i]);
end;
 
procedure TGlobalPosition.SetLatitude(const Value: Double);
begin
FLatitude := Value;
Recalculate;
end;
 
procedure TGlobalPosition.SetLongitude(const Value: Double);
begin
FLongitude := Value;
Recalculate;
end;
 
class function TGlobalPosition.toWord(w: int64): string;
begin
result := format('W%.5d', [w]);
end;
 
procedure TGlobalPosition.Assign(Ws: TThreeWordLocation);
var
i: Integer;
w: array[0..2] of int64;
ilat, ilon, latlon: Int64;
begin
SetLength(FWs, 3);
for i := 0 to 2 do
begin
FWs[i] := Ws[i];
w[i] := fromWord(Ws[i]);
end;
 
latlon := (w[0] shl 28) or (w[1] shl 14) or w[2];
ilat := latlon shr 22;
ilon := latlon and $3fffff;
FLatitude := (ilat - 900000) / 10000;
FLongitude := (ilon - 1800000) / 10000;
end;
 
var
pos: TGlobalPosition;
 
begin
pos.Create(28.3852, -81.5638);
 
Writeln('Starting figures:');
Writeln(Format(' latitude = %0.4f, longitude = %0.4f', [pos.Latitude, pos.Longitude]));
 
Writeln(#10'Three word location is:');
Writeln(' ', pos.TWLocationAsStr);
 
Writeln(#10'After reversing the procedure:');
 
// pos.Create(['W18497','W11324','W01322']);
pos.Create(pos.TWLocation);
Writeln(Format(' latitude = %0.4f, longitude = %0.4f', [pos.Latitude, pos.Longitude]));
 
Readln;
end.
 
</syntaxhighlight>
 
{{out}}
<pre>
Starting figures:
latitude = 28,3852, longitude = -81,5638
 
Three word location is:
W18497 W11324 W01322
 
After reversing the procedure:
latitude = 28,3852, longitude = -81,5638
</pre>
 
 
=={{header|FreeBASIC}}==
{{trans|Nim}}
<syntaxhighlight lang="freebasic">Print "Starting figures:"
Dim As Double lat = 28.3852, longi = -81.5638
Print Using " latitude = &, longitude = &"; lat; longi
 
' Convert "lat" and "long" to positive integers.
Dim As Integer ilat = Cint(lat * 10000 + 900000)
Dim As Integer ilong = Cint(longi * 10000 + 1800000)
 
' Build 43 bit int comprising 21 bits (lat) and 22 bits (lon).
Dim As Double latlong = ilat Shl 22 + ilong
 
' Isolate relevant bits.
Dim As Integer w1 = latlong Shr 28 And &H7fff
Dim As Integer w2 = latlong Shr 14 And &H3fff
Dim As Integer w3 = latlong And &H3fff
 
' Convert to word format.
Dim As String*5 w1s = String(5, "0"), w2s = String(5, "0"), w3s = String(5, "0")
Mid(w1s, 6-Len(Str(w1))) = Str(w1)
Mid(w2s, 6-Len(Str(w2))) = Str(w2)
Mid(w3s, 6-Len(Str(w3))) = Str(w3)
 
' Print the results.
Print !"\nThree word location is:"
Print Using " W\ \ W\ \ W\ \"; w1s; w2s; w3s
latlong = w1 Shl 28 Or w2 Shl 14 Or w3
ilat = latlong Shr 22
ilong = latlong And &H3fffff
lat = (ilat - 900000) / 10000
longi = (ilong - 1800000) / 10000
' Print the results.
Print !"\nAfter reversing the procedure:"
Print Using " latitude = &, longitude = &"; lat; longi
Sleep</syntaxhighlight>
{{out}}
<pre>Igual que la entrada de Nim</pre>
 
=={{header|Go}}==
{{trans|Wren}}
Though no need for big integers as we have int64 built in.
<langsyntaxhighlight lang="go">package main
 
import (
Line 126 ⟶ 548:
 
// isolate relevant bits
w1 := (latlon >> 28) & 0xefff0x7fff
w2 := (latlon >> 14) & 0x7fff0x3fff
w3 := latlon & 0x7fff0x3fff
 
// convert to word format
Line 146 ⟶ 568:
latlon = (w1 << 28) | (w2 << 14) | w3
ilat = latlon >> 22
ilon = latlon & 0xfffff0x3fffff
lat = float64(ilat-900000) / 10000
lon = float64(ilon-1800000) / 10000
Line 153 ⟶ 575:
fmt.Println("\nAfter reversing the procedure:")
fmt.Printf(" latitude = %0.4f, longitude = %0.4f\n", lat, lon)
}</langsyntaxhighlight>
 
{{out}}
Line 161 ⟶ 583:
 
Three word location is:
W18497 W27708W11324 W01322
 
After reversing the procedure:
latitude = 28.3852, longitude = -81.5638
</pre>
 
=={{header|J}}==
 
To take full advantage of the bit space, I think we should use 11650.8444 for the multiplier (2^21 - log2 180), but that's not what was asked for here.<syntaxhighlight lang="j">wloc=: {{ ;:inv wordlist{~ (15 14 14#i.3)#./.;(21 22#&.>2) #:&.> <.0.5+10000*90 180+y }}
colw=: {{ _90 _180+1e_4*21({.,&#.}.);(15 14 14#&.>2)#:&.>wordlist i.;:y }}</syntaxhighlight>
 
With <code>wordlist=: ('W',}.@":)&.> 1e5+i.3e4</code>
 
<syntaxhighlight lang="j"> wloc 28.3852 _81.5638
W18497 W11324 W01322
colw wloc 28.3852 _81.5638
28.3852 _81.5638</syntaxhighlight>
 
With <code>wordlist=: cutLF CR-.~fread 'wordlist'</code> based on the file 'wordlist' from http://www-personal.umich.edu/~jlawler/wordlist <syntaxhighlight lang="j"> wloc 28.3852 _81.5638
diplotene chamomile aeroplanist
colw wloc 28.3852 _81.5638
28.3852 _81.5638</syntaxhighlight>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
 
'''Works with jq, the C implementation of jq'''
 
'''Works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq">
## Generic functions
 
# If $j is 0, then an error condition is raised;
# otherwise, assuming infinite-precision integer arithmetic,
# if the input and $j are integers, then the result will be an integer.
def idivide($j):
. as $i
| ($i % $j) as $mod
| ($i - $mod) / $j ;
 
# From bitwise.jq
# integer to stream of 0s and 1s, least significant bit first
def bitwise:
recurse( if . >= 2 then idivide(2) else empty end) | . % 2;
 
# inverse of `bitwise`
def stream_to_integer(stream):
reduce stream as $c ( {power:1 , ans: 0};
.ans += ($c * .power) | .power *= 2 )
| .ans;
 
# Convert the $j least-significant bits of the input integer to an integer
def to_int($j):
stream_to_integer(limit($j; bitwise));
 
# Take advantage of gojq's support for infinite-precision integer arithmetic:
def power($b): . as $in | reduce range(0;$b) as $i (1; . * $in);
 
# Input is assumed to be a non-negative integer
def rightshift($n):
reduce range(0;$n) as $i (.; idivide(2)) ;
 
def lpad($len; $fill):
tostring
| ($len - length) as $l
| if $l <= 0 then .
else ($fill * $l)[:$l] + .
end;
 
## Functions to convert to and from the 'W00000' format
def toWord: "W\(lpad(5; "0"))";
 
def fromWord: .[1:] | tonumber;
 
# Latitude should be presented as a number in [-90, 90]
# and longitude as a number in [-180, 180].
def task($lat; $lon):
# convert lat and lon to positive integers
(($lat * 10000 | trunc) + 900000 ) as $ilat
| (($lon * 10000 | trunc) + 1800000) as $ilon
# build 43 bit integer comprising 21 bits (lat) and 22 bits (lon)
| ($ilat * (2 | power(22)) + $ilon) as $latlon
# isolate relevant bits
| ($latlon | rightshift(28) | to_int(15) | toWord) as $w1
| ($latlon | rightshift(14) | to_int(14) | toWord) as $w2
| ($latlon | to_int(14) | toWord) as $w3
| "Starting figures:",
" latitude = \($lat), longitude = \($lon)",
"\nThree word location is:",
([$w1, $w2, $w3] | join(" ")),
 
# now reverse the procedure
({}
| .latlon = ( ($w1 | fromWord) * (2 | power(28))
+ ($w2 | fromWord) * (2 | power(14))
+ ($w3 | fromWord ) )
| .ilat = (.latlon | rightshift(22))
| .ilon = (.latlon | to_int(22))
| .lat = ((.ilat - 900000) / 10000)
| .lon = ((.ilon - 1800000) / 10000)
| "\nAfter reversing the procedure:",
" latitude = \(.lat), longitude = \(.lon)" )
;
 
task(28.3852; -81.5638)
</syntaxhighlight>
{{output}}
<pre>
Starting figures:
latitude = 28.3852, longitude = -81.5638
 
Three word location is:
W18497 W11324 W01322
 
After reversing the procedure:
Line 168 ⟶ 703:
 
=={{header|Julia}}==
Direct translation from the SymSyn example given by the task creator., though note that idiomatic Julia would usually code this as two small encode() and decode() functions.
<langsyntaxhighlight lang="julia">
# Three Word Location - convert latitude and longitude to three words
LAT = 28.3852
Line 187 ⟶ 722:
# next 14 bits for word 2 index
# next 14 bits for word 3 index
W1 = (LATLON >> 28) & 0xefff0x7fff
W2 = (LATLON >> 14) & 0x7fff0x3fff
W3 = LATLON & 0x7fff0x3fff
 
# fetch each word from word array
Line 219 ⟶ 754:
# display values
println("latitude = $lat longitude = $lon")
</langsyntaxhighlight>{{out}}
<pre>
W18497 W27708W11324 W01322
latitude = 28.3852 longitude = -81.5638
</pre>
 
=== Idiomatic version with scrambling===
<langsyntaxhighlight lang="julia">using Random
 
const LAT = 28.3852
Line 241 ⟶ 776:
end
i = (Int(lat * 10000 + 900000) << 22) | Int(lon * 10000 + 1800000)
return map(x -> arr[x + 1], [(i >> 28) & 0xefff0x7fff, (i >> 14) & 0x7fff0x3fff, i & 0x7fff0x3fff])
end
 
Line 267 ⟶ 802:
lat, lon = threeworddecode(words..., 12345678)
println("latitude = $lat longitude = $lon")
</langsyntaxhighlight>{{out}}
<pre>
W18497 W27708W11324 W01322
latitude = -81.5638 longitude = 28.3852
 
Line 275 ⟶ 810:
W20242 W23427 W16215
latitude = -81.5638 longitude = 28.3852
</pre>
 
=={{header|Kotlin}}==
{{trans|Go}}
<syntaxhighlight lang="scala">fun toWord(w: Long): String {
return "W%05d".format(w)
}
 
fun fromWord(ws: String): Long {
return ws.substring(1).toUInt().toLong()
}
 
fun main() {
println("Starting figures:")
var lat = 28.3852
var lon = -81.5638
println(" latitude = %.4f, longitude = %.4f".format(lat, lon))
println()
 
// convert lat and lon to positive integers
var ilat = (lat * 10000 + 900000).toLong()
var ilon = (lon * 10000 + 1800000).toLong()
 
// build 43 bit BigInt comprising 21 bits (lat) and 22 bits (lon)
var latlon = (ilat shl 22) + ilon
 
// isolate relevant bits
var w1 = (latlon shr 28) and 0x7fff
var w2 = (latlon shr 14) and 0x3fff
var w3 = latlon and 0x3fff
 
// convert to word format
val w1s = toWord(w1)
val w2s = toWord(w2)
val w3s = toWord(w3)
 
// and print the results
println("Three word location is:")
println(" $w1s $w2s $w3s")
println()
 
/* now reverse the procedure */
w1 = fromWord(w1s)
w2 = fromWord(w2s)
w3 = fromWord(w3s)
 
latlon = (w1 shl 28) or (w2 shl 14) or w3
ilat = latlon shr 22
ilon = latlon and 0x3fffff
lat = (ilat - 900000).toDouble() / 10000
lon = (ilon - 1800000).toDouble() / 10000
 
// and print the results
println("After reversing the procedure:")
println(" latitude = %.4f, longitude = %.4f".format(lat, lon))
}</syntaxhighlight>
{{out}}
<pre>Starting figures:
latitude = 28.3852, longitude = -81.5638
 
Three word location is:
W18497 W11324 W01322
 
After reversing the procedure:
latitude = 28.3852, longitude = -81.5638</pre>
 
=={{header|Lua}}==
{{trans|C}}
<syntaxhighlight lang="lua">function toWord(w)
return string.format("W%05d", w)
end
 
function fromWord(ws)
return tonumber(string.sub(ws, 2, -1))
end
 
-------------------------------------------------------------------------
 
print("Starting figures:")
lat = 28.3852
lon = -81.5638
print(string.format(" latitude = %0.4f, longitude = %0.4f", lat, lon))
print()
 
-- convert from lat and lon to positive integers
ilat = lat * 10000 + 900000
ilon = lon * 10000 + 1800000
 
-- build 43 bit number comprising 21 bits (lat) and 22 bits (lon)
latlon = math.floor((ilat << 22) + ilon)
 
-- isloate relevant bits
w1 = (latlon >> 28) & 0x7fff
w2 = (latlon >> 14) & 0x3fff
w3 = latlon & 0x3fff
 
-- convert to word format
w1s = toWord(w1)
w2s = toWord(w2)
w3s = toWord(w3)
 
-- and print the results
print("Three word location is:")
print(" " .. w1s .. " " .. w2s .. " " .. w3s)
print()
 
-------------------------------------------------------------------------
 
-- now reverse the procedure
w1 = fromWord(w1s)
w2 = fromWord(w2s)
w3 = fromWord(w3s)
 
latlon = (w1 << 28) | (w2 << 14) | w3
ilat = latlon >> 22
ilon = latlon & 0x3fffff
lat = (ilat - 900000) / 10000
lon = (ilon - 1800000) / 10000
 
-- and print the results
print("After reversing the procedure:")
print(string.format(" latitude = %0.4f, longitude = %0.4f", lat, lon))</syntaxhighlight>
{{out}}
<pre>Starting figures:
latitude = 28.3852, longitude = -81.5638
 
Three word location is:
W18497 W11324 W01322
 
After reversing the procedure:
latitude = 28.3852, longitude = -81.5638</pre>
 
=={{header|Nim}}==
{{trans|Go}}
<syntaxhighlight lang="nim">import strformat, strutils
 
func toWord(w: int64): string = &"W{w:05}"
 
func fromWord(ws: string): int64 = ws[1..5].parseInt()
 
echo "Starting figures:"
var
lat = 28.3852
long = -81.5638
echo &" latitude = {lat:0.4f}, longitude = {long:0.4f}"
 
# Convert "lat" and "long" to positive integers.
var
ilat = int64(lat * 10_000 + 900_000)
ilong = int64(long * 10_000 + 1_800_000)
 
# Build 43 bit int comprising 21 bits (lat) and 22 bits (lon).
var latlong = ilat shl 22 + ilong
 
# Isolate relevant bits.
var
w1 = latlong shr 28 and 0x7fff
w2 = latlong shr 14 and 0x3fff
w3 = latlong and 0x3fff
 
# Convert to word format.
let
w1s = w1.toWord
w2s = w2.toWord
w3s = w3.toWord
 
# Print the results.
echo "\nThree word location is:"
echo &" {w1s} {w2s} {w3s}"
 
# Reverse the procedure.
w1 = w1s.fromWord
w2 = w2s.fromWord
w3 = w3s.fromWord
 
latlong = w1 shl 28 or w2 shl 14 or w3
ilat = latlong shr 22
ilong = latlong and 0x3fffff
lat = float(ilat - 900_000) / 10_000
long = float(ilong - 1_800_000) / 10_000
 
# Print the results.
echo "\nAfter reversing the procedure:"
echo &" latitude = {lat:0.4f}, longitude = {long:0.4f}"</syntaxhighlight>
 
{{out}}
<pre>Starting figures:
latitude = 28.3852, longitude = -81.5638
 
Three word location is:
W18497 W11324 W01322
 
After reversing the procedure:
latitude = 28.3852, longitude = -81.5638</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight 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;
@words
}
 
sub w_decode {
my($w, $f) = @_;
$f = \&thnys unless $f;
my $s = '%015b';
my $bin = sprintf($s, &$f($$w[0])) . substr(sprintf($s, &$f($$w[1])), 1) . substr(sprintf($s, &$f($$w[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, Norway'],
[ 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() });
}</syntaxhighlight>
{{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, Norway)
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}}==
{{trans|Go}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\Three_word_location.exw
-- ====================================
--</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">toWord</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"W%05d"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">fromWord</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">ws</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">scanf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ws</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"W%05d"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Starting figures:\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">lat</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">28.3852</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">lon</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">81.5638</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" latitude = %0.4f, longitude = %0.4f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">lat</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon</span><span style="color: #0000FF;">})</span>
<span style="color: #000080;font-style:italic;">-- convert lat and lon to positive integers</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ilat</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">lat</span><span style="color: #0000FF;">+</span><span style="color: #000000;">90</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ilon</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">lon</span><span style="color: #0000FF;">+</span><span style="color: #000000;">180</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- build 43 bit BigInt comprising 21 bits (lat) and 22 bits (lon)
-- (std phix atoms have 53/64 bits of precision on 32/64 bit, both plenty)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">latlon</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ilat</span> <span style="color: #0000FF;"><<</span> <span style="color: #000000;">22</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">ilon</span>
<span style="color: #000080;font-style:italic;">-- isolate relevant bits</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">w1</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">latlon</span> <span style="color: #0000FF;">>></span> <span style="color: #000000;">28</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&&</span> <span style="color: #000000;">0x7fff</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">w2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">latlon</span> <span style="color: #0000FF;">>></span> <span style="color: #000000;">14</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&&</span> <span style="color: #000000;">0x3fff</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">w3</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">latlon</span> <span style="color: #0000FF;">&&</span> <span style="color: #000000;">0x3fff</span>
<span style="color: #000080;font-style:italic;">-- convert to word format</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">w1s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">toWord</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w1</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">w2s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">toWord</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">w3s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">toWord</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w3</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- and print the results</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nThree word location is:\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" %s %s %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">w1s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">w2s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">w3s</span><span style="color: #0000FF;">})</span>
<span style="color: #000080;font-style:italic;">-- now reverse the procedure</span>
<span style="color: #000000;">w1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fromWord</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w1s</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">w2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fromWord</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w2s</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">w3</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fromWord</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w3s</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- NB: or_bits (likewise ||), being expressly 32-bit, is NOT appropriate here...</span>
<span style="color: #000000;">latlon</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">w1</span> <span style="color: #0000FF;"><<</span> <span style="color: #000000;">28</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">w2</span> <span style="color: #0000FF;"><<</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">w3</span>
<span style="color: #000000;">ilat</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">latlon</span> <span style="color: #0000FF;">>></span> <span style="color: #000000;">22</span>
<span style="color: #000000;">ilon</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">latlon</span> <span style="color: #0000FF;">&&</span> <span style="color: #000000;">0x3fffff</span>
<span style="color: #000000;">lat</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ilat</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10000</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">90</span>
<span style="color: #000000;">lon</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ilon</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10000</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">180</span>
<span style="color: #000080;font-style:italic;">-- and print the results</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nAfter reversing the procedure:\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" latitude = %0.4f, longitude = %0.4f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">lat</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lon</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Starting figures:
latitude = 28.3852, longitude = -81.5638
 
Three word location is:
W18497 W11324 W01322
 
After reversing the procedure:
latitude = 28.3852, longitude = -81.5638
</pre>
 
=={{header|Raku}}==
{{works with|Rakudo|2020.07}}
===The task===
In large part due to the complete lack of specification, reference implementation, or guidance from the task creator, came up with my own bespoke synthetic word list.
 
Line 297 ⟶ 1,197:
* u - long u (due boo moo)
 
<syntaxhighlight lang="raku" perl6line># SYNTHETICS HANDLING
my @synth = flat < b d f h j k l m n p r s t w y z > X~ < a e i o u >;
my %htnys = @synth.antipairs;
Line 308 ⟶ 1,208:
 
# ENCODE / DECODE
sub w-encode ( Rat(Real) $lat, Rat(Real) $lon, :&f = &synth ) {
$_ = (($lat + 90) * 10000).round.fmt('%021b') ~ (($lon + 180) * 10000).round.fmt('%022b');
(:2(.substr(0,15)), :2(.substr(15,14)),:2(.substr(29)))».&synthf
}
 
sub w-decode ( *@words, :&f = &thnys ) {
my $bin = (@words».&thnysf Z, <0 1 1>).map({.[0].fmt('%015b').substr(.[1])}).join;
(:2($bin.substr(0,21))/10000) - 90, (:2($bin.substr(21))/10000) - 180
}
Line 325 ⟶ 1,225:
59.3586, 24.7447, # Lake Raku
29.2021, 81.5324, # Village Raku
-7.1662, 53.9470, # The Indian ocean, south west of Seychelles
28.3852, -81.5638 # Walt Disney World
-> $lat, $lon {
my @words = w-encode $lat, $lon;
my @index = w-encode $lat, $lon, :f( { $_ } );
printf "Coordinates: %s, %s\n To 3-word: %-20s\n And back: %s, %s\n\n",
printf "Coordinates: %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, @words.Str, w-decode(@words);
$lat, $lon, @index.Str, @words.Str, w-decode(@words), w-decode @index, :f( { $_ } );
}</lang>
}</syntaxhighlight>
{{out}}
 
;Run 1
<pre>Coordinates: 51.4337, -0.2141
To 3-wordIndex: yotema22099 fohujo365 mibire12003
To 3-word: zofobe fohujo habute
And back: 51.4337, -0.2141
From 3-word: 51.4337, -0.2141
From Index: 51.4337, -0.2141
 
Coordinates: 21.2596, -157.8117
To 3-wordIndex: jusafu17384 pufemu5133 nazaka8891
To 3-word: nijemo zanaza fupawu
And back: 21.2596, -157.8117
From 3-word: 21.2596, -157.8117
From Index: 21.2596, -157.8117
 
Coordinates: -55.9652, -67.2256
To 3-wordIndex: mazuda5317 yisobu15428 denezo13632
To 3-word: zanohu julaso husese
And back: -55.9652, -67.2256
From 3-word: -55.9652, -67.2256
From Index: -55.9652, -67.2256
 
Coordinates: 59.3586, 24.7447
To 3-wordIndex: selapu23337 najoke4732 zifuro15831
To 3-word: kapupi hokame supoku
And back: 59.3586, 24.7447
From 3-word: 59.3586, 24.7447
From Index: 59.3586, 24.7447
 
Coordinates: 29.2021, 81.5324
To 3-wordIndex: juyasa18625 nutuza5535 likula10268
To 3-word: dijule nutuza nefini
And back: 29.2021, 81.5324
From 3-word: 29.2021, 81.5324
From Index: 29.2021, 81.5324
 
Coordinates: -7.1662, 53.947
To Index: 12942 12942 12942
To 3-word: rakudo rakudo rakudo
From 3-word: -7.1662, 53.947
From Index: -7.1662, 53.947
 
Coordinates: 28.3852, -81.5638
To 3-wordIndex: nimale18497 josulu11324 tesope1322
To 3-word: tabesa nekaso bupodo
And back: 28.3852, -81.5638</pre>
From 3-word: 28.3852, -81.5638
;Run 2 (same coordinates)
From Index: 28.3852, -81.5638</pre>
<pre>Coordinates: 51.4337, -0.2141
To 3-word: tapesi lawapi jowiyo
And back: 51.4337, -0.2141
 
(Ok, I admit I manipulated that second to last one, but it '''is''' a correct and valid 3-word location in this implementation. There is less than 1 chance in 5000 that it will produce that specific word group though.)
Coordinates: 21.2596, -157.8117
To 3-word: worayu dupika datisi
And back: 21.2596, -157.8117
 
===A thought experiment===
Coordinates: -55.9652, -67.2256
A little thought experiment... Latitude, longitude to four decimal places is accurate to about 11.1 meters at the equator, smaller the further from the equator you get.
To 3-word: zanohu wokemo denezo
What would it take to support five decimal places? (Accurate to 1.11 meters.)
And back: -55.9652, -67.2256
 
<code>360 * 100000 == 36000000;
Coordinates: 59.3586, 24.7447
ceiling 36000000.log(2) == 26;</code>
To 3-word: hewema lenafu jabuha
And back: 59.3586, 24.7447
 
So we need 26 bits to cover 360.00000; half of that for 180.00000, or <code>26 bits + 25 bits == 51 bits</code>. <code>51 / 3 == 17</code>. <code>2**17 == 131072</code> indices. The previous synthetics routine provides much more than enough.
Coordinates: 29.2021, 81.5324
 
To 3-word: zipupi wuha yeyonu
How many sylabics will we need to minimally cover it?
And back: 29.2021, 81.5324
 
<code>∛131072 == 50.7968...</code>
 
So at least 51. The synthetics routine provide sylabics in blocks of 5, so we would need
at least 11 consonants.
 
Capriciously and somewhat randomly cutting down the list we arrive at this.
 
10 times better accuracy in the same three, 6-letter word space.
 
<syntaxhighlight lang="raku" line># SYNTHETICS HANDLING
my @synth = flat < b d f j k n p r s t w > X~ < a e i o u >;
my %htnys = @synth.antipairs;
my $exp = @synth.elems;
my $prec = 100_000;
 
 
sub synth (Int $v) { @synth[$v.polymod($exp xx *).reverse || 0].join }
 
sub thnys (Str $v) { sum %htnys{$v.comb(2).reverse} Z× 1, $exp, $exp² }
 
 
# ENCODE / DECODE
sub w-encode ( Rat(Real) $lat, Rat(Real) $lon, :&f = &synth ) {
$_ = (($lat + 90) × $prec).round.fmt('%025b') ~ (($lon + 180) × $prec).round.fmt('%026b');
(:2(.substr(0,17)), :2(.substr(17,17)), :2(.substr(34)))».&f
}
 
sub w-decode ( *@words, :&f = &thnys ) {
my $bin = @words».&f.map({.fmt('%017b')}).join;
(:2($bin.substr(0,25))/$prec) - 90, (:2($bin.substr(25))/$prec) - 180
}
 
 
# TESTING
for 51.43372, -0.21412, # Wimbledon center court
21.25976,-157.81173, # Diamond Head summit
-55.96525, -67.22557, # Monumento Cabo De Hornos
28.3852, -81.5638, # Walt Disney World
89.99999, 179.99999, # test some
-89.99999,-179.99999 # extremes
-> $lat, $lon {
my @words = w-encode $lat, $lon;
printf "Coordinates: %s, %s\n To Index: %s\n To 3-word: %s\nFrom 3-word: %s, %s\n\n",
$lat, $lon, w-encode($lat, $lon, :f({$_})).Str, @words.Str, w-decode(@words);
}</syntaxhighlight>
{{out}}
<pre>Coordinates: 51.43372, -0.21412
To Index: 55247 71817 21724
To 3-word: jofuni kosasi diduwu
From 3-word: 51.43372, -0.21412
 
Coordinates: 21.25976, -157.81173
To Index: 43460 110608 121675
To 3-word: fukafa repebo safija
From 3-word: 21.25976, -157.81173
 
Coordinates: -55.96525, -67.22557
To Index: 13294 108118 5251
To 3-word: bukeru rasaso besane
From 3-word: -55.96525, -67.22557
 
Coordinates: 28.3852, -81.5638
To 3-wordIndex: lorihu46244 pasiju28747 yaneso13220
To 3-word: jajasu duniri bukaka
And back: 28.3852, -81.5638</pre>
From 3-word: 28.3852, -81.5638
 
Coordinates: 89.99999, 179.99999
To Index: 70312 65298 86271
To 3-word: kofoki kepifo nonope
From 3-word: 89.99999, 179.99999
 
Coordinates: -89.99999, -179.99999
To Index: 0 512 1
To 3-word: ba duji be
From 3-word: -89.99999, -179.99999</pre>
 
=={{header|RPL}}==
{{works with|RPL|HP-49C}}
« 43 STWS DEC
{ 90 180 } ADD 10000 * IP R→I
EVAL SWAP 4194304 * + R→B
1 2 '''START'''
#3FFFh AND LASTARG 1 + /
'''NEXT'''
3 →LIST REVLIST
100000 ADD
1 « →STR 4 OVER SIZE 1 - SUB "W" SWAP + » DOLIST
» '<span style="color:blue">LL→W</span>' STO <span style="color:grey">''@ ( { latitude longitude } → { "word1" .. "word3" )''</span>
« « 2 OVER SIZE SUB STR→ » MAP
DUP 1 GET
2 3 '''FOR''' j
16384 * OVER j GET +
'''NEXT'''
NIP R→B #400000h / LASTARG 1 - AND
2 →LIST B→R 10000 / { 90 180 } -
» '<span style="color:blue">W→LL</span>' STO <span style="color:grey">''@ ( → { "word1" .. "word3" → { latitude longitude } )''</span>
 
{ 28.3852 -81.5638 } <span style="color:blue">LL→W</span>
DUP <span style="color:blue">W→LL</span>
{{out}}
<pre>
2: { "W18497" "W11324" "W01322" }
1: { 28.3852 -81.5638 }
</pre>
 
=={{header|Symsyn}}==
<syntaxhighlight lang="symsyn">
<lang Symsyn>
| Three Word Location - convert latitude and longitude to three words
 
Line 493 ⟶ 1,508:
return -1
 
</syntaxhighlight>
</lang>
{{out}}
<pre>
W18497 W11324 W01322
latitude = 28.3852 longitude = -81.5638
</pre>
 
Using Real Words
 
<syntaxhighlight lang="symsyn">
 
| Three Word Location - convert latitude and longitude to three words
 
lat : 28.3852
lon : -81.5638
 
| Build real word array of the first 28126 words of 8
| or less characters from list of 69905 words sorted alphabetically
| at http://www-personal.umich.edu/~jlawler/wordlist.
| There are 36282 words of 8 or less characters here.
 
opentext 'LargeWordList.txt' wf
if ioresult <> 0
stop
endif
if i <= 28125
[wf] $s
if ioresult <> 0
go closefile
endif
#$s wsz
if wsz <= 8
+ $s $wordarray
(8-wsz) wsz
+ ' ' $wordarray wsz
+ i
endif
goif
endif
closefile close wf
 
| make latitude and longitude positive integers
 
{lat * 10000 + 900000} ilat
{lon * 10000 + 1800000} ilon
 
| build 43 bit integer containing latitude (21 bits) and longitude (22 bits)
 
ilat latlon
shl latlon 22
+ ilon latlon
 
| isolate most significant 15 bits for word 1 index
| next 14 bits for word 2 index
| next 14 bits for word 3 index
 
latlon:42:15 w1
latlon:27:14 w2
latlon:13:14 w3
 
| fetch each word from word array
 
(w1*8+1) w1
$wordarray.w1 $w1 8
(w2*8+1) w2
$wordarray.w2 $w2 8
(w3*8+1) w3
$wordarray.w3 $w3 8
 
| display words
 
"$w1 ' ' $w2 ' ' $w3" []
 
 
| reverse the procedure
 
 
| look up each word
call bsearch 0 28125 $w1
result w1index
 
call bsearch 0 28125 $w2
result w2index
 
call bsearch 0 28125 $w3
result w3index
 
| build the latlon integer from the word indexes
 
w1index latlon
shl latlon 14
+ w2index latlon
shl latlon 14
+ w3index latlon
 
| isolate the latitude and longitude
 
latlon:21:22 ilon
latlon:42:21 ilat
 
| convert back to floating point values
{(ilon - 1800000) / 10000} lon
{(ilat - 900000) / 10000} lat
 
| display values
 
"'latitude = ' lat ' longitude = ' lon" []
 
stop
 
bsearch
param L H $word
if L <= H
((L + H) shr 1) M
(M*8+1) I
$wordarray.I $w 8
if $w > $word
- 1 M H
else
if $w < $word
+ 1 M L
else
return M
endif
endif
goif
endif
return -1
 
</syntaxhighlight>
 
{{Output}}
<pre>
ling everyone amoral
latitude = 28.3852 longitude = -81.5638
</pre>
 
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="go">import strconv
fn to_word(w i64) string { return 'W${w:05}' }
fn from_word(ws string) i64 {
u, _ := strconv.common_parse_uint2(ws[1..], 10, 64)
return i64(u)
}
fn main() {
println("Starting figures:")
mut lat := 28.3852
mut lon := -81.5638
println(" latitude = ${lat:.4}, longitude = ${lon:.4}")
// convert lat and lon to positive integers
mut ilat := i64(lat*10000 + 900000)
mut ilon := i64(lon*10000 + 1800000)
// build 43 bit BigInt comprising 21 bits (lat) and 22 bits (lon)
mut latlon := (ilat << 22) + ilon
// isolate relevant bits
mut w1 := (latlon >> 28) & 0x7fff
mut w2 := (latlon >> 14) & 0x3fff
mut w3 := latlon & 0x3fff
// convert to word format
w1s := to_word(w1)
w2s := to_word(w2)
w3s := to_word(w3)
// and print the results
println("\nThree word location is:")
println(" $w1s $w2s $w3s")
/* now reverse the procedure */
w1 = from_word(w1s)
w2 = from_word(w2s)
w3 = from_word(w3s)
latlon = (w1 << 28) | (w2 << 14) | w3
ilat = latlon >> 22
ilon = latlon & 0x3fffff
lat = f64(ilat-900000) / 10000
lon = f64(ilon-1800000) / 10000
// and print the results
println("\nAfter reversing the procedure:")
println(" latitude = ${lat:.4}, longitude = ${lon:.4}")
}</syntaxhighlight>
 
{{out}}
<pre>
Starting figures:
latitude = 28.3852, longitude = -81.5638
 
Three word location is:
W18497 W11324 W01322
 
After reversing the procedure:
latitude = 28.3852, longitude = -81.5638
</pre>
 
Line 506 ⟶ 1,721:
 
Note that bitwise operations are limited to 32-bit unsigned integers in Wren which isn't big enough here so we use BigInts instead.
<langsyntaxhighlight ecmascriptlang="wren">import "./fmt" for Fmt
import "./big" for BigInt
 
// functions to convert to and from the word format 'W00000'
Line 527 ⟶ 1,742:
 
// isolate relevant bits and convert back to 'normal' ints
var w1 = ((latlon >> 28) & 0xefff0x7fff).toSmall
var w2 = ((latlon >> 14) & 0x7fff0x3fff).toSmall
var w3 = (latlon & 0x7fff0x3fff).toSmall
 
// convert to word format
Line 546 ⟶ 1,761:
latlon = (w1 << 28) | (w2 << 14) | w3
ilat = (latlon >> 22).toSmall
ilon = (latlon & 0xfffff0x3fffff).toSmall
lat = (ilat - 900000) / 10000
lon = (ilon - 1800000) / 10000
Line 552 ⟶ 1,767:
// and print the results
System.print("\nAfter reversing the procedure:")
Fmt.print(" latitude = $0.4f, longitude = $0.4f", lat, lon)</langsyntaxhighlight>
 
{{out}}
Line 560 ⟶ 1,775:
 
Three word location is:
W18497 W27708W11324 W01322
 
After reversing the procedure:
1,150

edits