2016-12-14 - One-Time Pad
(original .ipynb)test_input_str = "abc" puzzle_input_str = "qzyelonm" from hashlib import md5 def has_triplet(md5_hash): for i, c in enumerate(md5_hash): if i >= len(md5_hash) - 2: break if md5_hash[i+1] == c and md5_hash[i+2] == c: return c return None def plain_hash(input_str): m = md5() to_encode = (input_str).encode() m.update(to_encode) return m.hexdigest() def find_key(input_str, hasher): hashes = [] index = 0 while index <= 1000: hashes.append((index, hasher(input_str + str(index)))) index += 1 keys = 0 while True: prev_index, md5_hash = hashes.pop(0) if triplet := has_triplet(md5_hash): quintuplet = 5 * triplet for _, other_md5_hash in hashes: if quintuplet in other_md5_hash: keys += 1 if keys == 64: return prev_index break hashes.append((index, hasher(input_str + str(index)))) index += 1 return -1 def part_one(input_str): return find_key(input_str, plain_hash) assert 22728 == part_one(test_input_str) print("part one:", part_one(puzzle_input_str))
part one: 15168
def stretched_hash(to_hash): n = 2016 while n >= 0: to_hash = plain_hash(to_hash) n -= 1 return to_hash def part_two(input_str): return find_key(input_str, stretched_hash) assert 22551 == part_two(test_input_str) print("part two:", part_two(puzzle_input_str))
part two: 20864