Geohash: Difference between revisions
Content added Content deleted
Alextretyak (talk | contribs) (Added 11l) |
(Added solution for Action!) |
||
Line 78: | Line 78: | ||
encoder(lat=51.433718, lng=-0.214126, pre=9) = 'gcpue5hp4' |
encoder(lat=51.433718, lng=-0.214126, pre=9) = 'gcpue5hp4' |
||
encoder(lat=57.649110, lng=10.407440, pre=11) = 'u4pruydqqvj' |
encoder(lat=57.649110, lng=10.407440, pre=11) = 'u4pruydqqvj' |
||
</pre> |
|||
=={{header|Action!}}== |
|||
{{libheader|Action! Tool Kit}} |
|||
{{libheader|Action! Real Math}} |
|||
<lang Action!>INCLUDE "H6:REALMATH.ACT" |
|||
CHAR ARRAY code32="0123456789bcdefghjkmnpqrstuvwxyz" |
|||
PROC Encode(REAL POINTER lat,lng BYTE prec CHAR ARRAY hash) |
|||
REAL latMin,latMax,lngMin,lngMax,mid,r2,sum |
|||
REAL POINTER v,min,max |
|||
BYTE even,hashV,bits |
|||
IntToReal(2,r2) |
|||
ValR("-90",latMin) ValR("90",latMax) |
|||
ValR("-180",lngMin) ValR("180",lngMax) |
|||
hash(0)=0 hashV=0 even=1 bits=0 |
|||
WHILE hash(0)<prec |
|||
DO |
|||
IF even THEN |
|||
v=lng min=lngMin max=lngMax |
|||
ELSE |
|||
v=lat min=latMin max=latMax |
|||
FI |
|||
RealAdd(min,max,sum) |
|||
RealDiv(sum,r2,mid) |
|||
hashV==LSH 1 |
|||
IF RealGreaterOrEqual(v,mid) THEN |
|||
hashV==+1 |
|||
RealAssign(mid,min) |
|||
ELSE |
|||
RealAssign(mid,max) |
|||
FI |
|||
even=1-even |
|||
IF bits<4 THEN |
|||
bits==+1 |
|||
ELSE |
|||
bits=0 |
|||
hash(0)==+1 |
|||
hash(hash(0))=code32(hashV+1) |
|||
hashV=0 |
|||
FI |
|||
OD |
|||
RETURN |
|||
BYTE FUNC GetCodeVal(CHAR c) |
|||
BYTE i |
|||
FOR i=1 TO code32(0) |
|||
DO |
|||
IF c=code32(i) THEN |
|||
RETURN (i-1) |
|||
FI |
|||
OD |
|||
RETURN (0) |
|||
PROC Decode(CHAR ARRAY hash REAL POINTER lat,lng,latPrec,lngPrec) |
|||
REAL latMin,latMax,lngMin,lngMax,r2,sum |
|||
REAL POINTER min,max |
|||
BYTE i,j,v,mask,even |
|||
IntToReal(2,r2) |
|||
ValR("-90",latMin) ValR("90",latMax) |
|||
ValR("-180",lngMin) ValR("180",lngMax) |
|||
even=1 |
|||
FOR i=1 TO hash(0) |
|||
DO |
|||
v=GetCodeVal(hash(i)) |
|||
mask=16 |
|||
FOR j=1 TO 5 |
|||
DO |
|||
IF even THEN |
|||
min=lngMin |
|||
max=lngMax |
|||
ELSE |
|||
min=latMin |
|||
max=latMax |
|||
FI |
|||
RealAdd(min,max,sum) |
|||
IF (v&mask)=mask THEN |
|||
RealDiv(sum,r2,min) |
|||
ELSE |
|||
RealDiv(sum,r2,max) |
|||
FI |
|||
even=1-even |
|||
mask==RSH 1 |
|||
OD |
|||
OD |
|||
RealAdd(latMin,latMax,sum) |
|||
RealDiv(sum,r2,lat) |
|||
RealSub(latMax,lat,latPrec) |
|||
RealAdd(lngMin,lngMax,sum) |
|||
RealDiv(sum,r2,lng) |
|||
RealSub(lngMax,lng,lngPrec) |
|||
RETURN |
|||
PROC Test(CHAR ARRAY latStr,lngStr BYTE prec) |
|||
CHAR ARRAY hash(255) |
|||
REAL lat,lng,resLat,resLng,latPrec,lngPrec |
|||
ValR(latStr,lat) ValR(lngStr,lng) |
|||
Encode(lat,lng,prec,hash) |
|||
Decode(hash,resLat,resLng,latPrec,lngPrec) |
|||
Print("Input: ") PrintR(lat) Print(", ") |
|||
PrintR(lng) PrintF(", prec=%B%E",prec) |
|||
PrintF("Encode: %S%E",hash) |
|||
Print("Decode: ") PrintR(resLat) Print(" (+/-") PrintR(latPrec) |
|||
Print("), ") PrintR(resLng) Print(" (+/-") PrintR(lngPrec) |
|||
PrintE(")") PutE() |
|||
RETURN |
|||
PROC Main() |
|||
Put(125) PutE() ;clear the screen |
|||
Test("51.433718","-0.214126",2) |
|||
Test("51.433718","-0.214126",9) |
|||
Test("57.64911","10.40744",11) |
|||
RETURN</lang> |
|||
{{out}} |
|||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Geohash.png Screenshot from Atari 8-bit computer] |
|||
<pre> |
|||
Input: 51.433718, -0.214126, prec=2 |
|||
Encode: gc |
|||
Decode: 53.4375 (+/-2.8125), -5.625 (+/-5.625) |
|||
Input: 51.433718, -0.214126, prec=9 |
|||
Encode: gcpue5hp4 |
|||
Decode: 51.433717 (+/-2.15E-05), -0.21412611 (+/-2.14577E-05) |
|||
Input: 57.64911, 10.40744, prec=11 |
|||
Encode: u4pruydqqvm |
|||
Decode: 57.64911 (+/-1E-06), 10.40743967 (+/-6.7E-07) |
|||
</pre> |
</pre> |
||