Three word location: Difference between revisions
(changed an "language" section header to a "entry/solution version".) |
|||
Line 79: | Line 79: | ||
</pre> |
</pre> |
||
==Idiomatic version== |
=== Idiomatic version === |
||
Output is the same as direct translation version. |
Output is the same as direct translation version. |
||
<lang julia> |
<lang julia> |
Revision as of 00:26, 20 July 2020
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.
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
Idiomatic version
Output is the same as direct translation version. <lang julia> const LAT = 28.3852 const LON = -81.5638
- build word array W00000 ... W28125
const wordarray = ["W" * string(x, pad=5) for x in 0:28125]
function threewordencode(lat, lon) # returns vector of 3 strings
i = (Int(lat * 10000 + 900000) << 22) | Int(lon * 10000 + 1800000) return map(x -> wordarray[x + 1], [(i >> 28) & 0xefff, (i >> 14) & 0x7fff, i & 0x7fff])
end
words = threewordencode(LAT, LON) println(join(words, " "))
function threeworddecode(w1, w2, w3) # returns pair of Float64
(i1, i2, i3) = indexin([w1, w2, w3], wordarray) .- 1 latlon = (i1 << 28) | (i2 << 14) | i3 ilon, ilat = latlon & 0xfffff, latlon >> 22 return (ilon - 1800000) / 10000, (ilat - 900000) / 10000
end
lat, lon = threeworddecode(words...) println("latitude = $lat longitude = $lon") </lang>
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>