81 lines
1.5 KiB
Python
81 lines
1.5 KiB
Python
import re
|
|
|
|
re_hgt = re.compile(r"(?P<no>\d+)(?P<type>cm|in)")
|
|
re_hcl = re.compile(r"#[\da-f]{6}")
|
|
re_pid = re.compile(r"^\d{9}$")
|
|
|
|
def parse(data):
|
|
rec = {}
|
|
for line in data.split("\n"):
|
|
if not line:
|
|
yield rec
|
|
rec = {}
|
|
continue
|
|
|
|
pairs = line.split(" ")
|
|
for pair in pairs:
|
|
k, v = pair.split(":", 1)
|
|
rec[k] = v
|
|
|
|
|
|
def load(filename):
|
|
with open(filename, "r", encoding="utf-8") as f:
|
|
s = f.read()
|
|
return parse(s)
|
|
|
|
|
|
def is_valid_1(rec):
|
|
required_fields = set(("byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"))
|
|
fields = set(rec.keys())
|
|
return not (required_fields - fields)
|
|
|
|
|
|
def is_valid_2(rec):
|
|
if not is_valid_1(rec):
|
|
return False
|
|
|
|
if not 1920 <= int(rec["byr"]) <= 2002:
|
|
return False
|
|
|
|
if not 2010 <= int(rec["iyr"]) <= 2020:
|
|
return False
|
|
|
|
if not 2020 <= int(rec["eyr"]) <= 2030:
|
|
return False
|
|
|
|
m = re_hgt.match(rec["hgt"])
|
|
if not m:
|
|
return False
|
|
|
|
if m.group("type") == "cm":
|
|
if not 150 <= int(m.group("no")) <= 193:
|
|
return False
|
|
elif m.group("type") == "in":
|
|
if not 59 <= int(m.group("no")) <= 76:
|
|
return False
|
|
|
|
m = re_hcl.match(rec["hcl"])
|
|
if not m:
|
|
return False
|
|
|
|
if rec["ecl"] not in ("amb", "blu", "brn", "gry", "grn", "hzl", "oth"):
|
|
return False
|
|
|
|
if not re_pid.match(rec["pid"]):
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
if __name__ == "__main__":
|
|
data = load("data.txt")
|
|
n_valid_1 = n_valid_2 = 0
|
|
for x in data:
|
|
if is_valid_1(x):
|
|
n_valid_1 += 1
|
|
|
|
if is_valid_2(x):
|
|
n_valid_2 += 1
|
|
|
|
print(f"Task 1: There are {n_valid_1} valid passports.")
|
|
print(f"Task 2: There are {n_valid_2} valid passports.")
|