#!/usr/bin/python3

import loader
import re

inp = loader.string_list("input_day14")

mask = ""
mem = {}
for line in inp:
    if re.match('^mask', line):
        mask = line.split(" = ")[1]
        continue
    match = re.match('mem\[([0-9]+)] = ([0-9]+)', line)
    mem_addr = int(match.group(1))
    raw_value = int(match.group(2))
    raw_value_binary_string = "{:036b}".format(raw_value)
    masked_value_binary_string = ""
    for i in range(36):
        if mask[i] != "X":
            masked_value_binary_string += mask[i]
        else:
            masked_value_binary_string += raw_value_binary_string[i]
    masked_value_int = int(masked_value_binary_string, 2)
    mem[mem_addr] = masked_value_int

print(sum([mem[key] for key in mem.keys()]))
#!/usr/bin/python3

import loader
import logging
import re

#logging.basicConfig(level=logging.DEBUG)

valid_passport_required_keys = [
    "byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"
]
#"cid"]

passport_string_list = loader.string_list("input_day4")

all_passports = []
current_passport = {}
for line in passport_string_list:
    logging.debug(f"Got line: {line}")
    if line == "":
        logging.debug(
            f"Found blank line. Added {current_passport} to all_passports")
        all_passports.append(current_passport)
        current_passport = {}
        continue
    else:
        field_data = line.split()
        for field in field_data:
            split_field = field.split(":")
            current_passport[split_field[0]] = split_field[1]
#!/usr/bin/python3

import loader

boarding_passes = loader.string_list("input_day5")


def convert_pass_to_row_col(bpass):
    row = int(bpass[0:7].replace("F", "0").replace("B", "1"), 2)
    col = int(bpass[7:].replace("L", "0").replace("R", "1"), 2)
    return {"row": row, "col": col, "id": row * 8 + col}


seat_ids = [convert_pass_to_row_col(bpass)["id"] for bpass in boarding_passes]
min_id = min(seat_ids)
max_id = max(seat_ids)

for seat_id in range(min_id, max_id):
    if seat_id not in seat_ids:
        print(seat_id)
        exit(0)
#!/usr/bin/python3

import loader

inp = loader.string_list("input_day21")

foods = []
for raw_food_data in inp:
    ingredients = raw_food_data.split(" (contains ")[0].split(" ")
    allergens = raw_food_data.split(" (contains ")[1].rstrip(")").split(", ")
    food = {"i": ingredients, "a": allergens}
    foods.append(food)

all_ingredients = list()
all_allergens = list()
for food in foods:
    all_ingredients += food["i"]
    all_allergens += food["a"]

all_ingredients = set(all_ingredients)
all_allergens = set(all_allergens)

ingredients_x_allergens = set()  # represents possible food-allergen pairings
for i in all_ingredients:
    for a in all_allergens:
        ingredients_x_allergens.add((i, a))

for food in foods:
    for food_allergen in food["a"]:
        impossible_ingredients = all_ingredients - set(food["i"])
        for impossible_ingredient in impossible_ingredients:
        "letter": matches.group(3),
        "password": matches.group(4)
    }


def is_password_valid(password_dict):
    """
    Mandatory arguments:
    * password_dict - a password dictionary a returned by parse_password_line

    Returns True if the password is valid and False if it is not.
    """
    letter_count = sum([
        1 for letter in password_dict["password"]
        if letter == password_dict["letter"]
    ])
    if password_dict["minimum"] <= letter_count <= password_dict["maximum"]:
        return True
    else:
        return False


password_lines = loader.string_list("input_day2")
password_dicts = [
    parse_password_line(password_line) for password_line in password_lines
]
valid_password_count = sum([
    1 for password_dict in password_dicts if is_password_valid(password_dict)
])
print(valid_password_count)