Advent of Code 2016 solutions https://adventofcode.com/2016/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

14.py 1.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. #!/usr/bin/python3
  2. """Solution for day 14 of Advent of Code 2016.
  3. The actual logic for this solution is contained in the matches lambda, which returns an infinite-length generator
  4. containing all of the matching hashes. The implementation is very basic, calling the hash functions and triple-digit
  5. matcher multiple times for the same inputs. This avoids having to manually keep a second list of hashes to check for
  6. five letter matches.
  7. To avoid the massive slowness that would happen if we recomputed up to 1,000 hashes each step, the hash methods (and
  8. triple-finding method) themselves are cached using functools.lru_cache. The caches can hold 1024 entries, so
  9. comfortably hold the results of the 1,000 hash look-forward.
  10. """
  11. import functools
  12. import hashlib
  13. import itertools
  14. import re
  15. salt = 'cuanljph'
  16. @functools.lru_cache(maxsize=1024)
  17. def md5(index):
  18. return hashlib.md5((salt + str(index)).encode('UTF-8')).hexdigest()
  19. @functools.lru_cache(maxsize=1024)
  20. def stretched(index):
  21. key = salt + str(index)
  22. for _ in range(2017): key = hashlib.md5(key.encode('UTF-8')).hexdigest()
  23. return key
  24. @functools.lru_cache(maxsize=1024)
  25. def trip(index, fn):
  26. return tripmatcher.search(fn(index))
  27. tripmatcher = re.compile(r'(.)\1{2}')
  28. matches = lambda fn: ((i, fn(i)) for i in itertools.count()
  29. if trip(i, fn) and any(trip(i, fn).group(1) * 5 in fn(n)
  30. for n in range(i + 1, i + 1000)))
  31. print("Part one: %s" % next(itertools.islice(matches(md5), 63, 64))[0])
  32. print("Part two: %s" % next(itertools.islice(matches(stretched), 63, 64))[0])