Last active
October 1, 2015 21:10
-
-
Save frederikhermans/e4fd757cc25bcba31fc1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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