Difference between revisions of "Implementations"

From Geohashing
imported>Will clardy
(Python Implementation 2 Updated to Python 3)
imported>Crox
m (layout fixes)
 
(28 intermediate revisions by 5 users not shown)
Line 1: Line 1:
==Definition==
+
__TOC__
 +
 
 +
= Definition =
 
An '''implementation''' is a program that takes the method shown in [[The Algorithm]] to calculate the geohash location, presenting the user with text coordinates, a map, data for a navigation device, or some other information that facilitates reaching the geohash.
 
An '''implementation''' is a program that takes the method shown in [[The Algorithm]] to calculate the geohash location, presenting the user with text coordinates, a map, data for a navigation device, or some other information that facilitates reaching the geohash.
  
 
If you're looking to code your own utilities, you will need a source that provides the [[DJIA|Dow]]'s opening price for any given day.  Details on such services are available at [[Dow Jones Industrial Average]].
 
If you're looking to code your own utilities, you will need a source that provides the [[DJIA|Dow]]'s opening price for any given day.  Details on such services are available at [[Dow Jones Industrial Average]].
  
== Official Implementations ==
+
= Official Implementations =
 
 
=== Interactive Coordinate Calculator ===
 
{{30w compliant|yes=1}}
 
The original sample interactive coordinate calculator can be found at [http://carabiner.peeron.com/xkcd/map http://carabiner.peeron.com/xkcd/map]. Here are some notes on [[Using the Coordinate Calculator]]. The common URL, [http://xkcd.com/geohashing http://xkcd.com/geohashing], redirects here.  Any problems or issues should be mentioned to [[User:Zigdon|Zigdon]] either on the wiki or in the [[irc://irc.foonetic.net/geohashing #geohashing channel on irc.foonetic.net]], as well as posted at [[Talk:Implementations]].
 
 
 
=== Reference Implementation ===
 
{{30w compliant|yes=1}}
 
A reference implementation is available:
 
 
 
[http://carabiner.peeron.com/xkcd/map/sample.pl.html view] [http://carabiner.peeron.com/xkcd/map/sample.pl download]
 
 
 
It cannot automatically apply the 30W rule, as it doesn't take your location into consideration. If you're East of 30W, call it with the -e option and it will yield the correct results.
 
 
 
Any problems or issues should be mentioned to [[User:Zigdon|Zigdon]] either on the wiki or in the [[irc://irc.foonetic.net/geohashing #geohashing channel on irc.foonetic.net]], as well as posted at [[Talk:Implementations]].
 
 
 
=== Geo::Hashing on CPAN ===
 
{{30w compliant|yes=1}}
 
Reusable code library that can be used from any perl program:
 
 
 
[http://search.cpan.org/search?query=Geo%3A%3AHashing&mode=all Geo::Hashing]
 
[http://search.cpan.org/src/ZIGDON/Geo-Hashing-0.03/lib/sample.pl Sample code]
 
 
 
=== MediaWiki Implementation ===
 
{{30w compliant|tied=1}}
 
[[MediaWiki Implementation|MediaWiki half-implementation]] (for use by template creators).
 
 
 
== Python Implementations ==
 
=== Python Implementation 1 ===
 
{{30w compliant|yes=1}}
 
<pre>import hashlib, datetime, struct, urllib, re, sys
 
date = datetime.date.today()
 
djia = urllib.urlopen((date - datetime.timedelta(w30)).strftime("http://carabiner.peeron.com/xkcd/map/data/%Y/%m/%d")).read()
 
if '404 Not Found' in djia: sys.exit(sys.stderr.write("Dow Jones not available yet.\n"))
 
sum = hashlib.md5("%s-%s" % (date, djia)).digest()
 
lat, lon = [x/2.**64 for x in struct.unpack_from(">QQ", sum)]; print lat, lon
 
</pre>
 
 
 
* In the above, '''<code>w30</code>''' on line 3 should be replaced by 1 if you're east of -30°, and with 0 otherwise.
 
* As <code>md5</code> has been deprecated in favor of <code>hashlib</code> since python 2.5, if you are using python 2.4 or earlier, substitute <code>hashlib</code> for <code>md5</code>.
 
* To generate [[globalhash]]es, set w30=1 and multiply the final lat, lon values as indicated on that page.
 
 
 
=== Python Implementation 2 ===
 
{{30w compliant|yes=1}}
 
<pre>import hashlib, datetime, struct, urllib, re, sys, webbrowser
 
myLat = 34
 
myLon = -87
 
args = sys.argv
 
if len(args) == 1:
 
    args.append(myLat)
 
    args.append(myLon)
 
else:
 
    args[1] = int(args[1])
 
    args[2] = int(args[2])
 
if args[2] < -30:
 
    td30 = 0
 
else:
 
    td30 = 1
 
if args[1] < 0:
 
    south = -1
 
else:
 
    south = 1
 
if args[2] < 0:
 
    west = -1
 
else:
 
    west = 1
 
date = datetime.date.today()
 
djia = urllib.urlopen((date - datetime.timedelta(td30)).strftime("http://carabiner.peeron.com/xkcd/map/data/%Y/%m/%d")).read()
 
if '404 Not Found' in djia: sys.exit(sys.stderr.write("Dow Jones not available yet.\n"))
 
sum = hashlib.md5("%s-%s" % (date, djia)).digest()
 
n, w = [str(d*(abs(a)+f)) for d, f, a in zip((south, west),
 
    [x/2.**64 for x in struct.unpack_from(">QQ", sum)], args[1:])]
 
print n, w
 
dest = 'http://maps.google.com/maps?f=q&hl=en&geocode=&q=' + n + '+' + w + '&ie=UTF8&ll=' + n + ',' + w + '&spn=0.918082,1,864929&z=9&iwloc=addr'
 
print dest
 
webbrowser.open(dest)
 
</pre>
 
 
 
* The above code is based on the earlier sample code, and is subject to the same provisos regarding <code>md5</code> and <code>hashlib</code>.
 
* You can set the myLat and myLon variables on lines 2 and 3 to your latitude and longitude, and invoke the code directly.
 
* You can also save the code to a module (e.g., geohash.py) and invoke it like this: <code>python geohash.py 34 -87</code> (substituting my example with the latitude and longitude of your choice).
 
 
 
===Python Implementation 2 (Python 3 Update)===
 
{{30w compliant|yes=1}}
 
* This is simply a conversion of the above code to Python 3.
 
* Substitute your own latitude and longitude in the myLat and myLong variables.
 
 
 
<pre>import hashlib, datetime, struct, sys, webbrowser, re
 
from urllib.request import urlopen
 
from urllib.error import HTTPError
 
 
 
myLat = 34
 
myLon = -82
 
args = sys.argv
 
if len(args) == 1:
 
    args.append(myLat)
 
    args.append(myLon)
 
else:
 
    args[1] = int(args[1])
 
    args[2] = int(args[2])
 
if args[2] < -30:
 
    td30 = 0
 
else:
 
    td30 = 1
 
if args[1] < 0:
 
    south = -1
 
else:
 
    south = 1
 
if args[2] < 0:
 
    west = -1
 
else:
 
    west = 1
 
date = datetime.date.today()
 
try:
 
    djia = urlopen((date - datetime.timedelta(td30)).strftime("http://carabiner.peeron.com/xkcd/map/data/%Y/%m/%d")).read().decode('utf-8')
 
except HTTPError:
 
    sys.exit(sys.stderr.write('Dow Jones not available yet.\n'))
 
sum = hashlib.md5(bytes('{0}-{1}'.format(date,djia), 'utf-8')).digest()
 
n, w = [str(d*(abs(a)+f)) for d, f, a in zip((south, west),
 
    [x/2.**64 for x in struct.unpack_from(">QQ", sum)], args[1:])]
 
print(n, w)
 
dest = 'http://maps.google.com/maps?f=q&hl=en&geocode=&q=' + n + '+' + w + '&ie=UTF8&ll=' + n + ',' + w + '&spn=0.918082,1,864929&z=9&iwloc=addr'
 
print(dest)
 
webbrowser.open(dest)
 
</pre>
 
 
 
=== Python package <code>xkcd.geohash</code> ===
 
{{30w compliant|no=1}}
 
There is also a Python package [http://3rdengine.com/labs/geohash/ <code>xkcd.geohash</code>]  which is independent of the interactive coordinate calculator (but uses [http://finance.google.com/finance Google Finance] as well).
 
 
 
=== RESTful Python implementation with Atom feed ===
 
{{30w compliant|yes=1}}
 
This implementation uses [http://webpy.org/ <code>web.py</code>] to give simple, clean URLs.
 
 
 
The source for the [[#Atom_feed|Atom feed]] is available through anonymous svn here: https://staticfree.info/svn/ghfeed/
 
To contribute to it, please contact [[User:Xxv|xxv]] and he can set you up with commit access.
 
 
 
=== Hackish Bitcoin-based Python Implementation ===
 
{{30w compliant|no=1}}
 
[[User:MarkTraceur|MarkTraceur]] made this to test what Geohashing would look like using a different financial source. It's based on the opening price of Bitcoins in USD at Mt. Gox. You can change the site you use, the coordinates, or just about anything pretty easily. It will get nicer-looking as time goes on.
 
 
 
It is here: https://github.com/MarkTraceur/geohash-btc
 
 
 
Feel free to fork it and/or send feedback through GitHub!
 
 
 
== Shell Script Implementation ==
 
{{30w compliant|yes=1}}
 
 
 
<pre>
 
#!/bin/sh -e
 
 
 
command -v md5 >/dev/null 2>&1 || md5() { md5sum | cut -c 1-32; }; [ -n "$1" ]
 
command -v GET >/dev/null 2>&1 || GET() { wget -qO - "$@"; }; [ "$2" -gt -30 \
 
] && { date -R >/dev/null 2>&1 && y='-d yesterday' || y='-v -1d'; }; d=$(GET \
 
carabiner.peeron.com/xkcd/map/data/$(date $y +%Y/%m/%d)); printf $(date $3 +%F-$d) |
 
md5 | sed 'y/abcdef/ABCDEF/; s/.\{16\}/.&LgPp/g' | dc -e "[$2]Sg [$1]Sg 16i" -
 
</pre>
 
 
 
Pass your graticule's lat and long as the arguments to the script. (A third argument may be used to manipulate the date, if you know what you are doing. This is not useful for much more than getting Saturday's hash on Friday.) If something fails it will exit with a nonzero status.
 
 
 
This works with GNU/FreeBSD date, lwp or wget, and bash/ksh/ash, but not OpenBSD date or curl (which are missing some of the features abused here). It would theoretically work with fetch but I removed that for the sake of brevity. Suggestions are welcome, as well as reports of compatibility with other operating systems or implementations of dc.
 
 
 
Here is a contributed wrapper script that will set default co-ordinates for you and call the above implementation, then attempt to print the answer as a Google Maps URL. On OS X, it will launch the URL, but on other operating systems weird things might happen. It has been edited to assume that the first script is installed as "geohash".
 
 
 
<pre>
 
#!/bin/sh
 
 
 
if [ $# -lt 2 ] ; then  # Put your default geo-coords here
 
    : ${LAT:="36"}
 
    : ${LON:="-122"}
 
else
 
    : ${LAT:="$1"}
 
    : ${LON:="$2"}
 
fi
 
 
 
showGeoHash()
 
{
 
    echo "${1} ${2}"
 
    echo "http://maps.google.com/maps?q=${1}+${2}"
 
                                                        ######## Comment all but one of the following lines.
 
    open "http://maps.google.com/maps?q=${1}+${2}"      # For Mac OS X.
 
    firefox "http://maps.google.com/maps?q=${1}+${2}"  # For other *nix with Firefox installed in $PATH.
 
}
 
 
 
showGeoHash $(geohash $LAT $LON)
 
</pre>
 
 
 
== Former geohash location suggester ==
 
 
 
No longer available as of 2012.
 
 
 
{{30w compliant|partial=1|details=not compatible for dates before 2008-05-27}}
 
[http://geohashing.electronicwar.net/ Geohash Recommender - This website doesn't seem to work as of 12J-un-09]
 
 
 
Yet another implementation in Python is here as well. It does the same as the ones above but also gives "validation" information. Lets you know if the geohash location is under water and thus if its a valid place to go party. Using this it attempts to suggest the "best" alternative geohash by checking all neighbouring grid locations. I'll add more terrain recognition if people like it. The code is over here [http://users.ecs.soton.ac.uk/ss06r/GeoHashing/cgi-bin/geohashing.py Source Code]
 
 
 
=== Bugs ===
 
* There are a few, it needs a few refreshes to get the whole tagging right. It also has trouble guessing the terrain type occasionally. Refreshing it makes it work but its a problem im looking into, have a look at the code and help if you can :)
 
* Gives me a false location for May 28 and 29, 2008, which aren't yet known anywhere in the world according to the [[algorithm]].  --[[User:Tjtrumpet2323|Tim P]] 21:29, 24 May 2008 (UTC)
 
** But... thos dates aren't real yet. There is no dow result. Granted it should give an error instead of giving _something_ but...
 
*** As of 05:06, 26 May 2008 (UTC), this gives locations for May 27-30 west of [[30W]] and for May 28-31 east of 30W, i.e., four days beyond what should be calculable as of that time.  Beyond those dates, it gives a proper error message stating that no [[Dow]] is available.  I think temporary data were added to the implementation for testing purposes; these should be removed.  --[[User:Tjtrumpet2323|Tim P]]
 
*** One could interpret the algorithm such that, for any date in the future, one is to use ''"the opening price from [DOW's] previous day of active trading is used"'', ''i.e.'', the most recent trading day.  Obviously, this would lead to the location changing as the day approaches but, in a ''random spontaneous adventure generator'', that seems almost mathematically pure.  I mean, that's just what happens when you try to generate spontaneity too far into the future, yes?  ;)  [[User:Ted|Ted]] 00:19, 30 May 2008 (UTC)
 
* Electronicwar website seems to be no longer functioning. [[User:Jiml|Jiml]] 00:29, 13 June 2009 (UTC)
 
 
 
== Comic Creator ==
 
{{30w compliant|yes=1}}
 
A python class to recreate [http://xkcd.com/426/ the original comic], but for any given date with your own coordinates! Below shows the comic for the first [[2008-05-24_53_6|North East Netherlands meetup]]. Although it fetches the [[Dow]] itself, you can add <code>&dowjones=12345.67</code> if it doesn't do so correctly (e.g., peeron.com is down). Created by [[User:Hugo|Hugo]].
 
http://www.astro.rug.nl/~buddel/cgi-bin/geohashingcomic/geohashingcomic.cgi?year=2008&month=5&day=24&lat=55.218512&lon=6.566854
 
You can download the [http://www.astro.rug.nl/~buddel/cgi-bin/geohashingcomic/ script] as well if you wish.
 
 
 
In the image, [[Dow]] values less than 10,000.00 are padded with leading spaces, however in the algorithm it is not so it is compliant with other the algorithms. As [[User:Tjtrumpet2323|Tim P]] suggested, the comic is akin to all the bank cheques with "19__" printed on them being used in 2000.  The "form" has 5+2 "boxes" because that's how [[Dow]] prices are now, but that doesn't mean it can't be different.
 
 
 
: Oh, goodness.  Aren't we glad we took care of that before the Dow lost 24% in a month?  :)  --[[User:Tjtrumpet2323|Tim P]] 04:14, 10 October 2008 (UTC)
 
 
 
=== Bugs ===
 
* The font sizes are not exactly as the original and there can still be some alignment problems.
 
* The -0 issue is ignored. Only if you enter -0 as an integer you get an incorrect outcome. You are supposed to enter your own location as a float, up to 6 decimals, everything is okay even when you enter -0.0.
 
 
 
== Semi-manual offline calculator ==
 
{{30w compliant|yes=1}}
 
If you're going to be away from internet access, you'll need to compute the hash locally:
 
* Download and extract this: http://lab.brainonfire.net/drop/geohash-offline.zip
 
* Working example: http://lab.brainonfire.net/geohash-offline/calc.html
 
 
 
=== Notes ===
 
* All you need is a Javascript-enabled browser. Tested in Firefox so far.
 
* You will have to ''somehow'' acquire the [[Dow]]'s opening value for the appropriate date; there may be a service to do this.
 
** Remember, if you're east of [[30W]], you should use the '''previous day's''' opening price, even if a new one becomes available later in the day.
 
* The date is filled in automatically using the current timestamp.
 
* You'll have to combine the computed fractional coordinates with your graticule coordinates yourself.
 
* I grabbed MD5 and base conversion code from random internet sites.
 
 
 
== Text Messaging (email) service ==
 
{{30w compliant|yes=1}}
 
If your cell phone supports text messaging to an email address, you can get geohash updates on your phone by sending a formatted text to srv@geohash.info
 
=== Formatting ===
 
YYYY-MM-DD Lat Lon
 
Example:
 
<pre>2008-02-18 42 -83</pre>
 
Alternatively, it defaults to the current date (EST for now) and you can just enter Latitude and Longitude
 
<pre>42 -83</pre>
 
 
 
=== Bugs ===
 
* The [[-0 Issue]] is still very much an issue.
 
* This used to display the degree symbol after coordinate elements, but due to poor cell phone support of this character, which resulted in messages cutting off after the first Latitude, I have removed it.
 
* This is also not a terribly robust solution, but a better (stronger, faster) implementation is in the making.
 
* Not necessarily a bug, but a desirable feature: it would be nice to be able to omit the '-' character when specifying the date (it just happens to require many keystrokes to type - on my phone)
 
 
 
 
 
== Text Messaging service (SMS) ==
 
{{30w compliant|yes=1}}
 
Text "GH [date]" to +41774378210, eg:
 
<pre>gh 20091110</pre>
 
A few seconds later you should get an sms response similar to the following:
 
<pre>Relevant DJIA for 2009-11-10 is 10223.01(W) / 10020.62(E). Decimal parts are: 0.02335 0.228005(W) / 0.854495 0.149983(E).</pre>
 
 
 
Occasionally you may see a result of '''<n/a>''' when information is unavailable. For example, if you are looking at a date where coordinates are only available east of w30, you may see something like:
 
<pre>Relevant DJIA for 2009-11-10 is <n/a>(W) / 10020.62(E). Decimal parts are: <n/a>(W) / 0.854495 0.149983(E).</pre>
 
 
 
Not case-sensitive, so "Gh", "gh" etc. are all fine. Don't forget the space between "gh" and the date. The script is also flexible on the date format as long as it's in the Y-m-d order.
 
 
 
The service uses the [[Dow_Jones_Industrial_Average#geo.crox.net|DJIA source]] that I maintain.
 
 
 
I recommend testing it once before you are away from home and really need it. Also, don't hesitate to tell me if you don't get an sms back or if you feel that something else is not working properly...
 
 
 
See also [[Dow Jones Industrial Average#SMS|SMS DJIA service]]; suggestions, comments and other feedback to [[User:Crox]].
 
 
 
== Local email tool in D, for Linux ==
 
{{30w compliant|yes=1}}
 
Run this program once a day (for instance, per crontab) to get email notification whenever Google Maps indicates the daily target is nearer than a specified range. The first time around, run it from the commandline to configure. Configuration is stored in ~/.geohash/geohash.cfg. Use --help for info about commandline parameters. [http://paste.dprogramming.com/dpxcs3lx Source. ] [http://demented.no-ip.org/geohashd Linux 32-bit upx compressed binary. ]
 
 
 
== Feeds ==
 
=== GeoRSS feed ===
 
{{30w compliant|no=1}}
 
You can subscribe to a feed (in GeoRSS format) that will give you updates on a daily basis{{fact}}.  Updates include the "best guess" address of the location as well as the specific latitude/longitude coordinates.
 
<pre>http://atlas.freshlogicstudios.com/Features/Experiments/Xkcd/Xkcd.ashx?Latitude=38&Longitude=-91</pre>
 
 
 
For example, here's the [http://atlas.freshlogicstudios.com/Features/Experiments/Xkcd/Xkcd.ashx?Latitude=38&Longitude=-91 GeoRSS geohash for St. Louis].
 
 
 
This GeoRSS feed is used to power the [http://atlas.freshlogicstudios.com/?Xkcd Atlas geohash implementation].
 
 
 
=== Atom feed ===
 
{{30w compliant|yes=1}}
 
You can subscribe to a feed that will give you updates on a daily basis:
 
<pre>http://staticfree.info/geohash/atom/LAT,LON</pre>
 
 
 
For example, here's the [http://staticfree.info/geohash/atom/42,-71 Atom Geohash for Boston].
 
 
 
Just put your coordinates in, subscribe and you'll be ready to go!
 
 
 
Source is available from subversion: https://staticfree.info/svn/ghfeed/
 
 
 
==== Atom Feed Bugs ====
 
* I noticed yesterday that before the stock exchange data becomes available, the atom feed creates a kind of 'intemediary' geohash using todays date and yesterday's data. This might be intentional, but personally I find that undesirable on weekdays. Could it be modified to show yesterday's date and geohash until data is available? Nicktaylor 14:04, 23 May 2008 (UTC)
 
** It's definitely broken. -- [[User:Phyzome|Phyzome]] 11:37, 28 May 2008 (UTC)
 
*** This implementation was written before the [[30W]] rule.  As it turns out, the intermediate hash falls back on the previous Dow while using the current date from 00:00 (local) to 09:30 [[ET]], which happens to be the desired 30W behavior.  However, this is not helpful west of 30W.  An inverse problem occurs after 09:30 US[[ET]] east of 30W, until 24:00 local.  See detailed discussion at [[Talk:Implementations#Atom feed 30W-compliance]].  --[[User:Tjtrumpet2323|Tim P]] 15:45, 29 May 2008 (UTC)
 
 
 
=== geohash.info ===
 
{{30w compliant|yes=1}}
 
Subscribe to a feed that updates as soon as each day's meetup is calculable for your graticule:
 
http://www.geohash.info/srv/feed.php?lat=LAT&lon=LON
 
 
 
If you [http://www.geohash.info/srv/feed.php visit the URL with no parameters], you will be prompted for your graticule coordinates.
 
 
 
* Dow data comes from the [[Dow#irc.peeron.com|peeron service]]
 
* To view source, drop the parameters and change the extension to .phps -- this currently works for all PHP files in geohash.info/srv/
 
 
 
==== Quirks ====
 
* The script estimates your timezone based upon your longitude, and uses -04:30 as the timezone of the Dow. Therefore, the update times may be off by as much as an hour or two. Shouldn't be an issue, since they'll be around midnight for most people.
 
* For non-30W users, the feed will be empty between midnight and 9:30 AM -- this should be acceptable, since most feed readers keep entries that have dropped off the end of the feed. (This behavior may be changed in the future.)
 
 
 
=== Flickr ===
 
This won't help you find future (or, likely, present) coordinates, but one can keep tabs on photos that users have tagged with '''geohashing''' at Flickr by using [http://api.flickr.com/services/feeds/photos_public.gne?tags=geohashing this] RSS feed  link.
 
 
 
=== Geo Hashing RSS ===
 
{{30w compliant|yes=2}}
 
Another RSS implementation, coded by [[User:Mattyk|Matty K]].  This one simply provides a graticule's coordinates for a given day, and gives links to both Google maps and the peeron maplet.  It is recalculated at every request (so please don't hammer it, or my website will run out of bandwidths).
 
http://geohashing.kerwin.net.au/rss.php?ll=LAT,LON
 
For example, the link for [[San Francisco, California|San Francisco]]'s feed is: http://geohashing.kerwin.net.au/rss.php?ll=37,-122
 
 
 
Notes:
 
* If latitude/longitude are not given, it defaults to [[Townsville, Australia|my home graticule]] .
 
* <s>I don't know if it supports negative zero.  If there is a request to add specific support, please [mailto:matthew@kerwin.net.au?subject=Geo+Hashing+RSS let me know].</s>  I added specific negative zero support, and tested it with the London area.  It appeared to work okay.
 
* [[30W Time Zone Rule|30W]]-compliance is based on the fact that I live East of 30W, and it gives me the right coordinates each day.
 
* For any bug reports or other features requests, please [mailto:matthew@kerwin.net.au?subject=Geo+Hashing+RSS email Matty]
 
* Sources can be made available by request.  Although [[User:Mattyk|Matty]] might be a little ashamed of the shoddy code.
 
 
 
== k4 implementation ==
 
{{30w compliant|no=1}}
 
Here's an implementation in [http://kx.com/developers/license2.php k4], a vector-programming (i.e., self-obfuscating) language that seems to me to be very true to the spirit of xkcd. The following shell script takes the graticule as an argument, uses standard standard unix tools to retrieve the current Dow opening price, and returns a URL for a Google map to the the upcoming Saturday's meetup. It assumes the q executable is in your PATH.
 
<pre>
 
#!/bin/sh
 
 
 
test $# -eq 2 || exit 1
 
dow=`curl -s 'http://finance.google.com/finance?cid=983582'| \
 
egrep -o '<span id="ref_983582_op">[^<]+</span>'| \
 
sed -r 's/.*>(.*)<.*/\1/'|tr -d ,`
 
 
 
q -lat $1 -lon $2 -dow $dow<<"EOF"
 
\
 
(.q.set').(!:;,/)@\:.Q.opt .z.x;
 
h:.Q.n,6#.Q.A;c:16 xexp'-:'1+!16
 
u:"http://maps.google.com/maps?q="
 
d:.q.ssr[$.z.D+7-.q.mod[.z.D]7;".";"-"]
 
s:0N 16#,/$-15!"-"/:(d;dow);l:(lat;lon)
 
-1@u,"+"/:l,'1_'$sum'(h?/:.q.upper s)*\:c;
 
\\
 
EOF
 
</pre>
 
 
 
For example, here's New York as of 2008-05-23:
 
<pre>
 
% gh 40 -74
 
http://maps.google.com/maps?q=40.126648+-74.5475331
 
</pre>
 
 
 
N.B., this was written on a Friday; I make no guarantee that it will produce useful results when run on any other day of the week (though Saturdays will probably work).
 
 
 
[[User:Adavies42|Adavies42]] 20:50, 23 May 2008 (UTC)
 
 
 
== Automatic GPX File Generator ==
 
{{30w compliant|no=1}}
 
I have modified the sample perl implementation so that it automatically generates a .gpx file which you can upload to your favourite GPS device/software. [http://discarded-ideas.org/files/geohash.pl Download here]
 
Before you use the script, you need to modify it and put your own lat/lon values into the corresponding variables at the beginning.
 
~~Wansti
 
 
 
== GeohashGenerator for Popfly ==
 
{{30w compliant|yes=1}}
 
I have created a [http://www.popfly.com Popfly] block to use for creating mashups at http://www.popfly.com/users/rbuckton/GeohashGenerator.  Can be integrated with Virtual Earth, etc.
 
 
 
[[User:rbuckton|rbuckton]]
 
 
 
== Lazy Geohasher ==
 
{{30w compliant|partial=1}}
 
If you'd rather just stay at home and wait for a geohash to come to you (or perhaps have some other reason to participate in [[Geohash Hacking]]), there's a [http://www.mewlip.plus.com/geohash/geohash.pl perl script] which will search for combinations of times and DOW Jones opening prices to find when you could win the much coveted [[Couch Potato Geohash]] or [[Cubicle Geohash]] award. Just put in the ranges of values for the stock market and the time you want to wait for, and watch those CPU cycles fly! -- [mailto:thaniel.drake@gmail.com thaniel.drake@gmail.com].
 
 
 
'''30w compliance statement''': This code does not use live data. Users are expected to determine from the date of the Geohash which opening value is relevant for their locale.
 
 
 
<div style='font-size:90%; margin:2px 10% 2px; padding: 2px; border: 1px solid #dd0; background: #ffc'>
 
'''Disclaimer:''' The author humbly requests that you do not manipulate the Dow Jones Industrial Average to ensure that a geohash collides with your address. The author accepts no responsibility for any resulting financial instability you cause by such manipulations.
 
</div>
 
 
 
Here is an improved implementation which sorts results by great-circle distance. Distance cutoff, length of search, and dollar spread searched may be adjusted at the command line. Days may be a positive integer count of days following today or a comma-separated list of %F datespecs. Same 30W caveats apply.
 
 
 
{{30w compliant|partial=1}}
 
<pre>
 
#!/usr/bin/perl -w
 
require 5.9.2;
 
 
 
use Digest::MD5 qw(md5);
 
use POSIX qw(strftime);
 
use Math::Trig qw(deg2rad great_circle_distance);
 
 
 
die "usage: $0 lat lon orig-dow [spread] [days] [max-km]" unless @ARGV >= 3;
 
my ($lat, $lon, $orig, $spread, $days, $max_km) = @ARGV;
 
my ($g_lat, $g_lon) = map { int } $lat, $lon;
 
$spread ||= 500; $days ||= 7; $max_km ||= 1;
 
 
 
sub geohash { map { $_ / 2**64 } unpack("Q>Q>", md5(shift)) }
 
sub genday {
 
    my $date = shift;
 
    for (($orig - $spread) * 100 .. ($orig + $spread) * 100) {
 
        my $dow = sprintf("%.2f", $_ / 100);
 
        ($f_lat, $f_lon) = map { substr($_, 1) } geohash("$date-$dow");
 
        $gh{"$date-$dow"} = [$g_lat . $f_lat, $g_lon . $f_lon];
 
    }
 
}
 
 
 
if ($days =~ /^\d{4,}-\d{2}-\d{2}/) { genday($_) for split(/,/, $days) }
 
else { genday(strftime("%F", localtime(time + 86400 * $_))) for (1...$days) }
 
 
 
sub d2r { deg2rad($_[0]), deg2rad(90 - $_[1]) }
 
sub gdist { great_circle_distance(d2r($lat, $lon), d2r(@{$_[0]}), 6378) }
 
 
 
printf "%s -> %f,%f (%.3fkm)\n", $_->[0], @{$gh{$_->[0]}}, $_->[1] for
 
    sort { $a->[1] <=> $b->[1] }
 
        grep { $_->[1] < $max_km }
 
            map { [$_, gdist($gh{$_})] } keys %gh;
 
</pre>
 
 
 
For discussion of the actual algorithm stuff hiding in there, please see the next section.
 
 
 
== Alternative Perl Implementation ==
 
 
 
Because there is no way this page is complete without a lesson on endianness...
 
 
 
In writing the above "lazy" script I needed to come up with a way to do the actual hashing in Perl. So, here it is pulled out from that, and using today's data from the web service:
 
 
 
{{30w compliant|yes=1}}
 
<pre>
 
#!/usr/bin/perl -w
 
require 5.9.2;
 
 
 
use POSIX qw(strftime);
 
use LWP::Simple;
 
use Digest::MD5 qw(md5);
 
 
 
die "usage: $0 lat long" unless @ARGV == 2;
 
my @graticule = map { int } @ARGV;
 
 
 
sub dow_open {
 
    my $date = strftime("%Y/%m/%d", localtime(shift));
 
    get("http://carabiner.peeron.com/xkcd/map/data/$date");
 
}
 
 
 
sub geohash {
 
    map { $_ / 2**64 } unpack("Q>Q>", md5(shift));
 
}
 
 
 
my $today = strftime("%F", localtime);
 
my $dow = dow_open(time - ($graticule[1] > -30 ? 86400 : 0));
 
 
 
for (map { substr($_, 1) } geohash("$today-$dow")) {
 
    print shift @graticule, $_, "\n";
 
}
 
</pre>
 
 
 
This is the same bare output format as the shell script, for piping into your favorite formatter or google-launcher or whatever. The reason it requires Perl 5.10, however, is the code used to interpret the hash:
 
 
 
<pre>
 
map { $_ / 2**64 } unpack("Q>Q>", md5(shift))
 
</pre>
 
 
 
One unfortunate thing I have noticed across implementations is that a lot of effort has been spent converting hexadecimal into decimal. It is important to remember that MD5 hashes are 128 *bits* -- hexadecimal is just a form of representation. (It's very convenient, and we see it everywhere. But even in the original comic, it's representation.) In languages that provide the power to deal with data directly, the familiar hex representation can frequently be skipped in our quest to present numbers as decimal. This is what unpack does above (The Python implementation uses their flavor of unpack as well. I am sure Ruby has something similar).
 
 
 
I point this out only because Perl neglected to get this right until recently, and so the code as written will not run on 5.8 or earlier. As they are presented in the algorithm, the two 64-bit binary fractions (think: 1/2's place, 1/4's place, 1/8's place... with the caveat that we only see the numerator digits; the denominators are all 1!) from the 128 bits of MD5 are big-endian. Sadly, the machine running Perl might be big-endian or little-endian (think: the first 8 places at the end, then the next 8 places before that, etc... it's reversed by bytes, not bits). 5.10 provides the "<" and ">" endianness specifiers for all types, even 64-bit numbers. But on 5.8, attempting to directly grab the bits will always use the machine's native arrangement, and so only work if you're in big-endian-land. Most of us (running x86 CPUs) are not. Here is one (ugly) way to deal with it:
 
 
 
<pre>
 
map { $_ / 2**64 } reverse unpack("QQ", reverse md5(shift));
 
</pre>
 
 
 
Evaluation works backward from the right; by reversing the byte string (remember how it's backwards by bytes? the word that looks forward to us looks backward to them, too), we are able to unpack two 64-bit chunks that *would* be the right numbers, but are now (since the whole thing was reversed) in the wrong order, so we flip them around again. If they weren't the same sizes, we would have had to reverse the unpack specification as well (in fact, we did; you just couldn't tell). Fun, no? So if you need to run this on 5.8, patch this in and remember to delete the "require" line.
 
 
 
==All-Time Closest Geohash to Where You Lived At The Time==
 
{{30w compliant|yes=1}}
 
 
 
This Perl script takes as its input a comma-separated text file giving the starting and ending dates and latitude and longitude of every place you've ever lived (or worked, or any other place you're interested in), and finds the closest hashpoint ever to come to any of those places while they were current for you.  See if you have a retroactive [[Couch Potato Geohash]] somewhere in your history!  (You're out of luck if you lived anywhere before 1928-10-01, though, since that's as far back as the data goes.)
 
 
 
<pre>
 
#!/usr/bin/perl -w
 
 
 
# Program to find nearest historical geohash to place(s) you're interested
 
# in, such as your homes or workplaces.  As it goes forward through the
 
# dates it's checking for hashes in, it outputs each one that sets a new
 
# record for closest yet to a place of interest.
 
 
 
use strict;
 
use Geo::Hashing;
 
 
 
# set current date
 
my $currdate = sprintf("%04d-%02d-%02d", (localtime)[5]+1900,
 
                                        (localtime)[4]+1,
 
                                        (localtime)[3]);
 
 
 
# Initialize extremes so they're later replaced by actual values
 
my $mindate = $currdate;
 
my $maxdate = '1928-10-01';
 
 
 
# Read in places and dates of interest.  File should have all the locations
 
# you want to check for nearby past geohashes in, such as all the places
 
# you've ever lived (or worked), with the date range for each.
 
# Date ranges may overlap, so you can track multiple homes/workplaces at once.
 
# Put in file places.csv in same directory as this script
 
# Each line is in format: FromDate, ToDate, Latitude, Longitude, Title
 
# Dates are in form YYYY-MM-DD
 
# Lat/Lon are in decimal degrees, negative numbers for W / S
 
# Empty FromDate means 'from beginning of time', 1928-10-01 in this case
 
# Empty ToDate means 'until present', going up to and including current date
 
 
 
my $i = 0;
 
my @fromdate = ();
 
my @todate = ();
 
my @lat = ();
 
my @lon = ();
 
my @title = ();
 
open INFILE, "<places.csv" or die "You must create a places.csv file in the same directory as this script.
 
This is intended to contain a list of every place you've lived
 
(or worked, etc.), by date and location.
 
Format: 1 line per place
 
FromDate,ToDate,Latitude,Longitude,Title
 
Dates in format YYYY-MM-DD
 
Lat/Lon in decimal degrees
 
Title is whatever text string you want to identify a place with.\n";
 
while (<INFILE>)
 
{
 
  chomp;
 
  ($fromdate[$i], $todate[$i], $lat[$i], $lon[$i], $title[$i]) = split(/\,/);
 
  $fromdate[$i] = '1928-10-01' if !$fromdate[$i];
 
  $todate[$i] = $currdate if !$todate[$i];
 
 
 
  $mindate = $fromdate[$i] if $fromdate[$i] lt $mindate;
 
  $maxdate = $todate[$i] if $todate[$i] gt $maxdate;
 
 
 
  $i++;
 
}
 
close INFILE;
 
 
 
my $latmiles = 69.1703234283616; # Conversion factor of lat degrees to miles; always constant
 
 
 
my @MonthLen = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
 
 
 
my $date = $mindate;
 
my ($yr, $mo, $dy) = split(/-/, $date);
 
$MonthLen[2] = 29 if &is_leap($yr);
 
 
 
my $mindist = 9999; # Initialize min distance to high number
 
 
 
while ($date le $maxdate)
 
{
 
  for ($i = 0; $i<=$#fromdate; $i++)
 
  {
 
    if ($date ge $fromdate[$i] && $date le $todate[$i])
 
    {
 
      my ($lat, $lon) = (int($lat[$i]), int($lon[$i])); # Integer lat/lon for hashpoint lookup
 
   
 
      my $geo = new Geo::Hashing(lat => $lat, lon => $lon, date => $date); # Get hashpoint for date
 
     
 
      my $latdiff = abs($geo->lat - $lat[$i]); # Find absolute distance in each axis direction
 
      my $londiff = abs($geo->lon - $lon[$i]);
 
     
 
      my $lonmiles = 69.1703234283616 * cos($lat[$i]*0.0174532925199433); # Conversion factor of lon degrees to miles
 
      my $latdiffmiles = $latdiff * $latmiles; # Convert to miles
 
      my $londiffmiles = $londiff * $lonmiles;
 
     
 
      my $distance = sqrt($latdiffmiles**2 + $londiffmiles**2); # Find hypotenuse
 
     
 
      if ($distance < $mindist) # Found new shortest distance so far
 
      {
 
        $mindist = $distance;
 
        printf "$date: %0.6f, %0.6f -- %0.4f miles from $title[$i]\n", $geo->lat, $geo->lon, $distance;
 
      }
 
    }
 
  }
 
 
 
  # Advance date
 
  $dy++;
 
  if ($dy > $MonthLen[$mo])
 
  {
 
    $dy = 1;
 
    $mo++;
 
    if ($mo > 12)
 
    {
 
      $mo = 1;
 
      $yr++;
 
      if (&is_leap($yr))
 
      {
 
        $MonthLen[2] = 29;
 
      }
 
      else
 
      {
 
        $MonthLen[2] = 28;
 
      }
 
    }
 
  }
 
 
 
  $date = sprintf("%04d-%02d-%02d", $yr, $mo, $dy);
 
}
 
 
 
print "Finished searching.\n";
 
 
 
sub is_leap {
 
  # Returns 1 if leap year, 0 if not
 
  my($yr) = @_;
 
 
 
  if ($yr%4)
 
  {
 
    0;
 
  }
 
  elsif (!($yr%400))
 
  {
 
    1;
 
  }
 
  elsif ($yr%100)
 
  {
 
    1;
 
  }
 
  else
 
  {
 
    0;
 
  }
 
}
 
</pre>
 
 
 
Sample places.csv file:
 
 
 
<pre>
 
1982-08-26,1983-05-10,40.441164,-79.939020,Freshman Dorm
 
1983-08-25,1986-05-12,40.452789,-79.948439,Off-Campus Living
 
2000-02-03,,26.340754,-80.129356,Apartment
 
</pre>
 
 
 
==Java implementation==
 
{{30w compliant|yes=1}}
 
 
 
A Java port of the Python implementation can be found from [https://github.com/cannonerd/AdventureTablet/blob/master/src/com/wordpress/cannonerd/Geohash.java GitHub].
 
 
 
== Ruby Geohasher v1.2==
 
{{30w compliant|yes=1}}
 
ScottKuma did this as a first excursion into Ruby.  Yes, it's long.  Yes, it's kinda clunky.  However, '''IT WORKS!'''
 
 
 
v1.2 adds the ability to use unix-style commandline options in any order.
 
 
 
Any changes, suggestions, etc. are happily accepted!
 
 
 
 
 
<pre>
 
#!/usr/bin/ruby
 
# == Synopsis
 
# geohasher: prints geohash coordinates for a given date & graticule
 
#
 
# == Usage
 
#
 
# geohasher [OPTION] ...
 
# -d, --date YYYY-MM-DD:
 
#  the date in YYYY-MM-DD or YYYY/MM/DD format),
 
#
 
# -t, --lat x:
 
#  the latitude "base coordinate"
 
#
 
# -g, --long x:
 
#  the longitude "base coordinate"
 
#
 
# -m, --dow x
 
 
 
 
 
require 'net/http'
 
require 'date'
 
require 'digest'
 
require 'getoptlong'
 
require 'rdoc/usage'
 
 
 
def hexFracToDecFrac(hexFracPart)
 
#I wish I had a neat little algorithm to do this in one line - but this works!
 
#NOTE:  do not feed the preceding "0." to this function....only the fractional part (the part after the decimal point)
 
fracLen = hexFracPart.length
 
fracPortion = hexFracPart[0..(fracLen-1)]
 
fracLen = fracPortion.length
 
myLen = (fracLen - 1)
 
sum = 0
 
for i in (0 .. myLen)
 
numSixteenths = fracPortion[i..i].to_i(16)
 
conversionFactor = (16.**(i+1)).to_f
 
conversionFactor = 1./conversionFactor
 
sum = sum + ((numSixteenths) * conversionFactor)
 
end
 
return sum.to_s[2..8]
 
end
 
 
 
# Parse the command line options
 
 
 
opts = GetoptLong.new(
 
['--help','-h',GetoptLong::NO_ARGUMENT ],
 
['--lat','-t',GetoptLong::REQUIRED_ARGUMENT ],
 
['--long','-g',GetoptLong::REQUIRED_ARGUMENT ],
 
['--dow','-m',GetoptLong::REQUIRED_ARGUMENT ],
 
['--date','-d',GetoptLong::REQUIRED_ARGUMENT ]
 
)
 
 
 
# Set default items (still parsing...)
 
 
 
myLat = "39" # Change me to set the desired default graticule's latitude
 
myLong = "-84" # Change me to set the desired default graticule's longitude
 
t=Time.now
 
myDate = t.strftime("%Y-%m-%d")
 
dow = ""
 
 
 
begin
 
opts.each do |opt,arg|
 
case opt
 
when '--help'
 
RDoc::usage
 
when '--lat'
 
myLat = arg
 
when '--long'
 
myLong = arg
 
when '--dow'
 
dow = arg
 
when '--date'
 
myDate = arg
 
end
 
end
 
rescue
 
  RDoc::usage
 
end
 
 
 
 
 
dateSplit = ''
 
if myDate.split('/').length == 3
 
dateSplit = myDate.split('/')
 
else
 
dateSplit = myDate.split('-')
 
end
 
 
 
myDate = Date.civil(dateSplit[0].to_i, dateSplit[1].to_i, dateSplit[2].to_i)
 
 
 
#fix for the "-30 rule"
 
fixDate = Date.civil(2008,05,25)
 
timeDelta = 0
 
if myLong.to_i > -30 and (myDate > fixDate)
 
puts "-30 rule in effect!"
 
timeDelta = 1
 
end
 
 
 
algorithmEncodedDate = myDate.to_s
 
urlEncodedDate = (myDate - timeDelta).strftime('%Y/%m/%d')
 
 
 
baseURL = 'carabiner.peeron.com'
 
basePath = '/xkcd/map/data/'
 
fullPath = basePath + urlEncodedDate
 
if dow==""
 
  Net::HTTP.start(baseURL,80) do |http|
 
    dow = http.get(fullPath).body
 
  end
 
end
 
 
 
if !dow.include? "404 Not Found"
 
ghash = algorithmEncodedDate+'-'+dow
 
digest = Digest::MD5.hexdigest(ghash)
 
digest1 = digest[0..15]
 
digest2 = digest[16..31]
 
puts "(" + myLat + "." + hexFracToDecFrac(digest1) + ", " + myLong + "." + hexFracToDecFrac(digest2) + ")"
 
else
 
puts "Dow information not available for "+urlEncodedDate
 
end
 
</pre>
 
 
 
== Erlang Implementation ==
 
{{30w compliant|yes=1}}
 
[[user:Cjk|Carl-Johan]] made a reference Erlang implementation. It should be fully 30W compliant even for retro hashes. Don't forget to run geohash:init() befor your first lookup.
 
 
 
<pre>-module(geohash).
 
-export([init/0
 
, lookup/1
 
]).
 
 
 
-record(meetup,
 
{lat
 
, lon
 
, date
 
, djiadate
 
, latdec
 
, londec
 
, latcoord
 
, loncoord
 
, djia
 
}).
 
 
 
url() ->
 
    "http://carabiner.peeron.com/xkcd/map/data/~4.10.0b/~2.10.0b/~2.10.0b".
 
 
 
int_to_dec() ->
 
    5.421010862427522e-20. %math:pow(2,-64).
 
 
 
init() ->
 
    application:start(inets),
 
    application:start(crypto).
 
 
 
lookup(Meetup = #meetup{lat=Lat, lon=Lon, date = {_Y, _M, _D}}) when
 
      Lat > -90,
 
      Lat < 90,
 
      Lon > -180,
 
      Lon < 180 ->
 
    Meetup1 = w30(Meetup),
 
    get_djia(Meetup1).
 
 
 
w30(Meetup = #meetup{lat=Lat, date = {Y, M, D}}) ->
 
    case (Lat > -30) and
 
(calendar:date_to_gregorian_days(Y, M, D) >
 
    calendar:date_to_gregorian_days(2008, 5, 26)) of
 
true  -> Meetup#meetup{
 
  djiadate =
 
      calendar:gregorian_days_to_date(
 
calendar:date_to_gregorian_days(Y,M,D)-1)
 
  };
 
false -> Meetup#meetup{
 
  djiadate={Y, M, D}
 
  }
 
    end.
 
   
 
get_djia(Meetup = #meetup{djiadate = {Y, M, D}}) ->
 
    Url = io_lib:format(url(), [Y, M, D]),
 
    case httpc:request(Url) of
 
{ok, {{"HTTP/1.1",200,"OK"},
 
      _,
 
      Djia}} -> coords(Meetup#meetup{djia=Djia});
 
{ok, {{"HTTP/1.1",404,"Not Found"},
 
      _,_}}  -> Meetup
 
    end.
 
 
 
coords(Meetup = #meetup{lat = Lat
 
, lon = Lon
 
, date = {Y, M, D}
 
, djia = Djia}) ->
 
    Str = io_lib:format("~4.10.0b-~2.10.0b-~2.10.0b-~s",
 
[Y, M, D, Djia]),
 
    <<LatInt:64,
 
      LonInt:64>> = crypto:md5(Str),
 
    LatDec = LatInt * int_to_dec(),
 
    LonDec = LonInt * int_to_dec(),
 
    Meetup#meetup{latdec = LatDec
 
  , londec = LonDec
 
  , latcoord = Lat + LatDec
 
  , loncoord = Lon + LonDec
 
}.
 
</pre>
 
 
 
==macHasher==
 
{{30w compliant|yes=1}}
 
[[image:macHasher.png|thumb|macHasher screenshot]]
 
Scottkuma worked feverishly to:
 
# learn Apple OSX Programming and...
 
# put together a [http://scottkuma.net/geohashing/macHasher.dmg geohash calculator for the Mac.]
 
 
 
===Installation:===
 
It's a normal mac application - drag it to your Applications folder, OR just run it from inside the DMG.
 
I '''think''' I compiled it as a Universal Binary.  If you can't run it on a particular system and/or version of OSX, please let me know.
 
 
 
===Usage:===
 
Start by entering your graticule's Lat/Long numbers.  The given numbers are for Cincinnati, Ohio.
 
 
 
For today's graticule, just click "Generate!"  For dates in the past (or the near-future, for Saturday & Sunday graticules), select the date on the calendar, then click "Generate!"
 
 
 
===Known bugs:===
 
* '''Requires''' a valid network connection; locks pretty good when one doesn't exist.
 
* does not calculate east of -30 correctly for dates ''prior'' to 5/27/2008
 
* window doesn't lock its size like I thought it would...
 
 
 
===Planned enhancements:===
 
* will allow for saving of a known "home" location
 
* will calculate distance & bearing to a known location
 
* will calculate same for adjacent graticules to find a closer geohash
 
 
 
==Geohash for the iPhone==
 
{{30w compliant|partial=1}}
 
[[image:geohashiphone.png|thumb|Geohash screenshot]]
 
 
 
Geohash for the iPhone is available [http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=284951057&mt=8 here] in the app store (for free).
 
 
 
The new version of Geohash now supports looking forward over the weekend.  Yay!
 
 
 
The app is partially 30W compliant. It produces the correct coordinates, but doesn't allow you to select tomorrow's date (during the week) or Monday (from Friday afternoon onward).
 
 
 
Next feature up? 
 
The most requested feature by far is the ability to view Geohash locations in surrounding graticules.
 
 
 
I'll also be publishing the source code when I get a chance. (Update:  I'm still a little unsure about the implications of Apple's NDA on their SDK.  I'm trying to determine if releasing the source violates the NDA or not.  It'll be out for sure once I make sure I won't get spanked by Apple!)
 
 
 
Thanks to Scottkuma for a spot of help with the MD5 hash conversion.
 
 
 
PS.  Obviously, feel free to leave reviews on the app store telling everyone what you think, good and bad, but also send feedback to me (casey@kckd.org), so I can respond directly!
 
 
 
== Small Hash Inquiry Tool ==
 
{{30w compliant|yes=1}}
 
 
 
Small Hash Inquiry Tool is an online tool Ekorren built to his own needs but later rebuilt to be globally usable.
 
 
 
Compared to the nifty tools like those for the iPhone, this one looks ugly to the end. Which was intended as it should be stripped from all colourful overhead, featuring just basic compressed information, all on one page and from everywhere.
 
 
 
Features:
 
 
 
* lists up to nine nearby hashpoints per day, today and upcoming (no retro)
 
* may be called from a bookmark without needing further input
 
* calculates approximate distance and direction
 
* shows the location on configurable maps on request
 
* includes the globalhash
 
* does it all at once, and
 
* is so much basic that it works from virtually every phone which isn't entirely incapable of browsing.
 
 
 
Usage information is available from it's [[User:Ekorren/Hash Inquiry Tool|own page]].
 
 
 
== Probability Calculators ==
 
 
 
These do not calculate the hash, but instead the probability of the hashpoint to land in certain areas.
 
 
 
* [[Land usage]] - calculates the probability of certain types of land (forests, water, and the like).
 
* [[Public transport probability]] - calculates the probability of a certain distance from public transport.
 
 
 
== Geohash Droid (for Android phones) ==
 
{{30w compliant|yes=1}} <!-- fixed as per 0.7.1 -->
 
 
 
[[File:GeohashDroidAppCode.png|125px|thumb|right|Scan to find the app in the Market]]
 
 
 
Geohash Droid, a small, (so far) simple little Geohashing app for Android phones, can be found in the Android Marketplace as a free app.  So far, it gets the stock and hash values, plots it out, and follows you as you get closer to it.  <strike>It also has wiki-updating features</strike> (not since recaptcha was installed) and can automatically figure out what graticule has the closest point to where you are.  Simple, effective.  There's more stuff planned, but that's later.
 
 
 
The project itself [http://code.google.com/p/geohashdroid is hosted on Google Code].  The most recent version (as per this writing) is 0.7.10.  If you go from the Marketplace (far easier), feel free to leave reviews and such.  If you have something specific to say, either file an issue at the Google Code site, hit the [http://groups.google.com/group/geohashdroid group page], or email me.
 
 
 
So hey, give it a shot!  What've you got to lose?  Enjoy!
 
 
 
==The Tablet of Adventure (Geohash for Nokia N900)==
 
{{30w compliant|yes=1}}
 
[[image:TToA.png|center|400px|Social adventure screenshot]]
 
 
 
[http://cannonerd.wordpress.com/the-tablet-of-adventure/ The Tablet of Adventure] is a social adventure gaming tool that supports geohashes. It is available for Maemo 5 (Nokia N900) [http://maemo.org/packages/view/adventure-tablet/ from Maemo Extras].
 
 
 
With TToA you can seek geohashes in your area or create your own collaborative adventures and share them via Qaiku.
 
  
Source code is available [http://github.com/cannonerd/adventure_tablet from GitHub].
+
{{:Implementations/Official}}
  
== Automatic Daily Notifications ==
+
<div style="clear:both"></div>
After registering, it will automatically notify users about all hashpoints as soon as they become available.  Graticules are divided into 100 sub-graticules to allow users to only be notified when a hashpoint is near home, or alternatively, for all accessible hashpoints in a graticule.  For more information, see the [[User:Aperfectring/Notification|program's page]]. 
+
= Online calculators =
  
[[Category:Algorithm]]
+
{{:Implementations/Online}}
[[Category:Definitions]]
 
  
== Geohash module for phenny IRC bot ==
+
<div style="clear:both"></div>
{{:User:Relet/Shmulik}}
+
= Feeds / Web Services =
  
== Active Geohasher ==
+
{{:Implementations/Web services}}
{{30w compliant|yes=1}}
 
[http://activegeohasher.com/ Active geohasher] is a web application by [[User:Sermoa|Sermoa]] which provides resources for geohashers. You can subscribe to graticules to receive a daily email containing the address, distance from your home location, and useful links. It also tells you the globalhash.
 
  
The site provides graticule integration with twitter, flickr and youtube. A google earth feed is provided per gratiucule. Every geohash has a page showing various google maps, useful links and a PDF poster which you can download and print to take to the geohash.
+
<div style="clear:both"></div>
 +
= Mobile apps and applications =
  
Active geohasher is [http://github.com/sermoa/active_geohasher open source] (written in Ruby on Rails). Please contribute if you have ideas or would like to translate it into a different language. There is also a twitter account that delivers news and direct message geohashing notifications: @[http://twitter.com/activegeohasher activegeohasher]
+
{{:Implementations/Apps}}
  
== JSON Web Service ==
+
<div style="clear:both"></div>
{{30w compliant|yes=1}}
+
= Libraries =
A geohashing JSON web service is available at:
 
<tt><nowiki>http://relet.net/geo/[lat]/[lon]/[YYYY-mm-dd]</nowiki></tt> ([http://relet.net/geo/60/10/2008-05-27 example])
 
The output will contain the following values in a dictionary:
 
* error - if an error occurred retrieving the data - example: "DJIA for 2011-12-24 not available yet."
 
* exception - if an error occurred parsing the input or calculating the output - example: "time data '2011-13-24' does not match format '%Y-%m-%d'"
 
or:
 
* djia - DJIA as retrieved from geo.crox
 
* lat - latitude of the geohash
 
* lon - longitude of the geohash
 
* graticule - name of the graticule (may be null)
 
* global-lat - latitude of the globalhash
 
* global-lon - longitude of the globalhash
 
* ... - additional data may be present in the reply. This service may be extended in the future.
 
If you omit the date, you will only receive the name of the graticule.
 
  
== Geco ==
+
{{:Implementations/Libraries}}
{{30w compliant|yes=1}}
 
A re-implementation by [[user:Relet|Relet]] of the official map using leaflet/cloudmade and the above web service. By using geo.crox as a data source, it is hopefully more reliable than the official map.
 
  
http://relet.net/geco
+
<div style="clear:both"></div>
 +
= Miscellaneous utilities =
  
Parameters:
+
{{:Implementations/Utilities}}
* lat - latitude of the initial graticule
 
* lon - longitude of the initial graticule
 
* zoom - initial zoom level
 
* date - initial date in YYYY-MM-DD format
 
  
e.g: http://relet.net/geco/?date=2005-05-26&lat=37&lon=-122&zoom=8
+
<div style="clear:both"></div>
 +
= Broken Implementations =
  
==HashPlacer==
+
'''Note: [[Implementations/Broken]] contains a few more implementations which are known not to work any longer.'''
The HashPlacer is a perl script that allows you to define limit boxes on a map, and will notify you via email if the day's geohash point lands in one of these boxes. This is especially useful if you define a limit box surrounding your favorite park, or your neighborhood, or even your [[Couch Potato Geohash|couch]]. Currently the only areas supported are "boxes"... two latitude points and two longitude points define the corners of a [[graticule]]-shaped "box".
 
  
[[User:AeroIllini/HashPlacer]]
+
[[Category:Geohashing guide]]

Latest revision as of 21:34, 4 May 2013

Definition

An implementation is a program that takes the method shown in The Algorithm to calculate the geohash location, presenting the user with text coordinates, a map, data for a navigation device, or some other information that facilitates reaching the geohash.

If you're looking to code your own utilities, you will need a source that provides the Dow's opening price for any given day. Details on such services are available at Dow Jones Industrial Average.

Official Implementations

Reference Implementation

This implementation IS FULLY 30W-compliant.

A reference perl implementation is available: view download

It cannot automatically apply the 30W rule, as it doesn't take your location into consideration. If you're East of 30W, call it with the -e option and it will yield the correct results.

Any problems or issues should be mentioned to Zigdon either on the wiki or in the Geohashing IRC channel, as well as posted at Talk:Implementations.

MediaWiki Implementation

This implementation's 30W-compliance is tied to that of another implementation. See notes.

MediaWiki half-implementation (for use by template creators).

Online calculators

Eupeodes's geohashing map

Eupeodes's geohashing map
This implementation IS FULLY 30W-compliant.

An implementation using openlayers. Gives 3 x 3 hashes, with option to download as GPX. Uses geo.crox as data source. This implementation works very well on both desktop and mobile.

https://geohashing.info

See the help on the site for url parameters.

Small Hash Inquiry Tool

This implementation IS FULLY 30W-compliant.

Small Hash Inquiry Tool is an online tool Ekorren built to his own needs but later rebuilt to be globally usable.

Compared to the nifty tools like those for the iPhone, this one looks ugly to the end. Which was intended as it should be stripped from all colourful overhead, featuring just basic compressed information, all on one page and from everywhere.

Features:

  • lists up to nine nearby hashpoints per day, today and upcoming (no retro)
  • may be called from a bookmark without needing further input
  • calculates approximate distance and direction
  • shows the location on configurable maps on request
  • includes the globalhash
  • does it all at once, and
  • is so basic that it works from virtually every phone which isn't entirely incapable of browsing.

Usage information is available from its own page.

Geohashing Poster Tool

This implementation IS FULLY 30W-compliant.
sample output

This tool produces a PDF document that can be printed out, similar to the ones that were available from Active Geohasher.

Posters are available from the following URL:

 http://geo.crox.net/poster/[date]_[lat]_[lon]

Minimal globalhash support is also available:

 http://geo.crox.net/poster/[date]_global

From an expedition page, you can link to the poster like this:

 [http://geo.crox.net/poster/{{FULLPAGENAME}} Poster for this expedition]

For more information, credits and feedback, see User:Crox/Poster.

Quick & Dirty Geohash Navigator

QDGN is an online tool written by Kripakko. It shows the client's location, as well as the nearest Geohash and its location, both as text and on a map.

Shotgun

This implementation IS FULLY 30W-compliant.

Shotgun Retro search tool. Multiple locations can be shown on the same map, using custom filters.

(Updated on 12th September 2015 to fix a 30W issue.)

Features:

  • Option to limit the search to an area of interest, for example an island you live on, an area close to you, or just a favourite area.
  • Search instances of a specific day of the year within the area, for example your birthday or anniversary.
  • Show all matching results on a single map using Google Maps markers.

Example uses:

  • View all 2015 location on La Gomera. [1]
  • Search for 21st May locations on the Isle of Wight since 2008. [2]
  • Prove that the last location on land in the Lizard Point was September 22nd, 2019. [3]

Future plans include creating a graphical selector for the graticule, and area of interest.

Note: This tool uses a private data source that needs to be manually updated, so it may be missing the last week or so of recent hashpoints.

Written by Zamzara

KML Tool

This implementation IS FULLY 30W-compliant.

Sourcerer KML.jpg


Please double check the output - it has been tested but ...


Sourcerer has made a geohash KML calculator. The source code is available on GitHub.

  • This makes KML data which loads for viewing into Google Earth Desktop or similar applications like Marble. This might download as text if Google Earth Desktop is not installed.
Why?
Well there's no point having a dog and barking yourself.
Google Earth Desktop has powerful functionality and there's not much point re-inventing these features.

Usage instructions, bug reporting and feature requests are on the Sourcerer/KML tool page.

Feeds / Web Services

DJIA sources

See: Dow Jones Industrial Average for a list of data sources for the DJIA openings.

RSS/Atom

Phyzome's feed

This implementation IS FULLY 30W-compliant.

Subscribe to a feed that updates as soon as each day's meetup is calculable for your graticule:

https://lab.brainonfire.net/geohash.info/srv/feed.php?lat=LAT&lon=LON

If you visit the URL with no parameters, you will be prompted for your graticule coordinates.

  • Dow data comes from the peeron service
  • To view source, drop the parameters and change the extension to .phps -- this currently works for all PHP files in geohash.info/srv/
Quirks
  • The script estimates your timezone based upon your longitude, and uses -04:30 as the timezone of the Dow. Therefore, the update times may be off by as much as an hour or two. Shouldn't be an issue, since they'll be around midnight for most people.
  • For non-30W users, the feed will be empty between midnight and 9:30 AM -- this should be acceptable, since most feed readers keep entries that have dropped off the end of the feed. (This behavior may be changed in the future.)

Geo Hashing RSS

This implementation IS FULLY 30W-compliant.

Another RSS implementation, coded by Matty K. This one simply provides a graticule's coordinates for a given day, and gives links to both Google maps and the peeron maplet. It is recalculated at every request (so please don't hammer it, or my website will run out of bandwidths).

http://geohashing.kerwin.net.au/rss.php?ll=LAT,LON

For example, the link for San Francisco's feed is: http://geohashing.kerwin.net.au/rss.php?ll=37,-122

Notes:

  • If latitude/longitude are not given, it defaults to my home graticule .
  • I don't know if it supports negative zero. If there is a request to add specific support, please let me know. I added specific negative zero support, and tested it with the London area. It appeared to work okay.
  • 30W-compliance is based on the fact that I live East of 30W, and it gives me the right coordinates each day.
  • For any bug reports or other features requests, please email Matty
  • Sources can be made available by request. Although Matty might be a little ashamed of the shoddy code.

Automatic Daily Notifications

After registering, it will automatically notify users about all hashpoints as soon as they become available. Graticules are divided into 100 sub-graticules to allow users to only be notified when a hashpoint is near home, or alternatively, for all accessible hashpoints in a graticule. For more information, see the program's page.

Mobile apps and applications

Geohash Droid (Android)

This implementation IS FULLY 30W-compliant.
Scan to find the app in the Market

Geohash Droid, a simple Geohashing app for Android phones, can be found here in the Google Play Store as a free app. It gets the stock and hash values, plots it out, and follows you as you get closer to it. It also has wiki-updating features and can automatically figure out what graticule has the closest point to where you are. Simple, effective. There's more stuff planned, but that's later.

The project itself is hosted on GitHub. The most recent version (as per this writing) is 0.9.5.5. If you go from the Play Store (far easier), feel free to leave reviews and such. If you have something specific to say, please file an issue at the GitHub site or email CaptainSpam.

gHash for the iPhone (under development)

This implementation IS FULLY 30W-compliant.
gHash for iPhone (work in progress)

This is not yet finished, but if you’re interested in learning more or being a beta tester let me know on my talk page.

Features

  • Closest hash point to you (even if it’s in another graticule - good for split graticules)
  • Integrated map
  • Links to either Google Maps or Apple Maps (your choice)
  • Links to the “Internet was here” poster for that hash point

Planned Future Features

  • Phone notification if the day’s hash point is within a certain distance of your location

Possible Future Features

  • Global hash
  • Let me know what you would use!

Nokia N900

This implementation IS FULLY 30W-compliant.
Social adventure screenshot

The Tablet of Adventure is a social adventure gaming tool that supports geohashes. It is available for Maemo 5 (Nokia N900) from Maemo Extras.

With TToA you can seek geohashes in your area or create your own collaborative adventures and share them via Qaiku.

Source code is available from GitHub.

Libraries

D

Local email tool in D, for Linux
This implementation IS FULLY 30W-compliant.

Run this program once a day (for instance, per crontab) to get email notification whenever Google Maps indicates the daily target is nearer than a specified range. The first time around, run it from the commandline to configure. Configuration is stored in ~/.geohash/geohash.cfg. Use --help for info about commandline parameters. Source. Linux 32-bit upx compressed binary. - Ported it again to my own language. Source. Linux 32-bit binary

Erlang

This implementation IS FULLY 30W-compliant.

Implementations/Libraries/Erlang

Clojure

This implementation IS FULLY 30W-compliant.

A geohash and globalhash library in Clojure: https://github.com/timmc/geohash

Maintained by Phyzome, who also runs an email autoresponder that uses this library.

Java

This implementation IS FULLY 30W-compliant.

A Java port of the Python implementation can be found from GitHub.

Javascript

Semi-manual offline calculator
This implementation IS FULLY 30W-compliant.

If you're going to be away from internet access, you'll need to compute the hash locally:

Notes
  • All you need is a Javascript-enabled browser. Tested in Firefox so far.
  • You will have to somehow acquire the Dow's opening value for the appropriate date; there may be a service to do this.
    • Remember, if you're east of 30W, you should use the previous day's opening price, even if a new one becomes available later in the day.
  • The date is filled in automatically using the current timestamp.
  • You'll have to combine the computed fractional coordinates with your graticule coordinates yourself.
  • I grabbed MD5 and base conversion code from random internet sites.

k4

This implementation IS NOT 30W-compliant.

Implementations/Libraries/k4

Lua

This implementation IS FULLY 30W-compliant.

Geohash and globalhash calculation in Lua (almost pure, uses wget for web access): https://github.com/atenfyr/luaGH

Mathematica

This implementation IS FULLY 30W-compliant.

Geohashing in Mathematica

perl

Geo::Hashing on CPAN

This implementation IS FULLY 30W-compliant.

Reusable code library that can be used from any perl program:

Geo::Hashing Sample code

Alternative implementations

This implementation IS FULLY 30W-compliant.

Alternatives to the official implementation can be found at Implementations/Libraries/Perl.

Python

geohashing.py

A python script by User:Cole that can calculate geohash coordinates, given a graticule. It can calculate globalhashes as well. It is meant to be used from the command line, but is based around functions that can be used for library usage.

Code snippets

This implementation IS FULLY 30W-compliant.

Various code snippets can be found at Implementations/Libraries/Python.

Python package xkcd.geohash

This implementation IS NOT 30W-compliant.

There is Python package xkcd.geohash which is independent of the interactive coordinate calculator (but uses Google Finance as well).

Python 3 standard library

In Python 3.1 and above, an implementation of the geohashing algorithm is included in the antigravity module. Unfortunately importing the module will open a web browser.

>>>import antigravity
(opens the xkcd comic)
>>>antigravity.geohash(34,-118,b'2012-04-09-13057.57')
34.386614 -118.231675

RESTful implementation with Atom feed

This implementation IS FULLY 30W-compliant.

The source for the Atom feed is available through anonymous svn here: https://staticfree.info/svn/ghfeed/

This implementation uses web.py to give simple, clean URLs. To contribute to it, please contact xxv and he can set you up with commit access.

Ruby

This implementation IS FULLY 30W-compliant.

Implementations/Libraries/Ruby

Rust

This implementation IS FULLY 30W-compliant.

Available on crates.io or GitLab.

Maintained by Kellerkind.

Shell Script

This implementation IS FULLY 30W-compliant.

Implementations/Libraries/Shell

C#

This implementation IS FULLY 30W-compliant.

A C# command line tool, using dotnet core 3.1, where the implementation can easily be copied to other projects. Just copy two files and don't forget to mention where you found them.

Relies on geo.crox.net for the Dow Jones industrial average.

Source code and a windows binary is available on Göran Roseen's github

Maintained by Göran Roseen.

Miscellaneous utilities

Comic Creator

This implementation IS FULLY 30W-compliant.

A python class to recreate the original comic, but for any given date with your own coordinates! Created by Hugo.

The comic creator has been moved to github: https://github.com/hugobuddel/geohashingcomic

It used to run as a cgi service, but these are all down now.

In the image, Dow values less than 10,000.00 are padded with leading spaces, however in the algorithm it is not so it is compliant with other the algorithms. As Tim P suggested, the comic is akin to all the bank cheques with "19__" printed on them being used in 2000. The "form" has 5+2 "boxes" because that's how Dow prices are now, but that doesn't mean it can't be different.

Bugs
  • The font sizes are not exactly as the original and there can still be some alignment problems.
  • The -0 issue is ignored. Only if you enter -0 as an integer you get an incorrect outcome. You are supposed to enter your own location as a float, up to 6 decimals, everything is okay even when you enter -0.0.

Hashie (IRC bot)

This implementation IS FULLY 30W-compliant.

Because the Shmulik bot and relet are not online Eupeodes created a new bot. Over the coming time features will be implemented in an attempt to fill the gap left by shmulik. Documentation can be found on Eupeodes/Hashie

Probability Calculators

These do not calculate the hash, but instead the probability of the hashpoint to land in certain areas.

  • Land usage - calculates the probability of certain types of land (forests, water, and the like).
  • Public transport probability - calculates the probability of a certain distance from public transport.

HashPlacer

The HashPlacer is a perl script that allows you to define limit boxes on a map, and will notify you via email if the day's geohash point lands in one of these boxes. This is especially useful if you define a limit box surrounding your favorite park, or your neighborhood, or even your couch. Currently the only areas supported are "boxes"... two latitude points and two longitude points define the corners of a graticule-shaped "box".

User:AeroIllini/HashPlacer

GeoHistory

GeoHistory is a perl script that outputs a [kml] file containing every historical geohash point in a specific graticule since a specified date. This can be used to get a retroactive Couch Potato Award, apply for a Curse of Unawareness Award, or simply study past geohash points.

User:AeroIllini/GeoHistory

notify-send bash tool

Linux users can use this bash script to give them desktop warnings of nearby geohashes. notify-send, bc, sed, xml_grep are needed to run the tool. It will but has not been tested within cron at the time of this writting.

Regiohashing Minesweeper Tool

These were created to help people display their regiohash achievement progress.

Mepohash

This implementation IS FULLY 30W-compliant.

Mepo is "a fast, simple, hackable OSM map viewer for mobile and desktop Linux." It also happens to be my maps app of choice. Due to it's scriptable nature, I naturally wanted to integrate geohashing into my map solution to make geohashing on my Pinephone as seamless as possible. Also, as someone newer to bash scripting this was an interesting exercise in creating an implementation from scratch. I bring to you mepo_geohash.sh, a simple 30W compliant script that opens Mepo to the detected graticule's hashpoint of the day. By moving the map and calling the script again, you can get the hashpoint for the graticule you moved to. You can view the script at this mailing list, whether it gets accepted into the main project or not I hope someone can get use out of this handy little script.

User:Hamblingreen

Broken Implementations

Note: Implementations/Broken contains a few more implementations which are known not to work any longer.