Skip to content

Instantly share code, notes, and snippets.

@frederikhermans
Last active October 1, 2015 21:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frederikhermans/e4fd757cc25bcba31fc1 to your computer and use it in GitHub Desktop.
Save frederikhermans/e4fd757cc25bcba31fc1 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
'''Traverses JSON objects to retrieve a secret string.
The JSON objects form a tree structure. The hashes identifying an object's
children are stored in the object's `next` field. Some objects have a
`secret` value, which holds one character. In-order traversal of the object
tree gives the secret string, which when reversed yields the challenge's
solution.
Objects are retrieved from a web server by their hash (see `get_page()`).
Examples of objects:
>>> get_page('34ffe00db65f4576b5add43dda39ff99', session_id)
{"depth": 1,
"id": "34ffe00db65f4576b5add43dda39ff99",
"next": ["81dd32039f2f4bfea3ab35f40c994a0e",
"adad9a3a96464d2ba2977d9863e33794",
"33aaccd7d4fe40019160c49b689c7358"]}
>>> get_page('d9f9a7c4ac0a48959f0de596c91ee90b', session_id)
{"depth": 4,
"id": "d9f9a7c4ac0a48959f0de596c91ee90b",
"secret": "A"}
'''
import requests
import sys
def get_session_id():
req = requests.get('http://challenge.shopcurbside.com/get-session')
return req.text
def get_page(page_hash, session_id):
req = requests.get('http://challenge.shopcurbside.com/{}'.format(page_hash),
headers={'Session': session_id})
return req.json()
def main():
nrequests = 0
stack = list()
stack.append('start')
secrets = list()
status_fmt = '\r#processed: {}, stack size: {}, #secrets: {}, last hash: {}'
while len(stack) > 0:
if nrequests % 10 == 0:
session_id = get_session_id()
page_hash = stack.pop()
response = get_page(page_hash, session_id)
nrequests += 1
# Convert all keys to lower case, since the responses are inconsistent
# in their use of upper- and lower-case.
response = {key.lower(): value for (key, value) in response.iteritems()}
if 'next' in response:
if isinstance(response['next'], basestring):
stack.append(response['next'])
else:
for next_page_hash in response['next']:
stack.append(next_page_hash)
if 'secret' in response:
secrets.append(response['secret'])
print status_fmt.format(nrequests, len(stack), len(secrets), page_hash),
sys.stdout.flush()
secrets = ''.join(secrets)
print '\nSecrets: {}'.format(secrets)
print 'Reversed: {}'.format(secrets[::-1])
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment