Skip to content

Instantly share code, notes, and snippets.

@chilang
Created December 27, 2011 13:11
Show Gist options
  • Save chilang/1523616 to your computer and use it in GitHub Desktop.
Save chilang/1523616 to your computer and use it in GitHub Desktop.
geohash decoding
scala> def mid(pair:(Double,Double)) = (pair._1+pair._2) / 2
mid: (pair: (Double, Double))Double
scala> def decode(range:(Double,Double), bin:String) = bin.map(_.toInt - '0'.toInt).foldLeft(range)( (acc,bit) => if (bit == 0) (acc._1, mid(acc)) else (mid(acc), acc._2) )
decode: (range: (Double, Double), bin: String)(Double, Double)
scala> def decodeLat(bin:String) = mid(decode((-90.0,90.0), bin))
decodeLat: (bin: String)Double
scala> def decodeLon(bin:String) = mid(decode((-180.0,180.0), bin))
decodeLon: (bin: String)Double
scala> decodeLat("101111001001")
res33: Double = 42.60498046875
scala> decodeLon("0111110000000")
res34: Double = -5.60302734375
scala> val BASE32 = ('0' to '9') ++ ("bcdefghjkmnpqrstuvwxyz")
BASE32: scala.collection.immutable.IndexedSeq[Char] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, b, c, d, e, f, g, h, j, k, m, n, p, q, r, s, t, u, v, w, x, y, z)
scala> def base32toBin(s:String) = s.map( BASE32.indexOf(_) )
base32toBin: (s: String)scala.collection.immutable.IndexedSeq[Int]
scala> base32toBin("ezs42")
res69: scala.collection.immutable.IndexedSeq[Int] = Vector(13, 31, 24, 4, 2)
scala> base32toBin("ezs42").map(bin32)
res70: scala.collection.immutable.IndexedSeq[java.lang.String] = Vector(01101, 11111, 11000, 00100, 00010)
scala> def bin32(i:Int) = Array(16,8,4,2,1).map( c => if ((i & c) > 0) "1" else "0" ).reduceLeft(_+_)
scala> def base32binary(s:String) = base32toBin(s).map(bin32).reduce(_+_)
base32binary: (s: String)java.lang.String
scala> base32binary("ezs42")
res89: java.lang.String = 0110111111110000010000010
scala> odd(base32binary("ezs42"))
res90: String = 101111001001
scala> even(base32binary("ezs42"))
res91: String = 0111110000000
scala> decodeLon(even(base32binary("ezs42")))
res92: Double = -5.60302734375
scala> decodeLat(odd(base32binary("ezs42")))
res93: Double = 42.60498046875
scala> decodeLat(odd(base32binary("u4pruydqqvj")))
res94: Double = 57.64911063015461
scala> decodeLon(even(base32binary("u4pruydqqvj")))
res95: Double = 10.407439693808556
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment