Three word location
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.
Symsyn
<lang Symsyn> | Three Word Location - convert latitude and longitude to three words
lat : 28.3852 lon : -81.5638
| build word array W00000 ... W28125
i if i <= 28125 ~ i $r #$r szr 'W00000' $t (6-szr) szr szr #$t + $r $t + $t $wordarray + i goif endif
| 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*6+1) w1 $wordarray.w1 $w1 6 (w2*6+1) w2 $wordarray.w2 $w2 6 (w3*6+1) w3 $wordarray.w3 $w3 6
| 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*6+1) I $wordarray.I $w 6 if $w > $word - 1 M H else if $w < $word + 1 M L else return M endif endif goif endif return -1
</lang>
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. <lang julia>
- Three Word Location - convert latitude and longitude to three words
LAT = 28.3852 LON = -81.5638
- build word array W00000 ... W28125
wordarray = ["W" * string(x, pad=5) for x in 0:28125]
- make latitude and longitude positive integers
ILAT = Int(LAT * 10000 + 900000) ILON = Int(LON * 10000 + 1800000)
- build 43 bit integer containing latitude (21 bits) and longitude (22 bits)
LATLON = (ILAT << 22) + ILON
- isolate most significant 15 bits for word 1 index
- next 14 bits for word 2 index
- next 14 bits for word 3 index
W1 = (LATLON >> 28) & 0xefff W2 = (LATLON >> 14) & 0x7fff W3 = LATLON & 0x7fff
- fetch each word from word array
w1 = wordarray[W1 + 1] w2 = wordarray[W2 + 1] w3 = wordarray[W3 + 1]
- display words
println("$w1 $w2 $w3")
- reverse the procedure
- look up each word
(w1index, w2index, w3index) = indexin([w1, w2, w3], wordarray) .- 1
- build the latlon integer from the word indexes
latlon = (w1index << 28) | (w2index << 14) | w3index
- isolate the latitude and longitude
ilon = latlon & 0xfffff ilat = latlon >> 22
- convert back to floating point values
lon = (ilon - 1800000) / 10000 lat = (ilat - 900000) / 10000
- display values
println("latitude = $lat longitude = $lon")
</lang>
- Output:
W18497 W27708 W01322 latitude = 28.3852 longitude = -81.5638