Difference between revisions of "Implementations"

From Geohashing
(Automatic GPX File Generator)
imported>R0d3n7z
(revert spam by 92.48.114.82 to last version by Zigdon)
Line 1: Line 1:
 
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]].
  
6F4MhP  <a href="http://jojecsnylmvp.com/">jojecsnylmvp</a>, [url=http://pxqfglovadqf.com/]pxqfglovadqf[/url], [link=http://mfdoaxgripoc.com/]mfdoaxgripoc[/link], http://snervepojheb.com/
+
== Official Implementations ==
  
I have seen all Internet... Anything... ,  http://oratiursal.nireblog.com/post/2008/06/22/alice-cooper-press-kit alice cooper press kit
+
=== Interactive Coordinate Calculator ===
038559,  http://ottymaky.wordpress.com/2008/06/22/alice-cooper-brutal-planet/ alice cooper brutal planet
+
{{30w compliant|yes=1}}
  rxpnb, http://ulasanche.wordpress.com/2008/06/22/alice-cooper-frankenstien/ alice cooper frankenstien
+
The original sample interactive coordinate calculator can be found at [http://irc.peeron.com/xkcd/map http://irc.peeron.com/xkcd/map]. The common URL, [http://xkcd.com/geohashing http://xkcd.com/geohashing], redirects hereAny 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]].
muxej,  http://searfrodin.nireblog.com/post/2008/06/22/alice-cooper-tablature alice cooper tablature
 
zybah, http://blogs.grab.com/cazharve/590621 desperado alice cooper
 
510124, http://physhany.wordpress.com/2008/06/22/alice-com-com-cooper-google/ alice com com cooper google
 
037716,  http://ulasanche.wordpress.com/2008/06/22/alice-cooper-dvds/ alice cooper dvds
 
65593,  http://blogs.grab.com/cazharve/590632 hard rock summer alice cooper
 
:-(((, http://ulasanche.wordpress.com/2008/06/22/alice-cooper-dvd-trade/ alice cooper dvd trade
 
cyvq,
 
  
The Friends, who heard what your opinion on the about the? ,  http://malduanbj.nireblog.com/post/2008/06/22/alice-cooper-im-eighteen-mp3 alice cooper im eighteen mp3
+
=== Reference Implementation ===
=)),  http://oratiursal.nireblog.com/post/2008/06/22/alice-cooper-restaurant-phoenix alice cooper restaurant phoenix
+
{{30w compliant|yes=1}}
6880,  http://blogs.grab.com/fayvern/590645 rusty alice cooper royce
+
A reference implementation is available:
70093,  http://ottymaky.wordpress.com/2008/06/22/alice-cooper-clones-lyrics/ alice cooper clones lyrics
 
405,  http://ottymaky.wordpress.com/2008/06/22/alice-cooper-concert-history/ alice cooper concert history
 
:)),  http://ulasanche.wordpress.com/2008/06/22/alice-cooper-eighteen-tab/ alice cooper eighteen tab
 
712688,  http://oratiursal.nireblog.com/post/2008/06/22/alice-cooper-restaurant-cleveland alice cooper restaurant cleveland
 
>:OO,  http://searfrodin.nireblog.com/post/2008/06/22/alice-cooper-schools-out-for-summer alice cooper schools out for summer
 
5052,  http://ellwyla.nireblog.com/post/2008/06/22/adult-acute-myeloid-leukemia adult acute myeloid leukemia
 
mbixvq,
 
  
I sell the. Write on mine e-mail.,  http://glynnquabi.nireblog.com/post/2008/06/22/adult-animated-card-greeting adult animated card greeting
+
[http://irc.peeron.com/xkcd/map/sample.pl.html view] [http://irc.peeron.com/xkcd/map/sample.pl download]
zkmctv,  http://glynnquabi.nireblog.com/post/2008/06/22/adult-animated-cartoons-free adult animated cartoons free
 
3929,  http://ulasanche.wordpress.com/2008/06/22/alice-cooper-im-eighteen/ alice cooper i'm eighteen
 
agzma,  http://ottymaky.wordpress.com/2008/06/22/alice-cooper-dead-baby/ alice cooper dead baby
 
8)),  http://physhany.wordpress.com/2008/06/22/alice-cooper-trash/ alice cooper - trash
 
gwnhgl,  http://blogs.grab.com/neylsanj/590676 adult asian live web cam
 
34567,  http://ulasanche.wordpress.com/2008/06/22/alice-cooper-i-love-the-dead-lyrics/ alice cooper i love the dead lyrics
 
804,  http://ellwyla.nireblog.com/post/2008/06/22/adult-add-com adult add com
 
>:],  http://blogs.grab.com/cazharve/590655 eighteen alice cooper lyrics
 
5247,
 
  
Order and buy the in ours online-shop! , http://blogs.grab.com/neylsanj/590708 adult ass dating rumprater.com
+
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.
=-PP, http://ottymaky.wordpress.com/2008/06/22/alice-cooper-detroit/ alice cooper detroit
 
43597,  http://quynwalt.nireblog.com/post/2008/06/22/adult-adventure-games adult adventure games
 
epncd,  http://blogs.grab.com/neylsanj/590694 adult asian film
 
rigsg,  http://blogs.grab.com/neylsanj/590687 adult asian free video
 
261,  http://glynnquabi.nireblog.com/post/2008/06/22/adult-animated-clip adult animated clip
 
omwuf,  http://glynnquabi.nireblog.com/post/2008/06/22/adult-animated-dirty-cartoons adult animated dirty cartoons
 
csob,  http://meegiverna.nireblog.com/post/2008/06/22/adult-american-bulldogs-for-sale adult american bulldogs for sale
 
06786,  http://ottymaky.wordpress.com/2008/06/22/alice-cooper-desperado-lyrics/ alice cooper desperado lyrics
 
2776,
 
  
And who sells? Give its phone number? The under the low prices! Call or write!,  http://ellwyla.nireblog.com/post/2008/06/22/adult-add-online adult add online
+
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]].
%-]]],  http://meegiverna.nireblog.com/post/2008/06/22/adult-amidala-costume adult amidala costume
 
cbiimt,  http://blogs.grab.com/tadlwendel/590743 adult art bondage work
 
abuimg,  http://blogs.grab.com/tadlwendel/590755 adult arizona entertainment
 
%)),  http://blogs.grab.com/garlywartin/590730 adult babe bomis video
 
knn,  http://pinglen.nireblog.com/post/2008/06/22/adult-adultdvdonlinestorenet-college-dvd-movie-sex-video adult adultdvdonlinestore.net college dvd movie sex video
 
=]]], http://tashylato.wordpress.com/2008/06/22/2-adult-sims-skin/ 2 adult sims skin
 
:-[,  http://glynnquabi.nireblog.com/post/2008/06/22/adult-animated-fantasy adult animated fantasy
 
=-[,  http://blogs.grab.com/garlywartin/590732 adult babe baby erotic lady most teen woman
 
>:OOO,
 
  
Would you like to see. Coquitlam provides both garbage and recycling collection for City residents, along with drop-off locations for larger disposal items and composting information.,  http://meegiverna.nireblog.com/post/2008/06/22/adult-among-suicide-teen-young adult among suicide teen young
+
=== Geo::Hashing on CPAN ===
8-],  http://tashylato.wordpress.com/2008/06/22/1st-adult-finder-friend-friendfindinginfo-in-matchmaking/ 1st adult finder friend friendfinding.info in matchmaking
+
{{30w compliant|yes=1}}
8-OOO,  http://blogs.grab.com/neylsanj/590772 adult asian model
+
Reusable code library that can be used from any perl program:  
jxf,  http://quynwalt.nireblog.com/post/2008/06/22/adult-adventure-free-game-sex adult adventure free game sex
 
8O,  http://blogs.grab.com/tadlwendel/590789 adult arlington care facility
 
rwjvv,  http://blogs.grab.com/neylsanj/590762 adult asian clip movie
 
gbmm,  http://blogs.grab.com/neylsanj/590777 adult aspergers syndrome
 
32907,  http://blogs.grab.com/tadlwendel/590792 adult arizona hotel motel xxx
 
>:-((,  http://meegiverna.nireblog.com/post/2008/06/22/adult-among-cigarette-smoking adult among cigarette smoking
 
uayk,
 
  
Where it is possible to order the in us?,  http://bisrahma.wordpress.com/2008/06/22/3d-adult-animated-comic/ 3d adult animated comic
+
[http://search.cpan.org/search?query=Geo%3A%3AHashing&mode=all Geo::Hashing]
373,  http://blogs.grab.com/tadlwendel/590829 adult arcade video game
+
[http://search.cpan.org/src/ZIGDON/Geo-Hashing-0.03/lib/sample.pl Sample code]
%[[,  http://blogs.grab.com/gaenagerla/590828 adult audience figurine item mature
 
52282,  http://blogs.grab.com/tadlwendel/590832 adult archie comic
 
8-(((,  http://blogs.grab.com/garlywartin/590810 adult babies
 
807135,  http://blogs.grab.com/neylsanj/590842 adult asian web cam
 
ils,  http://blogs.grab.com/garlywartin/590802 adult baby and diaper lover stories
 
8-DD,  http://blogs.grab.com/tadlwendel/590825 adult arcade location video
 
0241,  http://blogs.grab.com/gaenagerla/590830 adult audience item mature toy
 
9389,
 
  
The City of Arlington's goal is 500 pledges. Thank you for doing your part.,  http://blogs.grab.com/marheyd/590885 similar site youtube
+
=== MediaWiki Implementation ===
amyu,  http://quynwalt.nireblog.com/post/2008/06/22/adult-adultnewreleasecom-dvd-lesbian-movie-porn-star-video adult adultnewrelease.com dvd lesbian movie porn star video
+
{{30w compliant|tied=1}}
cryoc,  http://quynwalt.nireblog.com/post/2008/06/22/adult-adultnewreleasecom-download-dvd-movie-movie-porn-sex-star adult adultnewrelease.com download dvd movie movie porn sex star
+
[[MediaWiki Implementation|MediaWiki half-implementation]] (for use by template creators).
=[[[,  http://havilynd.wordpress.com/2008/06/22/80-adult-older/ 80 adult older
 
xgxtg,  http://blogs.grab.com/tadlwendel/590876 adult archive erotica jpeg pic posting
 
881,  http://blogs.grab.com/tadlwendel/590873 adult archive comic
 
910077,  http://urantail.nireblog.com/post/2008/06/22/adult-allegheny-county-probation adult allegheny county probation
 
68385,  http://manfalbu.wordpress.com/2008/06/22/adhd-adult-because-can-trauma-witnessing/ adhd adult because can trauma witnessing
 
>:(((,  http://tashylato.wordpress.com/2008/06/22/1af1934-adultresults2ejsp1f-jrun-search-search/ 1af1934 adultresults2ejsp1f jrun search search
 
=P,
 
  
I have an information on the the is well! , http://wakchio.nireblog.com/post/2008/06/22/adult-affiliate-marketing-programs adult affiliate marketing programs
+
== Python Implementations ==
9284,  http://blogs.grab.com/reyndarian/590913 adult author boyd david young
+
=== Python Implementation 1 ===
%[[,  http://ivortarco.nireblog.com/post/2008/06/22/adult-anime-free-porn adult anime free porn
+
{{30w compliant|yes=1}}
  jaofj,  http://wakchio.nireblog.com/post/2008/06/22/adult-affiliate-click-pay-per-program adult affiliate click pay per program
+
<pre>import hashlib, datetime, struct, urllib, re, sys
  8D, http://glynnquabi.nireblog.com/post/2008/06/22/adult-animated-graphic adult animated graphic
+
date = datetime.date.today()
  193559,  http://wakchio.nireblog.com/post/2008/06/22/adult-affiliate-book-guest-inurl-program-toy adult affiliate book guest inurl program toy
+
djia = urllib.urlopen((date - datetime.timedelta(w30)).strftime("http://irc.peeron.com/xkcd/map/data/%Y/%m/%d")).read()
lthdg, http://meegiverna.nireblog.com/post/2008/06/22/adult-amoxicillin-dose adult amoxicillin dose
+
if djia.find('404 Not Found') >= 0: sys.exit(sys.stderr.write("Dow Jones not available yet.\n"))
29821,  http://evapeel.nireblog.com/post/2008/06/22/adult-adult-adultdvdonlinestorenet-movie-porn-sale-video adult adult adultdvdonlinestore.net movie porn sale video
+
sum = hashlib.md5("%s-%s" % (date, djia)).digest()
wtpac, http://blogs.grab.com/gaenagerla/590898 adult austin in outpatient treatment young
+
lat, lon = [x/2.**64 for x in struct.unpack_from(">QQ", sum)]; print lat, lon
842331,
+
</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 deprected in favor of <code>hashlib</code> since python 2.5, if you are using python 2.4 or earlier, substitude <code>hashlib</code> for <code>md5</code>.
 +
 
 +
=== 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://irc.peeron.com/xkcd/map/data/%Y/%m/%d")).read()
 +
if djia.find('404 Not Found') >= 0: 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 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.
 +
 
 +
== Shell Script Implementation ==
 +
{{30w compliant|yes=1}}
 +
 
 +
<pre>
 +
#!/bin/sh -e
 +
 
 +
command -v GET > /dev/null 2>&1 || GET() { fetch -qo- "$@" || wget -qO- "$@"; }
 +
command -v md5 > /dev/null 2>&1 || md5() { md5sum | cut -c 1-32; };test -n "$1"
 +
[ "$2" -gt -30 ] && { date -R > /dev/null 2>&1 && y='-d -1day' || y='-v -1d'; }
 +
d=$(GET http://irc.peeron.com/xkcd/map/data/`date $y +%Y/%m/%d`);printf `date \
 +
+%F-$d` | md5 | tr a-f A-F | sed "s/.\{16\}/.&LgPp/g" | dc -e [$2]Sg[$1]Sg16i -
 +
</pre>
 +
 
 +
Pass your graticule's lat and long as the arguments to the script. This works with GNU/FreeBSD date, GET/fetch/wget, and bash/ksh/ash, but does not work with OpenBSD date or curl (suggestions 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>
 +
 
 +
== Alternative geohash location suggester ==
 +
{{30w compliant|yes=1}}
 +
[http://geohashing.electronicwar.net/ Geohash Recommender]
 +
 
 +
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. A webservice to access it can be found [http://geohashing.electronicwar.net/cgi-bin/geohashing.py?date=2008-05-20&xloc=-2&yloc=50 JSON Web Service]. 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)
 +
 
 +
== 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.
 +
=== 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)
 +
 
 +
== 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.
 +
 
 +
== 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 ==
 
== GeohashGenerator for Popfly ==

Revision as of 12:32, 22 June 2008

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

Interactive Coordinate Calculator

This implementation IS FULLY 30W-compliant.

The original sample interactive coordinate calculator can be found at http://irc.peeron.com/xkcd/map. The common URL, http://xkcd.com/geohashing, redirects here. Any problems or issues should be mentioned to Zigdon either on the wiki or in the [#geohashing channel on irc.foonetic.net], as well as posted at Talk:Implementations.

Reference Implementation

This implementation IS FULLY 30W-compliant.

A reference 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 channel on irc.foonetic.net], as well as posted at Talk:Implementations.

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

MediaWiki Implementation

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

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

Python Implementations

Python Implementation 1

This implementation IS FULLY 30W-compliant.
import hashlib, datetime, struct, urllib, re, sys
date = datetime.date.today()
djia = urllib.urlopen((date - datetime.timedelta(w30)).strftime("http://irc.peeron.com/xkcd/map/data/%Y/%m/%d")).read()
if djia.find('404 Not Found') >= 0: 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
  • In the above, w30 on line 3 should be replaced by 1 if you're east of -30°, and with 0 otherwise.
  • As md5 has been deprected in favor of hashlib since python 2.5, if you are using python 2.4 or earlier, substitude hashlib for md5.

Python Implementation 2

This implementation IS FULLY 30W-compliant.
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://irc.peeron.com/xkcd/map/data/%Y/%m/%d")).read()
if djia.find('404 Not Found') >= 0: 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)
  • The above code is based on the earlier sample code, and is subject to the same provisos regarding md5 and hashlib.
  • 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: python geohash.py 34 -87 (substituting my example with the latitude and longitude of your choice).

Python package xkcd.geohash

This implementation IS NOT 30W-compliant.

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

RESTful Python implementation with Atom feed

This implementation IS FULLY 30W-compliant.

This implementation uses web.py to give simple, clean URLs.

The source for the Atom feed is available through anonymous svn here: https://staticfree.info/svn/ghfeed/ To contribute to it, please contact xxv and he can set you up with commit access.

Shell Script Implementation

This implementation IS FULLY 30W-compliant.
#!/bin/sh -e

command -v GET > /dev/null 2>&1 || GET() { fetch -qo- "$@" || wget -qO- "$@"; }
command -v md5 > /dev/null 2>&1 || md5() { md5sum | cut -c 1-32; };test -n "$1"
[ "$2" -gt -30 ] && { date -R > /dev/null 2>&1 && y='-d -1day' || y='-v -1d'; }
d=$(GET http://irc.peeron.com/xkcd/map/data/`date $y +%Y/%m/%d`);printf `date \
+%F-$d` | md5 | tr a-f A-F | sed "s/.\{16\}/.&LgPp/g" | dc -e [$2]Sg[$1]Sg16i -

Pass your graticule's lat and long as the arguments to the script. This works with GNU/FreeBSD date, GET/fetch/wget, and bash/ksh/ash, but does not work with OpenBSD date or curl (suggestions 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".

#!/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)

Alternative geohash location suggester

This implementation IS FULLY 30W-compliant.

Geohash Recommender

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. A webservice to access it can be found JSON Web Service. The code is over here 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. --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. --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?  ;) Ted 00:19, 30 May 2008 (UTC)

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! Below shows the comic for the first North East Netherlands meetup. Although it fetches the Dow itself, you can add &dowjones=12345.67 if it doesn't do so correctly (e.g., peeron.com is down). Created by 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 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 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.

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.

Text Messaging (email) service

This implementation IS FULLY 30W-compliant.

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:

2008-02-18 42 -83

Alternatively, it defaults to the current date (EST for now) and you can just enter Latitude and Longitude

42 -83

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)

Feeds

GeoRSS feed

This implementation IS NOT 30W-compliant.

You can subscribe to a feed (in GeoRSS format) that will give you updates on a daily basis[citation needed]. Updates include the "best guess" address of the location as well as the specific latitude/longitude coordinates.

http://atlas.freshlogicstudios.com/Features/Experiments/Xkcd/Xkcd.ashx?Latitude=38&Longitude=-91

For example, here's the GeoRSS geohash for St. Louis.

This GeoRSS feed is used to power the Atlas geohash implementation.

Atom feed

This implementation IS FULLY 30W-compliant.

You can subscribe to a feed that will give you updates on a daily basis:

http://staticfree.info/geohash/atom/LAT,LON

For example, here's the 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. -- 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 USET east of 30W, until 24:00 local. See detailed discussion at Talk:Implementations#Atom feed 30W-compliance. --Tim P 15:45, 29 May 2008 (UTC)

geohash.info

This implementation IS FULLY 30W-compliant.

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 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.)

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 this RSS feed link.

k4 implementation

This implementation IS NOT 30W-compliant.

Here's an implementation in 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.

#!/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

For example, here's New York as of 2008-05-23:

% gh 40 -74
http://maps.google.com/maps?q=40.126648+-74.5475331

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).

Adavies42 20:50, 23 May 2008 (UTC)

Automatic GPX File Generator

This implementation IS NOT 30W-compliant.

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. 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

This implementation IS FULLY 30W-compliant.

I have created a Popfly block to use for creating mashups at http://www.popfly.com/users/rbuckton/GeohashGenerator. Can be integrated with Virtual Earth, etc.

rbuckton

Lazy Geohasher

This implementation IS PARTIALLY 30W-compliant.

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 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! -- 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.

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.

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.

This implementation IS PARTIALLY 30W-compliant.
#!/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;

For discussion of the actual algorithm stuff hiding in there, please see the next section.

Alternative Perl Implementiation

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:

This implementation IS FULLY 30W-compliant.
#!/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://irc.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";
}

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:

map { $_ / 2**64 } unpack("Q>Q>", md5(shift))

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:

map { $_ / 2**64 } reverse unpack("QQ", reverse md5(shift));

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.

Ruby Geohasher

This implementation IS FULLY 30W-compliant.

ScottKuma did this as a first excursion into Ruby. Yes, it's long. Yes, it's kinda clunky. However, IT WORKS!

Any changes, suggestions, etc. are happily accepted!


#!/usr/bin/ruby
#geohasher.rb

#Written by ScottKuma

# Can be run without any command-line arguments (and gets the current geohash for the graticule specified in myLat and myLong, below),
# a single argument (the date in YYYY-MM-DD or YYYY/MM/DD format), 
# two arguments (the latitude & longitude "base" coordinates), 
# or three arguments (latitude & longitude "base" coordinates, followed by the date.

require 'net/http'
require 'date'
require 'digest'

myLat = "39"	# Change me to set the desired default graticule's latitude
myLong = "-84"	# Change me to set the desired default graticule's longitude

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
	sum = sum.to_s
	return sum[2..8]
end

t=Time.now
myDate = t.strftime("%Y-%m-%d")

if ARGV.length == 1
	myDate = ARGV[0]
end

if ARGV.length == 2
	myLat = ARGV[0]
	myLong = ARGV[1]
end
	
if ARGV.length == 3
	myLong = ARGV[1]
	myLat = ARGV[0]
	myDate = ARGV[2]
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 = 'irc.peeron.com'
basePath = '/xkcd/map/data/'
fullPath = basePath + urlEncodedDate
dow = ""

Net::HTTP.start(baseURL,80) do |http|
	dow = http.get(fullPath).body
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


Here's one way you could do hex to dec fraction in one line - it's "little", I'm not so sure about "neat"

def hexFracToDecFrac hexFracPart
  hexFracPart.split('').inject((cf=1)-1){|sum,c|sum+ c.to_i(16)/(cf<<=4).to_f}.to_s[2..8]
end

macHasher

This implementation IS FULLY 30W-compliant.
macHasher screenshot

Scottkuma worked feverishly to:

  1. learn Apple OSX Programming and...
  2. put together a 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