aoc-2020/d04/main.py

122 lines
3.1 KiB
Python
Executable File

#! /usr/bin/env python3
import re
def height_validator(x):
match = re.match(r"^([0-9]+)(cm|in)$", x.strip())
if not match:
return False
if match.group(2) == "cm":
return 150 <= int(match.group(1)) <= 193
elif match.group(2) == "in":
return 59 <= int(match.group(1)) <= 76
return False
required_keys = {
"byr": lambda x: 1920 <= int(x) <= 2002,
"iyr": lambda x: 2010 <= int(x) <= 2020,
"eyr": lambda x: 2020 <= int(x) <= 2030,
"hgt": height_validator,
"hcl": lambda x: re.match(r"^#[0-9a-f]{6}$", x.strip()),
"ecl": lambda x: x in ("amb", "blu", "brn", "gry", "grn", "hzl", "oth"),
"pid": lambda x: re.match(r"^[0-9]{9}$", x.strip()),
}
optional_keys = {
"cid": lambda x: True,
}
class Passport(object):
def __init__(self, s):
self.d = {}
for kvp in s.split():
parts = kvp.partition(":")
self.d[parts[0]] = parts[2]
def key_set(self):
return set(self.d.keys())
def is_valid(self, deep=False):
valid = set(required_keys.keys()) <= self.key_set()
if not valid or not deep:
# print(f"Valid: {valid}. Missing: {set(required_keys.keys()) - self.key_set()}")
return valid
for key, validator in required_keys.items():
valid = validator(self.d[key])
if not valid:
# print(f"Invalid value for {key}: {self.d[key]}")
return False
# print("Valid!", self.d)
return valid
def parse_passport(buffer):
s = " ".join(buffer)
return Passport(s)
def part1():
num_valid = 0
total_passports = 0
with open("input.txt") as f:
buffer = []
for line in f:
line = line.strip()
if line == "":
p = parse_passport(buffer)
total_passports += 1
if p.is_valid():
num_valid += 1
buffer = []
else:
buffer.append(line)
# if total_passports == 4:
# break
if buffer:
p = parse_passport(buffer)
total_passports += 1
if p.is_valid():
num_valid += 1
print("Total passports:", total_passports)
print("Total valid passports:", num_valid)
def part2():
num_valid = 0
total_passports = 0
# with open("valid.txt") as f:
# with open("invalid.txt") as f:
with open("input.txt") as f:
buffer = []
for line in f:
line = line.strip()
if line == "":
p = parse_passport(buffer)
total_passports += 1
if p.is_valid(deep=True):
num_valid += 1
buffer = []
else:
buffer.append(line)
# if total_passports == 4:
# break
if buffer:
p = parse_passport(buffer)
total_passports += 1
if p.is_valid(deep=True):
num_valid += 1
print("Total passports:", total_passports)
print("Total valid passports:", num_valid)
if __name__ == "__main__":
part1()
part2()