10
\$\begingroup\$

XKCD Comic:enter image description here


Goal:

Given a date, the current Dow Opening, and your current coordinates as a rounded integer, produce a "geohash."

Input:

Input through any reasonable means (STDIN, function argument, flag, etc.) the following:

  • The current date. This does necessarily have to be the date of the system's clock, so assume that the input is correct.
  • The most recent Dow Opening (must support at least 2 decimal places)
  • The floor of your current latitude and longitude.

To make input easier, you can input through any reasonable structured format. Here are some examples (you may create your own):

["2005","05","26","10458.68","37",-122"]
2005-05-26,10458.68,37,-122
05-26-05 10458.68 37 -122

Algorithm:

Given your arguments, you must perform the "geohash" algorithm illustrated in the comic. The algorithm is as follows.

  1. Format the date and Dow Opening in this structure: YYYY-MM-DD-DOW. For example, it might look like 2005-05-26-10458.68.
  2. Perform an md5 hash on the above. Remove any spacing or parsing characters, and split it in to two parts. For example, you might have these strings: db9318c2259923d0 and 8b672cb305440f97.
  3. Append each string to 0. and convert to decimal. Using the above strings, we get the following: 0.db9318c2259923d0 and 0.8b672cb305440f97, which is converted to decimal as aproximately 0.8577132677070023444 and 0.5445430695592821056. You must truncate it down the the first 8 characters, producing 0.857713 and 0.544543.
  4. Combine the coordinates given through input and the decimals we just produced: 37 + 0.857713 = 37.857713 and -122 + 0.544543 = -122.544543

Notes:

  • To prevent the code from being unbearably long, you may use a built-in for the md5 hash.
  • Standard loopholes (hardcoding, calling external resource) are forbidden.
\$\endgroup\$
8
  • \$\begingroup\$ May we take negative integers in the format _# instead of -#, i.e. _37 instead of -37? \$\endgroup\$
    – R. Kap
    Jan 15, 2017 at 20:47
  • \$\begingroup\$ Yes. As I stated, input and output can be flexible. \$\endgroup\$ Jan 15, 2017 at 22:55
  • 3
    \$\begingroup\$ Shame about not using built-ins. Python3's module antigravity would have works well hg.python.org/cpython/file/tip/Lib/antigravity.py \$\endgroup\$
    – george
    Jan 16, 2017 at 10:51
  • \$\begingroup\$ @george Did you make that module? \$\endgroup\$ Jan 16, 2017 at 16:27
  • \$\begingroup\$ @JulianLachniet Unfortunately not, never actually had a use for it though \$\endgroup\$
    – george
    Jan 16, 2017 at 16:42

5 Answers 5

5
\$\begingroup\$

Python 2, 129 bytes

import md5
d,q,c=input()
h=md5.new(d+'-'+q).hexdigest()
print map(lambda p,o:o+'.'+`float.fromhex('.'+p)`[2:8],(h[:16],h[16:]),c)

Input is given in the form '2005-05-26','10458.68',('37','-122') (using the example).

Computes the MD5 hash with md5.new().hexdigest(), then performs the necessary transforms. I could save five bytes by using h instead of h[:16], but I'm not sure if that would affect the six most significant digits in the decimal conversion.

Ideone it! (substituting an eval() call for the input())

\$\endgroup\$
2
  • 2
    \$\begingroup\$ BTW in python3 geohash is in the stdlib:from antigravity import geohash \$\endgroup\$
    – pgy
    Jan 23, 2017 at 20:36
  • \$\begingroup\$ float.fromhex can be .0.fromhex \$\endgroup\$
    – pxeger
    Dec 18, 2021 at 1:54
0
\$\begingroup\$

Bash + Coreutils + md5, 98 bytes:

C=`md5 -q -s $1-$2`;C=${C^^};for i in 3 4;{ dc -e 16i[${!i}]n`cut -c1-7<<<.${C:$[16*(i>3)]:16}`p;}

Try It Online!

Uses the built-in md5 command on OSX to generate the MD5 hash. Takes 4 space separated command line arguments in the following format:

YYYY-MM-DD DOW LAT LONG

with negative numbers input and output with a leading underscore (i.e. _122 instead of -122).

Note: Depending on your system, you may need to substitute in echo -n $1-$2|md5sum for md5 -q -s $1-$2 in order for this to work. Doing so brings the byte count up to 103, and is indeed the case in the TIO link.

\$\endgroup\$
0
\$\begingroup\$

Groovy, 198 161 bytes

{d,o,l,L->m=""+MessageDigest.getInstance("MD5").digest((d+"-"+o).bytes).encodeHex()
h={(Double.valueOf("0x0."+it+"p0")+"")[1..7]}
[l+h(m[0..15]),L+h(m[16..31])]}

This is an unnamed closure.

Input
f("2005-05-26","10458.68","37","-122")

Output
[37.857713, -122.544543]

Try it here!

Ungolfed -

import java.security.*
{
    date,open,lat,lon ->
    md = "" + MessageDigest.getInstance("MD5").digest((date+"-"+open).bytes).encodeHex()
    decimal = {(Double.valueOf("0x0."+it+"p0")+"")[1..7]}
    [lat+decimal(md[0..15]),lon+decimal(md[16..31])]  //Implicity returns
}
\$\endgroup\$
4
  • 1
    \$\begingroup\$ tio.run/nexus/groovy btw ;). \$\endgroup\$ Jan 17, 2017 at 20:52
  • 1
    \$\begingroup\$ Also, ` as String` is shorter than .toString() by one byte. \$\endgroup\$ Jan 17, 2017 at 20:54
  • \$\begingroup\$ @carusocomputing Thanks saved a lot by using this instead ""+... \$\endgroup\$ Jan 17, 2017 at 21:37
  • 1
    \$\begingroup\$ Oh jeez! I shoulda seen that as well, haha that took it even further, nice one ☺. \$\endgroup\$ Jan 17, 2017 at 21:50
0
\$\begingroup\$

Javascript (Node, using built-in Crypto), 165 characters

(d,o,l)=>l.map((p,i)=>p+Math.sign(p)*[...require('crypto').createHash('md5').update(d+-o).digest`hex`.slice(z=i*16,z+16)]
.reduce((a,d,i)=>a+parseInt(d,16)*16**~i,0))

Such a verbose API!

JavaScript (using md5 library), 125 characters

(d,o,l)=>l.map((p,i)=>p+Math.sign(p)*[...require('md5')(d+-o).slice(z=i*16,z+16)]
.reduce((a,d,i)=>a+parseInt(d,16)*16**~i,0))

Nothing very golfy here.

In both cases:

f('2005-05-26', 10458.68, [144,-37])

=> [ 144.857713267707, -37.54454306955928 ]
```
\$\endgroup\$
2
  • \$\begingroup\$ Save 3 bytes with d+-o. \$\endgroup\$
    – Shaggy
    Aug 23, 2023 at 8:49
  • \$\begingroup\$ Oh, nice one :) \$\endgroup\$ Aug 23, 2023 at 13:00
0
\$\begingroup\$

Python, 185 bytes

import hashlib as h
x,y,a,n=input().split(',')
b=h.md5((x+'-'+y).encode()).hexdigest()
q=list(map(str,map(float.fromhex,['0x.'+b[:15],'0x.'+b[16:]])))
print(a+q[0][1:8]+','+n+q[1][1:8])

Attempt This Online!

Hashlib stole my bytes, :P.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I can recover those bytes, but you’ll need to pay a £10.00 fee. \$\endgroup\$ Nov 12, 2023 at 13:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.