Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

README.md

3.09 Kb · 59 lines

gno.land/p/moul/x/daily/geohash/v0

Geohash: a latitude/longitude pair as a short base32 string with Encode, Decode, DecodeBox, Neighbor, Neighbors, Box and Direction.

1import "gno.land/p/moul/x/daily/geohash/v0"
2
3h, _ := geohash.Encode(42.6, -5.6, 5)      // "ezs42"
4b, _ := geohash.DecodeBox(h)               // the cell, not a point
5n, _ := geohash.Neighbor(h, geohash.North) // "ezs48"

A geohash is a prefix code, and that is the whole point of storing one. Every character narrows the box by five bits, so a prefix is a valid geohash of the same place, zoomed out, and two places that share a long prefix are close together. An avl tree keyed by geohash therefore answers "everything near here" with a range scan over a prefix, storing no geometry and computing no distance.

A hash names a box, never a point. Decode returns the centre because the centre is the best single point a box can give; DecodeBox returns the box itself with HeightDeg and WidthDeg, which is what you want before claiming two coordinates are "the same place".

Longitude wraps and latitude does not. The cell east of z is b: the antimeridian is a line on a map, not an edge of the world. The classic border/neighbour lookup-table implementations report nothing there, which is a property of the tables rather than of the globe, so this package differs from them on purpose and the tests pin both behaviours. A step past a pole is genuinely impossible and returns ErrNoNeighbor; Neighbors returns a short list there rather than padding it with empty strings a caller has to filter.

Deterministic by construction. Both world ranges are powers of two over powers of two, so every box bound is exactly representable in a float64, the one-cell step Neighbor takes lands on another centre rather than near one, and nothing is rounded or iterated out of a map. Two identical calls cannot disagree, which is the bar a Render has to clear.

The alphabet is the standard one and drops a, i, l and o, so a hash survives being read aloud. Anything outside it is refused rather than skipped, and so is a hash longer than MaxPrecision (12 characters, 60 bits).

Not included: distances, Encode from a radius, or the 3x3 prefix search a proximity query would build on top. The box and its neighbours are the primitives those need.

Live demo: r/moul/x/daily/geohashdemo · render it at /r/moul/x/daily/geohashdemo/v0.


Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.