Sean McLemon | Advent of Code

Home | Czech | Blog | GitHub | Advent Of Code | Notes


2016-12-04 - Security Through Obscurity

(original .ipynb)
from collections import defaultdict
puzzle_input_str = open("puzzle_input/day4.txt").read()
test_input_str = """aaaaa-bbb-z-y-x-123[abxyz]
a-b-c-d-e-f-g-h-987[abcde]
not-a-real-room-404[oarel]
totally-real-room-200[decoy]"""


def most_common_letters(name_parts):
    counts = defaultdict(lambda:0)
    for c in "".join(name_parts):
        counts[c] += 1
        
    return list(sorted(counts.items(), key=lambda x:(-x[1], x[0])))[:5]


def part_one(input_str):
    count = 0
    for line in input_str.split("\n"):
        line_parts = line.split("-")
        encrypted_name_parts = line_parts[:-1]
        sector_and_checksum = line_parts[-1].split("[")
        sector_id = int(sector_and_checksum[0])
        checksum = sector_and_checksum[1].removesuffix("]")
        
        if all(letter in checksum for letter,_ in most_common_letters(encrypted_name_parts)):
            count += sector_id
            
    return count


assert 1514 == part_one(test_input_str)

print("part one:", part_one(puzzle_input_str))
part one: 158835
def rotate(letter, sector_id):
    a = ord("a")
    l = ord(letter) - a
    return chr(a + ((l + sector_id) % 26))    
    

def decrypt(enc_name, sector_id):
    name = []
    for l in enc_name:
        name.append(rotate(l, sector_id))
    
    return "".join(name)


def part_two(input_str):
    count = 0
    for line in input_str.split("\n"):
        line_parts = line.split("-")
        encrypted_name_parts = line_parts[:-1]
        sector_and_checksum = line_parts[-1].split("[")
        sector_id = int(sector_and_checksum[0])
        checksum = sector_and_checksum[1].removesuffix("]")
        
        if all(letter in checksum for letter,_ in most_common_letters(encrypted_name_parts)):
            name = " ".join(decrypt(part, sector_id) for part in encrypted_name_parts)
        
            if "north" in name.lower():
                return sector_id

    raise Exception("something is not quite right")


assert "very encrypted name" == " ".join(decrypt_name(part, 343) for part in ["qzmt","zixmtkozy","ivhz"])

print("part two:", part_two(puzzle_input_str))
part two: 993